Draft: TokenIssuer approach
POC from our conversation in #605019 (comment 3628872793)
What does this MR do and why?
Implements the interim TokenIssuer approach agreed in #605019 (closed) for replacing Duo Workflow's direct Doorkeeper OAuth token creation with short-lived RS256 JWTs.
Duo Workflows currently mints OAuth tokens by writing rows directly into oauth_access_tokens via Doorkeeper, which will break on Protocells/Cells where OAuth moves to the IAM service. This POC reuses and extends the JWT-based token exchange built for Artifact Registry.
Changes
-
Extended
Authn::TokenExchange::TokenIssuerwith:- Optional
gitlab.identitiesclaim (composite identity: human user embedded in JWT instead ofuser:<id>Doorkeeper scope) gitlab.scopesclaim (OAuth-style scopes for Rails enforcement without DB lookup)RAILS_AUDIENCEconstant (gitlab-rails) alongside existing AR audiencescopes:andidentities:constructor params; longer TTLs supported
- Optional
-
New
Authn::Tokens::DuoWorkflowToken(ee/lib/authn/tokens/duo_workflow_token.rb):- Verifies RS256 JWTs against the CloudConnector::Keys JWKS
- Validates aud/iss/exp/nbf
- Resolves
sub(GlobalID) to user/service-account - Exposes
#scopesforvalidate_and_save_access_token! - Exposes
#identity_user/#scope_userfor composite identity fromgitlab.identities - Gated by
duo_workflow_use_token_issuerfeature flag
-
Auth wiring (EE extensions):
EE::Gitlab::Auth::AuthFinders#find_oauth_access_token: tries DuoWorkflowToken before IamOauthToken/DoorkeeperEE::Gitlab::Auth#oauth_access_token_check: also accepts DuoWorkflowToken for git-over-HTTPS- Composite identity linking reuses existing
Identity.link_from_oauth_tokenpath (DuoWorkflowToken#scope_user delegates to #identity_user)
-
Service changes (behind
duo_workflow_use_token_issuerflag, default off):CreateCompositeOauthAccessTokenService: JWT path (sub=service account, identities=[human user], ttl=1h); skipsensure_oauth_application!CreateOauthAccessTokenService: JWT path (sub=current_user, no identities, ttl=2h); skips DB load-balancer stickingWorkflowContextGenerationService#already_scoped_for_ai_workflows?: handles DuoWorkflowToken by checkingidentity_userinstead ofuser:<id>scopeFlowTriggers::RunService#can_use_composite_identity?: JWT path doesn't require OAuth application
-
Feature flag:
duo_workflow_use_token_issuer(wip, default off)
Amazon Q (ee/lib/gitlab/llm/q_ai/client.rb) is explicitly out of scope.
References
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist.