Access the authorize request in the Complement Token flow (Actions V1)
Hello Zitadel crew π
We have a need to pass arbitrary parameters in the
/authorize
request and then run some API request inside an action using those parameters, to finally complement the token claims. E.g.:
1- User attempts to login and the frontend passes the arbitrary company_id=42
query parameter in the /authorize
request
2- On an action inside Zitadel, we read that arbitrary parameter and use that to make an internal request to our backend API (to e.g.: check if user really has access to company_id=42
3- If response of that internal request is successful, the Zitadel action complements the access token with a new claim (e.g.: "company_id": 42
)
Looking through the documentation I didn't find a way of doing that using Action V1 - is it possible?
Note: we're on Zitadel 2.67.3 (default version from Helm charts) and using only Actions V1 for now5 Replies
I was able to workaround that by using two separate actions (one in a Post Authentication, and one in Complement Token)
- in the authorize request, pass state encoded with the arbitrary data I want, e.g.:
state=company_id:42;subdomain:mycompany;foo:bar
- in an action in External Authentication
or Internal Authentication
flow, parse the state (from ctx.v1.authRequest.transferState
), then add company_id
to the user metadata, e.g.:
- in an action in Complement Token
flow (pre access token creation):
This is not great though... If the user is logged into multiple devices the state could leak between them, e.g.:
- login using my computer passing company_id=1 - and that is successfuly added as a claim in the token
- login using my phone passing company_id=42
- when my computer generates a new token (using the refresh_token), it would NOT go through the Post Authentication Flow
and read directly from the user metadata, so it would add company_id=42 to the new token claims - regardless of the previous company_id my computer used to authenticate
So, thinking about it, I guess if I want to pass arbitrary data into my token claims, the correct approach would be passing through the /token
request - NOT the /authorize
request, right? That way we theoretically wouldn't have to store any "intermediate" state
I don't think this is possible in Actions V1 at all π€
Perhaps it is possible in Actions V2? (set custom claims based on parameters sent to /token
request)Good morning @bawsky I'm tagging one of our engineers @Rajat to help on this front and share his insights. Thanks for your patience!
Fantastic, thanks a lot @Jim Morrison and @Rajat π
Hope we can get a way to overcome this - it'd be very helpful to have a more flexible way to complement tokens
For now the workaround we've took is something on the lines of:
- add support for a new custom header, e.g.:
x-company-id: 42
- during every request, we validate if the user really have access to that company set on their headers
(note: this is a bit tricky in the case of impersonating other users from other companies - something we also support - in impersonation scenarios we have to validate whether the original user has access to impersonate the impersonated user ON <x-company-id>)
Instead of that workaround, we'd like it if it was possible to submit a company_id on the /token
request and use it to change the structure of our jwts (after validating in our backend via an API call inside actions) to something like:
regarding impersonation (via token exchange), ideallly we also would like the possibily to, inside actions, make a request to validate if the user can impersonate some speciific user on some specific company, and if yes, generate an impersonate token like:
(I must say: I really like token exchange beta feature! hope it gets more love and traction π )hey @bawsky thanks for the context and I will read it and get back to you
hey @bawsky with Actions V1 itβs not possible to pass arbitrary params from
/authorize
into the token claims directly without workaround.
Actions V2 supports executing during the Token Complement Flow (preβtoken creation) where you can use setClaim()
to inject the company_id (or impersonation id) into the token. You might wanna read about it here.So is it possible to access arbitrary params/headers in actions V2? More specifically, in Action V2, can I either:
- access arbitrary params/headers in
/authorize
request, then re-access those during the /token
request to complement the token - being ensured that the data I'm accessing corresponds to my current OIDC session (i.e.: arbitrary data from an /authorize
request can be tied to the current OIDC session, when accessing it in the complement token flow)?
- access arbitrary params/headers in /token
request?
Either would work for me - just want to better understand how Actions V2 can solve the problem
Also, just want to confirm in regards to impersonation:
Is it correct then that I am able to access act.sub
inside the Token Complement flow (or equivalent) in Actions V2?
The reason of my surprise is that, from my own testing, in Actions V1 (Zitadel v2.67.2) act.sub
(the actor/original user id) is simply this not visible inside the Complement Token flow