mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 10:59:59 +00:00
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
114 lines
5.7 KiB
Markdown
114 lines
5.7 KiB
Markdown
# OIDC 🪪
|
|
|
|
This page describes how application roles consume the platform's OIDC provider, [Keycloak](../../../../roles/web-app-keycloak/).
|
|
The variable tree lives in [11_oidc.yml](../../../../group_vars/all/11_oidc.yml) under `defaults_oidc`.
|
|
For the cross-cutting IAM principles, including the paired identifier rule shared with LDAP, see [common.md](common.md).
|
|
For LDAP-side details see [ldap.md](ldap.md).
|
|
|
|
## Variable Tree 🌳
|
|
|
|
The `OIDC` tree is a lazy group_var: it resolves in the consuming role's
|
|
context, so the issuer family-aligns to that consumer (clearnet page →
|
|
clearnet issuer, onion page → onion issuer). Inventory overrides therefore
|
|
live under `OIDC_OVERRIDE:` — an inventory-level `OIDC:` block would shadow
|
|
the lazy resolution and is rejected by a constructor assert.
|
|
|
|
The keys consumers care about:
|
|
|
|
| Key | Meaning |
|
|
|---|---|
|
|
| `OIDC.URL` | Base URL of the Keycloak instance |
|
|
| `OIDC.CLIENT.ID` | Client identifier, defaults to `SOFTWARE_DOMAIN` |
|
|
| `OIDC.CLIENT.SECRET` | Client secret, MUST come from the inventory (`OIDC_OVERRIDE.CLIENT.SECRET`) |
|
|
| `OIDC.CLIENT.REALM` | Realm the client is registered in |
|
|
| `OIDC.CLIENT.ISSUER_URL` | Issuer URL, equal to discovery `issuer` |
|
|
| `OIDC.CLIENT.DISCOVERY_DOCUMENT` | `.well-known/openid-configuration` URL |
|
|
| `OIDC.CLIENT.AUTHORIZE_URL` | Authorization endpoint |
|
|
| `OIDC.CLIENT.TOKEN_URL` | Token endpoint |
|
|
| `OIDC.CLIENT.USER_INFO_URL` | Userinfo endpoint |
|
|
| `OIDC.CLIENT.LOGOUT_URL` | RP-initiated logout endpoint |
|
|
| `OIDC.CLIENT.CERTS` | JWKS endpoint, equal to discovery `jwks_uri` |
|
|
| `OIDC.CLIENT.ACCOUNT.URL` | User self-service console root |
|
|
| `OIDC.CLIENT.ACCOUNT.PROFILE_URL` | Personal-info section deep link |
|
|
| `OIDC.CLIENT.ACCOUNT.SECURITY_URL` | Login and security section deep link |
|
|
| `OIDC.CLIENT.CHANGE_CREDENTIALS` | Direct link to the credentials editor |
|
|
| `OIDC.CLIENT.RESET_CREDENTIALS` | Public password-reset entry point |
|
|
| `OIDC.BUTTON_TEXT` | Default label for SSO login buttons |
|
|
|
|
When a role needs an OIDC endpoint, it MUST template the corresponding `OIDC.CLIENT.*` value rather than build the URL from `OIDC.URL` itself.
|
|
The URL builders in [11_oidc.yml](../../../../group_vars/all/11_oidc.yml) already handle realm and protocol concerns.
|
|
|
|
## Claim Attributes 🏷️
|
|
|
|
`OIDC.ATTRIBUTES` lists the claim names that downstream applications read out of the userinfo response and ID token:
|
|
|
|
| Key | Default value | Meaning |
|
|
|---|---|---|
|
|
| `OIDC.ATTRIBUTES.USERNAME` | `preferred_username` | Stable user identifier |
|
|
| `OIDC.ATTRIBUTES.GIVEN_NAME` | `givenName` | First name |
|
|
| `OIDC.ATTRIBUTES.FAMILY_NAME` | `surname` | Last name |
|
|
| `OIDC.ATTRIBUTES.EMAIL` | `email` | Email address |
|
|
|
|
Rules:
|
|
|
|
- Application roles MUST identify users via `OIDC.ATTRIBUTES.USERNAME`. They
|
|
MUST NOT introduce a private claim name (for example `user_id`, `uid`, or
|
|
`oauth_uid`) when `preferred_username` already satisfies the requirement.
|
|
- Roles MUST NOT hardcode the literal value `preferred_username`. Always
|
|
template `{{ OIDC.ATTRIBUTES.USERNAME }}`.
|
|
- The standard OIDC `sub` claim is permitted as an alternative when the
|
|
application explicitly requires a UUID-shaped identifier and stores its own
|
|
mapping table. In that case the role MUST document the deviation in its
|
|
README.
|
|
- The OIDC username claim is paired with the LDAP login attribute by design.
|
|
See [ldap.md](ldap.md) for the LDAP-side rule.
|
|
|
|
## Keycloak Client Templates 📦
|
|
|
|
Keycloak client definitions are imported from
|
|
[clients](../../../../roles/web-app-keycloak/templates/import/clients/). The
|
|
default template in
|
|
[default.json.j2](../../../../roles/web-app-keycloak/templates/import/clients/default.json.j2)
|
|
is shared by every application client.
|
|
|
|
Rules:
|
|
|
|
- The shared `default.json.j2` MUST stay generic. App-specific protocol
|
|
mappers, claims, or scopes MUST NOT be added there because the change
|
|
affects every other client.
|
|
- An app that needs an extra mapper MUST add it through a per-client scope.
|
|
See
|
|
[nextcloud.json.j2](../../../../roles/web-app-keycloak/templates/import/scopes/nextcloud.json.j2)
|
|
for the precedent: a dedicated scope holds the Nextcloud-specific UID and
|
|
quota mappers and is attached only to the Nextcloud client.
|
|
- New scope files MUST be referenced from the consuming app via its
|
|
`KEYCLOAK_RBAC_GROUP_CLAIM` style configuration or via the
|
|
`optionalClientScopes` list in the client template.
|
|
|
|
## Consumer Pattern 🧩
|
|
|
|
A typical OIDC-consuming role wires the values into its environment template, for example [env.j2](../../../../roles/web-app-mastodon/templates/env.j2):
|
|
|
|
```jinja
|
|
OIDC_ISSUER={{ OIDC.CLIENT.ISSUER_URL }}
|
|
OIDC_DISCOVERY=true
|
|
OIDC_SCOPE=openid,profile,email
|
|
OIDC_UID_FIELD={{ OIDC.ATTRIBUTES.USERNAME }}
|
|
OIDC_CLIENT_ID={{ OIDC.CLIENT.ID }}
|
|
OIDC_CLIENT_SECRET={{ OIDC.CLIENT.SECRET }}
|
|
```
|
|
|
|
Every application role SHOULD follow the same shape: discovery on, the `OIDC.CLIENT.*` endpoints templated, the user identifier read from `OIDC.ATTRIBUTES.USERNAME`, and the scopes limited to what the app actually consumes.
|
|
|
|
## Related Files 📚
|
|
|
|
| File | Purpose |
|
|
|---|---|
|
|
| [11_oidc.yml](../../../../group_vars/all/11_oidc.yml) | OIDC SPOT, defines `OIDC.*` |
|
|
| [web-app-keycloak](../../../../roles/web-app-keycloak/) | OIDC provider role |
|
|
| [default.json.j2](../../../../roles/web-app-keycloak/templates/import/clients/default.json.j2) | Shared client template, MUST stay app-agnostic |
|
|
| [scopes](../../../../roles/web-app-keycloak/templates/import/scopes/) | Per-app client scopes for extra mappers |
|
|
| [realm.json.j2](../../../../roles/web-app-keycloak/templates/import/realm.json.j2) | Realm definition, including the `preferred_username` mapper |
|
|
| [ldap.md](ldap.md) | LDAP-side counterpart, paired user identifier |
|
|
| [common.md](common.md) | Cross-cutting IAM principles and integration checklist |
|