Adding custom roles to JWT on login with Google Identity Platform
Google Identity Platform is a pretty cool managed service to hold the identities of your users. It provides multi-tenancy and allows to unify the user entity across various authentication provider. But the functionality is very much focused on managing the identity of a user.
Sometimes your applications will need more information to facilitate authorisation (AuthZ) for the actions it provides. So you might want to add some role-based access control (RBAC) to your application. But sometimes using roles isn’t the best approach and you might need an owner approach, or want to allow users from a certain country to see certain data items, an attribute-based access control (ABAC) might be a better choice. And sometimes you just want to go with policy-based access control (PBAC) mechanism. I’m quite happy that Identity Platform doesn’t try to provide a solution for this problem, since it would always be limiting towards one of the other options.
But Identity Platform provides a nifty approach that allows you to add custom claims to a JWT, using Cloud Functions. This is obviously following an open-closed design approach, with a clear Extension mechanism. You can find the documentation for that here.
The gist is as follows, simply go to your Identity Platform setup and select Settings->Triggers. You can select here Cloud Functions that are triggered when a user is created in Identity Platform or when a user is signing in. The Cloud Function needs to be publicly accessible, but the Identity Platform SDK will check authentication of each request. If your using javascript you will also need to add the ”gcip-cloud-functions”: “0.0.1”
dependency to package.json
.
The beforeCreate trigger allows to add custom claims to a user before she is added to Identity Platforms user repository. This is a great feature for adding information about the user, that you want to have accessible in the token, that is changing seldom. You can also change those claims afterwards via the admin SDK (link). Here is an example function that adds a custom claim to our user on signup.
gcipCloudFunctions = require('gcip-cloud-functions');const authClient = new gcipCloudFunctions.Auth();exports.beforeCreate = authClient.functions().beforeCreateHandler((user, context) => {
return {
customClaims: {
"test_claim": "Awesome!"
}
};
});
The beforeSignIn triggers allows to add claims to each sign-in of the user. This is very useful if you have for example roles in a database table and want to add which roles the user can access. Here is an example function that adds another custom claim to the token:
gcipCloudFunctions = require('gcip-cloud-functions');const authClient = new gcipCloudFunctions.Auth();exports.beforeSignIn = authClient.functions().beforeSignInHandler((user, context) => {
return {
customClaims: {
"signInClaim": "Awesome Too!!!"
}
};
});
There is one thing to keep in mind for both options, your function needs to respond within 7 seconds. That can be forever for some use cases, but you probably want to keep an eye on, what information you are loading. Especially during sign-in this could result in a bad user experience if your are loading a lot of data.