Manuel DesdinM
ZITADEL8mo ago
48 replies
Manuel Desdin

Help needed: Custom claim not appearing in token/userinfo from Complement Token Action

I'm working on integrating Zitadel with pgAdmin using OAuth2. My goal is to include a custom
roles
claim in the ID token and userinfo response, so I can leverage
OAUTH2_ADDITIONAL_CLAIMS
in pgAdmin for access control.

I've created a Complement Token script to flatten the
grants
structure and set a custom
roles
claim. However, neither this dynamic claim nor even a simple static claim (for testing) appears in the ID token or userinfo output.

For example, even this simplified test script doesn't work:
function flatRoles(ctx, api) {
  api.v1.claims.setClaim("test", "hello");
}


I've ensured:
- The script is enabled and attached to the correct Trigger: Pre Userinfo Creation, Pre Access Token Creation
- The user has valid roles
- I'm inspecting
userinfo
and the
token
in pgAdmin logs

Still, only the default Zitadel claims are returned. My custom claim (
test
or
roles
) is never visible.

❓ Am I missing something for Complement Token Actions to take effect? Do I need to adjust scopes or project settings to expose custom claims?

Here's a screenshot of my action configuration and a copy of the script. Any guidance would be much appreciated!

Thanks in advance!

My Script:
/**
 * Flatten roles into a top-level "roles" claim.
 * Format: "roles": ["role1", "role2", ...]
 *
 * Flow: Complement Token
 * Triggers: Pre Userinfo Creation, Pre Access Token Creation
 *
 * @param ctx
 * @param api
 */
function flatRoles(ctx, api) {
  const userGrants = ctx.v1.user?.grants?.grants;

  if (!userGrants || userGrants.length === 0) {
    return;
  }

  const flatRoles = [];

  userGrants.forEach(grant => {
    if (grant.roles && grant.roles.length > 0) {
      grant.roles.forEach(role => flatRoles.push(role));
    }
  });

  if (flatRoles.length > 0) {
    api.v1.claims.setClaim("roles", flatRoles);
  }
}
Screenshot_2025-07-20_at_09.39.38.png
Was this page helpful?