- Newest
- Most votes
- Most comments
Yes, you can use the Cognito "pre token generation lambda trigger" in combination with client metadata to add custom claims to identity or access tokens. However, you're correct that when the tokens are refreshed, the client metadata is no longer available, which makes it challenging to forward the custom claims to the new tokens. One potential solution is to store the custom claims as user attributes in the Cognito User Pool when you first issue the tokens. Then, during the token refresh process, the pre-token generation Lambda trigger can retrieve these custom claims from the user attributes and add them to the new tokens.
Here's a high-level overview of the steps:
- When a user first authenticates and you issue the initial tokens, use the pre-token generation Lambda trigger to add the custom claims based on the client metadata.
- In the same pre-token generation Lambda trigger, store these custom claims as user attributes in the Cognito User Pool using the
adminUpdateUserAttributesAPI. - During the token refresh process, the pre-token generation Lambda trigger is invoked again. In this trigger, you can retrieve the custom claims from the user attributes using the
adminGetUserAPI. - Add the retrieved custom claims to the new tokens being issued during the refresh process.
Here's some sample code in Node.js to illustrate this approach:
// Initial token issuance
exports.handler = async (event) => {
if (event.request.clientMetadata) {
const customClaims = getCustomClaimsFromClientMetadata(event.request.clientMetadata);
// Add custom claims to tokens
event.response = {
...event.response,
claimsOverrideDetails: {
claimsToAddOrOverride: customClaims
}
};
// Store custom claims as user attributes
const userAttributes = Object.entries(customClaims).map(([key, value]) => ({
Name: key,
Value: value
}));
await adminUpdateUserAttributes(event.userName, userAttributes);
}
return event;
};
// Token refresh
exports.handler = async (event) => {
const user = await adminGetUser(event.userName);
const customClaims = user.UserAttributes.reduce((claims, attr) => {
claims[attr.Name] = attr.Value;
return claims;
}, {});
event.response = {
...event.response,
claimsOverrideDetails: {
claimsToAddOrOverride: customClaims
}
};
return event;
};
This approach has a few caveats:
- It assumes that the custom claims can be stored as user attributes (within the attribute name and value limits).
- It requires additional logic to handle user attribute updates if the custom claims change over time.
- It may not work if the user is deleted and recreated, as the user attributes would be lost.
Another potential solution is to store the client metadata or a reference to it in a separate data store (like DynamoDB) during the initial token issuance. Then, during the refresh process, you can retrieve this metadata from the data store and use it to add the custom claims to the new tokens. Ultimately, the best approach depends on your specific requirements and the nature of the custom claims you're adding to the tokens.
Useful resources:
answered 2 years ago
Relevant content
asked 3 years ago
- AWS OFFICIALUpdated 4 months ago
- AWS OFFICIALUpdated 3 years ago

Thank you for your answer but the main issue is storing claims (or information used to derive claims) in user attributes (or in a third party db) assumes the claims only depend on the user account and not on the authentication context.
Imagine that on device A the user logs in in a given way and with device B the user logs in in a different way. Each token set (actually token trees once you start refreshing) would have a distinct set of claims. This cannot be handled by storing information at account level.
What would help would be to have something to tag these trees, have context dependent information being forwarded across refresh calls.
I agree with @pmezard, not being able to retain these claims through token refreshes, seems like functionality that should be there, but is unfortunately not present. I hope this changes soon!