Ralph
Ralph4mo ago

Assistance requested with adding custom claim with Actions V2

Use-case: we are fully integrating Zitadel with all our products, replacing the build-in custom IDP of our current platform. I'm writing this post because I am struggling to add a custom claim with Actions V2 when our users are logging in to a specific solution of ours. Environment: Zitadel Cloud Version: v3.2.2 Stack: we are using Xano for our back-end and another software solution where our customers can login to. What you expected to happen: The OIDC part is already working, but I am struggling with Actions V2 to add another custom claim, and I would like to request some guidance here. Please note, I am a low-code/no-code kind of guy, and not a full-fledged developer, so please bear with me 😉 What I have done so far is creating a POST endpoint in Xano which is going to be used as the Target in Zitadel. It's quite simple; it's just looking up a specific variable for that user in our Xano database and returning it as follows:
{
"claims": {
"custom_claim": "claim_value"
}
}
{
"claims": {
"custom_claim": "claim_value"
}
}
For the endpoint I have enabled external access and copied the endpoint URL to the Zitadel target. That seemed easy enough, assuming I've done it correctly. However, when setting op the Zitadel Action I am completely lost. I have no clue if I need to run this on Request or Response, which service and method to use (I have so far tried the v1.AuthService and v2.OIDCService with all methods), and how to tell Zitadel to specifically only run this action during the OIDC authentication of this specific software solution. Very sporadically I see some requests coming in in Xano, but they only use the ListMyProjectOrgs or the ListMyZitadelPermissions methods. Kindly asking for assistance here. Please let me know if you would require some more information from my side. I'm also more than happy to hop on a call if that's easier. Thank you! Kind regards, Ralph
5 Replies
Rajat
Rajat4mo ago
hey @Ralph thanks for your question, I will look into this and get back to you.
Ralph
RalphOP3mo ago
Hi Rajat, thank you! Hi @Rajat , a little bit more information: So, in the meantime I'm using Actions V1 temporarily, until I get V2 working. This is the action I created:
function addl_email_claim(ctx, api) {
// return if addl_email already set
if (ctx.v1.claims && ctx.v1.claims.addl_email) {
return;
}

const metadata = ctx.v1.user.getMetadata();

// assign addl_email from metadata, if present
metadata.metadata.forEach(({ key, value: addl_email }) => {
if (key === 'addl_email' && addl_email) {
api.v1.claims.setClaim('addl_email', addl_email)
}
});
}
function addl_email_claim(ctx, api) {
// return if addl_email already set
if (ctx.v1.claims && ctx.v1.claims.addl_email) {
return;
}

const metadata = ctx.v1.user.getMetadata();

// assign addl_email from metadata, if present
metadata.metadata.forEach(({ key, value: addl_email }) => {
if (key === 'addl_email' && addl_email) {
api.v1.claims.setClaim('addl_email', addl_email)
}
});
}
The authentication flow trigger I'm using is of "Complement Token" type, on the "Pre Userinfo creation" and "Pre access token creation". This is working perfectly and I'm happy with the result. Now, I'm looking for some assistance to convert this into an Action V2. Hope you're able to assist, thanks in advance.
Rajat
Rajat3mo ago
hi @Ralph apologies for the wait and I am glad you figured out a workaround, infact this workaround might also help another user who also has a similar problem statement. cc @bawsky this might help 🙂
bawsky
bawsky3mo ago
Thanks for quoting me @Rajat - this is indeed very similar to my inquiry 🙂 I'm not sure though if @Ralph solution would work for me though - in my case I am definitely worried about one session's "state" falling to another session's "state" So e.g.: if the token on my pc has customClaim: "a" and the token on my phone has customClaim: "b", I wouldn't like to have them mixing up when the token is re-generated without going through authentication again @Rajat That said, got a question (haven't tried that myself yet): when I re-generate a token via refresh_token grant, would that: - trigger Pre access token creation on Complement Token flow? - if yes, would ctx.v1.claims.customClaim (from the original, pre-refresh, access token) be available? @Rajat is there a big techinical limitation stopping us from accessing arbitrary headers/params sent in the token request? Something in the lines of:
// in "Complement Token" flow, "Pre access token creation" trigger
ctx.v1.tokenRequest.headers

// which would return an object with all the headers used in the "/oauth/v2/token" request
// in "Complement Token" flow, "Pre access token creation" trigger
ctx.v1.tokenRequest.headers

// which would return an object with all the headers used in the "/oauth/v2/token" request
The above sounds like it would solve custom claims troubles for quite a few people (from what I've seen here in Discord) Moreover, setting a metadata in the /authorize request and accessing in the /token request sounds like a massive workaround since there's no way to correlate the metadata with the current session (if there was something like an ephemeral "session metadata", which would only be available on the current OIDC session, then I guess this wouldn't be an issue) btw, sorry @Ralph to hijack your post! 🙇‍♂️ In case you're curious, @Rajat and I are discussing about this other post I created, which has a very similar inquiry as yours https://discord.com/channels/927474939156643850/1379933999148830782
Ralph
RalphOP3mo ago
Hi both, @bawsky no worries about the hijack, the more people the merrier 😉 But @Rajat , please note that the V1 Action I created is a temporary workaround since Zitadel states the V1 Actions will be discontinued in the future and replaced by the V2 Actions. Therefore, I'm still very curious to learn how to convert the current V1 Action to V2. Is it possible you provide me with an example V2 Action that achieves the same as the current V1? But, instead of referring to the Zitadel user metadata, it must return the custom_claim from my Xano endpoint (ref. original post). Cheers!

Did you find this page helpful?