Document service tokens in AR auth ADR-020
What this changes
Adds a ## Service-to-service authentication section to ADR-020: the shared two-layer pattern, then one subsection per edge.
- Artifact Registry to the relationships API (
iam-data-access) carries both layers — a service token ingitlab-iam-data-access-tokenplus the end-user JWT. Covers token rotation, the opaque rejection behavior, the health-RPC exemption, which token flows on the data path versus the admin and UI flows, and that each side verifies the JWT independently rather than trusting the other's check. - GitLab Rails to the Artifact Registry internal API is not user-initiated, so there is no identity for the second layer to carry and the service token alone authenticates the caller.
The target-state direction (mutual TLS with workload identity, caller identity in a URT) goes to "Future work / open debates", since neither is decided.
Extends ADR-020's existing authentication-flow diagram with the relationships API call, showing both credentials on the wire (steps 5-6). Updates the ADR-021 authorization-flow diagram the same way, and links to the new ADR-020 section.
Also corrects four claims in ADR-020 about the token payload GitLab Rails issues, found while writing the new section.
Why
No ADR documented the service token, so every sequence diagram showed only JWTs on that call. A reader planning an integration would use the wrong credentials. This was agreed in gitlab-org/ops/artifact-registry#255 (closed), which concluded a short addition to ADR-020 was enough — no rewrite needed.
Drift fixes — please review
Checked against ee/lib/authn/token_exchange/token_issuer.rb on gitlab-org/gitlab master:
audcarries two values, not one: the requested audience (gitlab-artifact-registry) plusgitlab-iam-data-access, which Rails appends to every token. This is what lets Artifact Registry forward the token to the relationships API.- Added the
verclaim (payload schema version, currently1). IAM's verifier rejects a token without it. - Replaced
gitlab_realmandgitlab_organization_id, which do not exist, with the nestedgitlabobject Rails actually issues:origin,origin_id(an organization UUID),local_id,identity_kind,organization_role.organization_roleis documented as the bootstrapping fallback, tying to ADR-021's R6 requirement. - "Token duration" said a client "may request a shorter lifetime"; the endpoint accepts 1 second to a 12-hour cap, so a client can request longer than the 5-minute default too. "Enablement enforcement" now cites
gitlab.origin_idinstead ofgitlab_organization_id.
Sources: https://gitlab.com/gitlab-org/auth/iam/-/blob/main/docs/service-access.md and https://gitlab.com/gitlab-org/auth/iam/-/blob/main/docs/relationships-api.md
vale reports no issues on ADR-020; markdownlint reports no issues on either file.
Not in scope
The interface agreement at agreements/auth.md has the same omission in its interim-state sequence diagram; a reviewer may want that as a separate MR.
pkg/userauth never refreshes its JWKS, so ADR-020's claim that keys are "refreshed periodically" with brief stale-key retention is untrue today. That is a code gap, filed as gitlab-org/gitlab#616174, and deliberately left out of this MR.