Skip to Content

mutatingPostAuthentication Hook Configuration

Published: 2022-05-23

The mutatingPostAuthentication hook is called right after the user authentication flow is complete and before the user is saved as a secure cookie. This means, it's still possible, intentionally so, to deny the user to be authenticated at all. Even though they might complete the authentication flow with the external Identity Provider, we can still stop the user from authenticating with our WunderGraph application.

This is essential, because we might be building an internal application which should only grant access to our own employees. By implementing the mutatingPostAuthentication hook, it's possible to write arbitrary NodeJS (TypeScript) code to determine if the user should be allowed and.

Additionally, to just allowing the user in, we can also assign the user roles, like "admin", "guest" or "user". By assigning one or more roles to the user, we're able to use the @rbac directive to implement role based access controls for operations.

So, the mutatingPostAuthentication hook is responsible for assigning roles to the user. The @rbac directive defines, what roles will grant or deny access to Operations.

On top of simply accessing the user object, it's also possible to use the access token and id token and enrich the user object with custom claims and attributes. These can later be used to implement attribute based access controls or evaluate based on custom claims if a user is allowed to make a certain operation.

Let's look at an annotated hooks configuration.

// wundergraph.hooks.ts
// this is our in memory database of super admins
const superAdmins = [
"jens@wundergraph.com"
]
const wunderGraphHooks = configureWunderGraphHooks({
authentication: {
// implement the following hook to take ownership of the authentication flow
mutatingPostAuthentication: async (user, accessToken, idToken) => {
// OpenID Connect Identity Providers return a boolean value that indicated if the user has verified their email
// In this scenario, we're denying the completion of the authentication flow if the user has not verified their email
if (user.email_verified !== true) {
return {
status: "deny",
message: "email not verified"
}
}
// We check our in memory database if if contains the users email
// If the users email is found, we grant the roles "user" and "superadmin"
if (superAdmins.find(s => s === user.email) !== undefined) {
return {
status: "ok",
user: {
...user,
roles: [
"user",
"superadmin"
],
custom_attributes: [
"jens:read",
],
custom_claims: {
realm_access: accessToken.realm_access,
resource_access: accessToken.resource_access,
jens: accessToken.jens,
}
}
}
}
// otherwise, we just grant the role "user"
return {
status: "ok",
user: {
...user,
roles: [
"user"
]
}
}
}
},
});
export default wunderGraphHooks;

This is a simple example to demonstrate how easy it is to assign roles to a user. Keep in mind that you're allowed to put any logic into the hooks. You can talk to a database or external system to determine the roles of a user.

Next Steps#

In order to implement role based access controls for Operations, you have to use the @rbac directive.

If you're looking to define your own custom roles, have a look at the authorization configuration.


Product

Comparisons

Subscribe to our newsletter!

Stay informed when great things happen! Get the latest news about APIs, GraphQL and more straight into your mailbox.

© 2022 WunderGraph