Manuel Desdin
Manuel Desdin2mo ago

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); } }
No description
31 Replies
Manuel Desdin
Manuel DesdinOP2mo ago
no one?
Rajat
Rajat2mo ago
hey @Manuel Desdin thanks for your question and welcome to the server, I will look into this and will get back to you! 🙂
karripallo
karripallo2mo ago
Came here because of the same issue. Tried to add static claim, even throwing in the script and nothing happens on login.
Rajat
Rajat2mo ago
hey @Manuel Desdin good morning, can you pls check if you have Assert Roles on Authentication checked?.
ZITADEL • Identity infrastructure, simplified for you
ZITADEL • Identity infrastructure, simplified for you
This article demonstrates how to add custom claims to your tokens through customizable actions.
Manuel Desdin
Manuel DesdinOP2mo ago
hi rajat, thanks for taking care, yes, yes, i see the claims listed in the response, but none of the custom ones
Manuel Desdin
Manuel DesdinOP2mo ago
this is how it looks in my case
No description
Rajat
Rajat2mo ago
hey @Manuel Desdin what scopes are you passing, on your OAuth2 side?
Manuel Desdin
Manuel DesdinOP2mo ago
you mean here?
No description
Manuel Desdin
Manuel DesdinOP2mo ago
i have also tested it by selecting all options, to include them everywhere, right now it is only part of the userinfo
Rajat
Rajat2mo ago
hey @Manuel Desdin I read a bit more, because you are running with pgAdmin using OAuth2, you must be having a this config file? Can you pls check for scopes you passed there?
Manuel Desdin
Manuel DesdinOP2mo ago
based on my observations seems like pgadmin has to request a specific claim for the custom claims to be included. yes, sure, give me a second to retrieve this 'OAUTH2_SCOPE':'openid email profile' and 'OAUTH2_ADDITIONAL_CLAIMS':{'roles':['pgadmin-administrator','pgadmin-user']} if i don't set OAUTH2_ADDITIONAL_CLAIMS then no claim is requested
Rajat
Rajat2mo ago
try appending urn:zitadel:iam:org:project:roles in the oauth2 scope 'OAUTH2_SCOPE': 'openid email profile urn:zitadel:iam:org:project:roles
Manuel Desdin
Manuel DesdinOP2mo ago
oki, this is a good idea, i will do now and see nothing yet, trying few things i get the claims included in urn:zitadel:iam:org:project:roles, but not the custom ones and this was so before, so far nothing has changed
karripallo
karripallo2mo ago
If it helps, I figured out the action name must match exactly the function name in the script. @Manuel Desdin In your case try changing "Flatten roles into a claim" to "flatRoles"
Rajat
Rajat2mo ago
oh yes 😅
Manuel Desdin
Manuel DesdinOP2mo ago
wow, ok, let me try it
karripallo
karripallo2mo ago
I had a test for adding static claim like: function addClaim(), I renamed the action to addClaim and boom, got the claim on frontend I don't think it was mentioned in the docs
Rajat
Rajat2mo ago
hey @karripallo good catch but its mentioned on the action docs on the intro
Manuel Desdin
Manuel DesdinOP2mo ago
i must be missing something more, still not listed, but let me first do some more debugging to be sure and i started to log inside the action too, will check this as well
karripallo
karripallo2mo ago
True. Somehow I missed it yesterday
Rajat
Rajat2mo ago
its easy to miss but then its fun to play around 😄
No description
Manuel Desdin
Manuel DesdinOP2mo ago
could it be this error? action run failed: ReferenceError: api is not defined at <eval>:12:1(6) sorry, this one is my bad i was adding stuff to it out of desperation line 12 has this: api.v1.claims.setClaim("myclaim", "testing") and this is outside of the function and this was it i am very sorry, it was just a wrong naming for the action thanks a lot!!! @Rajat @karripallo
Rajat
Rajat2mo ago
hey @Manuel Desdin can I see your scipt again, just to make sure if yoiu missed soemthing
Manuel Desdin
Manuel DesdinOP2mo ago
a second /** * 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 */ let logger = require("zitadel/log"); function flatRoles(ctx, api) { const userGrants = ctx.v1.user?.grants?.grants; if (!userGrants || userGrants.length === 0) { logger.log("flatRoles: No user grants."); 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); } }
Rajat
Rajat2mo ago
looks okay! anything on your logs?
Manuel Desdin
Manuel DesdinOP2mo ago
all ok on logs side! and working as expected
karripallo
karripallo2mo ago
Great success ✨
Rajat Singh
Rajat Singh2mo ago
Oh so it worked 😄
Manuel Desdin
Manuel DesdinOP2mo ago
yes, yes, the problem was only the wrong action naming
Rajat Singh
Rajat Singh2mo ago
Oh wow ahaha! But happy that it worked!
Gigi the Giraffe (Zitadel)
🎉 Looks like you just helped out another community member! Thanks for being so helpful <@833999961363316746>! You're now one step closer to leveling up—keep up the amazing peer support! 🚀

Did you find this page helpful?