Files
minecraft-account-manager/docs/admin-oidc-keycloak-setup.md
T
dmg c2ac2ad16b
CI / validate (push) Successful in 6m49s
Release / release (push) Successful in 11m24s
feat(auth): verify machine tokens for admin read APIs
2026-09-10 14:53:47 -04:00

1.9 KiB

Admin OIDC setup

The admin console uses Keycloak OIDC and JWT-backed NextAuth sessions.

Application environment

  • AUTH_SECRET
  • NEXTAUTH_URL
  • KEYCLOAK_ISSUER_URL
  • KEYCLOAK_CLIENT_ID
  • KEYCLOAK_CLIENT_SECRET
  • KEYCLOAK_REQUIRED_ROLE (defaults to minecraft-account-manager-admin)

Keycloak client

Create a confidential OpenID Connect client with standard authorization code flow enabled and direct access grants disabled.

Recommended client ID: minecraft-account-manager-admin

Allow exact callback and logout URLs for each environment. Avoid wildcard origins and redirect URLs.

Create the realm role minecraft-account-manager-admin and assign it directly or through an admin group. Ensure realm roles are emitted in realm_access.roles.

The admin console rejects sign-in when the required role is absent, even when Keycloak authentication itself succeeds. Existing browser sign-in accepts realm or configured-client roles; this behavior is unchanged.

Read-only machine API access

The admin API guard independently verifies signed Keycloak access tokens. Machine tokens must include KEYCLOAK_CLIENT_ID in aud and KEYCLOAK_REQUIRED_ROLE in resource_access[KEYCLOAK_CLIENT_ID].roles. A realm role alone is not sufficient for bearer access. The identity provider must emit both the portal audience and this client role; a token's azp is not an audience substitute.

Verification uses the HTTPS issuer's /protocol/openid-connect/certs JWKS endpoint and RS256 only. It does not use KEYCLOAK_CLIENT_SECRET, exchange tokens, or create a browser session. Browser client configuration above remains required for interactive SSO. Provisioning or changing machine clients, role/audience mappers, credentials, and production deployment requires separate operational approval; this source implementation performs none of those operations.