mancala/apps/keycloak/README.md
Halit Aksoy 7c99a76af7 feat(keycloak): add Keycloak with guest login extension
- Custom authenticator creates and logs in a guest user when the
  authorization request has guest=true; other requests get the login form
- Scheduled task removes guests with no remaining sessions
- Realm export with mancala-web PKCE client, guest role and guest-aware
  browser flow (verify profile disabled so guests are not asked for details)
- Dockerfile building the extension into a Keycloak 26.7.5 image
- Keycloak and Postgres in compose; nginx proxies auth.playmancala.app
  and rate limits the auth endpoint
- Integration tests run the extension and realm in a Keycloak container
2026-10-14 01:46:48 +03:00

63 lines
2.5 KiB
Markdown

# Mancala Keycloak
Keycloak is the only auth system for Mancala. Players can either log in with an account or play as a guest,
and both come back as normal Keycloak tokens from the `mancala` realm.
## Guest login
`extension/` adds a `mancala-guest-authenticator` to Keycloak. When an authorization request has `guest=true`,
it creates a new user named `guest-xxxxxxxx`, gives it the `guest` realm role and logs it in without showing a
form. Requests without the parameter fall through to the normal login form.
```
/realms/mancala/protocol/openid-connect/auth?client_id=mancala-web&response_type=code
&scope=openid%20offline_access&redirect_uri=...&code_challenge=...&code_challenge_method=S256
&guest=true
```
- Clients can tell guests apart by `"guest"` in the access token's `realm_access.roles`.
- Guests should request `offline_access` so they keep their identity after the SSO session ends
(offline sessions expire after 30 days without use).
- A scheduled task deletes guests that are older than a day and have no session or offline session left.
Its timing can be changed with server options such as
`KC_SPI_AUTHENTICATOR__MANCALA_GUEST_AUTHENTICATOR__CLEANUP_INTERVAL_SECONDS` (default 3600),
`..._CLEANUP_MIN_AGE_SECONDS` (default 86400) and `..._CLEANUP_MAX_DELETES_PER_RUN` (default 1000).
- Each guest login creates a user, so the auth endpoint is rate limited per IP in `config/nginx.conf`.
## Realm
`realm/mancala-realm.json` holds the realm: the `mancala-web` public client (PKCE S256), the
`browser with guest` flow, the `guest` role, and the required actions with "Verify Profile" turned off so guests
are not asked for an email or a name.
Keycloak imports the file only if the realm does not exist yet. After changing it, apply the change in the admin
console too, or delete the realm and restart Keycloak.
## Running
```sh
cd apps
cat > .env <<EOF
KEYCLOAK_DB_PASSWORD=change-me
KEYCLOAK_ADMIN_PASSWORD=change-me
EOF
docker compose up -d --build keycloak
```
Keycloak is then at http://localhost:8080 and the admin console at http://localhost:8080/admin.
In production set `KEYCLOAK_HOSTNAME=https://auth.playmancala.app`; nginx proxies that host to port 8080.
## Tests
```sh
cd apps/keycloak/extension
mvn test
```
The tests start Keycloak with the extension and the real realm file in a container, so they need Docker.
## Upgrading Keycloak
The extension uses Keycloak's authenticator SPI, which Keycloak marks as internal. When upgrading, change the
version in `extension/pom.xml` and in `Dockerfile` together and run the tests.