Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Identity provider setup

The registry can run with no identity provider at all — registry API tokens and a root token are enough to administer it. Configuring one buys two things: people sign in instead of pasting tokens, and deployments authenticate with credentials the registry never stores.

Configuration

export TAR_OIDC_ISSUER=https://sso.example.org/realms/main
export TAR_OIDC_CLIENT_ID=tar-ui

That is the minimum for browser sign-in. Everything else has a working default:

Default
TAR_OIDC_ISSUERThe human issuer. The only issuer allowed to assert roles.
TAR_OIDC_CLIENT_IDThe public client the browser uses.
TAR_OIDC_CLIENT_SECRETOnly if your client is confidential.
TAR_OIDC_AUDIENCETAR_BASE_IRIThe aud a token must carry.
TAR_OIDC_REQUIRE_AUDIENCEtrueWhether aud is required rather than merely checked when present.
TAR_OIDC_ROLES_CLAIMrealm_access.rolesWhere human roles are read from.
TAR_OIDC_CLIENT_CLAIMazpWhere a workload's client id is read from.
TAR_OIDC_SCOPE_CLAIMscopeWhere granted scopes are read from.
TAR_WORKLOAD_ISSUERSComma-separated. Accepted for workload tokens only.
TAR_OIDC_AUTO_REGISTER_INSTANCESfalseLet any accepted credential register a deployment of software it names itself.

The audience mapper, which is what catches everyone

TAR_OIDC_AUDIENCE defaults to TAR_BASE_IRI, and TAR_OIDC_REQUIRE_AUDIENCE defaults to true. So the client in your identity provider needs an audience mapper adding that exact string.

Without one, a typical provider issues an access token with an audience of its own account service, sign-in completes at the provider, the browser comes back, and the registry rejects the token. The symptom is a successful login followed immediately by a failure, which is a confusing thing to debug from either end.

The audience is the base IRI, not the origin, not the sign-in redirect URL. If you serve the registry on a second origin, that origin needs its own mapper.

Requiring the audience rather than merely checking it when present is deliberate. A token with no audience is a token minted for nobody in particular, and accepting one means accepting any token that issuer ever signs, for any application.

Roles

Three, read from the roles claim:

RoleMeans
readerSigned in; no write authority.
curatorRegister and edit software, releases, deployments and vocabulary terms.
adminEverything a curator can, plus peers and token administration.

A signed-in person with none of them is exactly that: signed in, and able to read what anonymous readers can read.

Workload issuers

TAR_WORKLOAD_ISSUERS lists additional issuers accepted for workload tokens: a Kubernetes API server, a CI provider's OIDC issuer, a partner's identity provider.

They are trusted to say which deployment is calling and nothing else. Only TAR_OIDC_ISSUER may assert roles.

This is the single most important line in the auth configuration. A Kubernetes API server and a CI provider can each mint a token containing a realm role called admin; if the registry honoured that, adding a CI issuer would hand the registry to anyone who can open a pull request against any repository on that platform.

Pin the issuer on every credential binding

Roles are not the only thing a second issuer can spell. A client id is only unique within an issuer: validator-prod at your Keycloak and validator-prod at a CI provider are different principals with the same name, and registering a client under a chosen name is free everywhere.

So once you add a workload issuer, say which issuer each binding means:

WhereFieldNames
Softwareregistration_issuerthe provider registration_clients belong to
Deploymentoidc_issuerthe provider oidc_client_id belongs to
Deploymentself_registered_issuerwritten by the registry when a deployment self-registers

A binding that pins nothing is read against the primary issuer (TAR_OIDC_ISSUER), or the sole workload issuer when that is all there is — the two readings with one obvious answer. With several accepted and no primary, the registry refuses the binding rather than guessing, because guessing would grant the weakest accepted issuer the authority meant for the strongest. On a single-issuer registry none of this changes anything.

See How a tool authenticates.

A local provider to try it against

deploy/keycloak/ holds a one-container Keycloak with an importable realm — three roles, a PKCE public client, a service-account client for the workload path, and users with known passwords — so both flows can be exercised for real rather than described.

docker compose -f deploy/keycloak/compose.yaml up -d

deploy/keycloak/README.md has the realm's users, clients, ports and redirect URIs, and the exact environment to serve the registry with. The credentials in it are test values committed on purpose: that is what makes the setup reproducible rather than click-configured. Nothing in that directory belongs anywhere near a real deployment — it runs in development mode, over plain HTTP, with a database that is wiped on every down.

Its clients already carry the audience mappers for the origins it documents. Serve on any other origin and you must add one.

Repository sync credentials

Keeping a software record in step with a private repository needs a forge token. If your identity provider can broker one for the signed-in person, the registry reads exactly what that person can read. Otherwise TAR_FORGE_TOKEN is a registry-wide fallback, which means every curator can pull anything that token can see. See Registering software.

What is not covered

Nothing on the browser sign-in side. Token refresh — once a gap — now renews silently on a timer and on a 401, with the refresh token kept in memory only; see Token refresh.