feat(infra): Keycloak with mock DigiD/eHerkenning/eIDAS/medewerker realms (closes #3)
Add infra/keycloak/docker-compose.yml (Keycloak 26.1, dev mode, --import-realm) with four realms imported at boot (infra/keycloak/realms/*.json): digid, eherkenning, eidas, medewerker. Each has a public big-portal OIDC client (standard flow + direct access grants) and test users; protocol mappers inject the identifying claims (bsn / kvk / eidas_id) and medewerker realm roles. Add `make keycloak-up/keycloak-smoke/keycloak-down`; keycloak-smoke runs infra/keycloak/check_realms.py (password-grant login per realm, asserts the claim). Document credentials in docs/synthetic-data.md and a runbook. Verified: `make keycloak-smoke` green — all four realms log in and return the expected claims (bsn 123456782, kvk 12345678, eidas_id FR/NL..., role behandelaar). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
37
docs/runbooks/keycloak.md
Normal file
37
docs/runbooks/keycloak.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# Keycloak runbook
|
||||
|
||||
Keycloak (`infra/keycloak/docker-compose.yml`) runs in dev mode with four realms
|
||||
imported at boot from `infra/keycloak/realms/`: **digid**, **eherkenning**, **eidas**,
|
||||
**medewerker**. It mocks the Dutch identity brokers so portals can do real OIDC logins
|
||||
locally. Host port **:8180**.
|
||||
|
||||
## Quick test (`make`)
|
||||
|
||||
```bash
|
||||
make keycloak-up # start Keycloak + import realms (~30-60s first boot)
|
||||
make keycloak-smoke # start + verify every realm logs in and returns its claim
|
||||
make keycloak-down # stop + wipe
|
||||
```
|
||||
|
||||
`make keycloak-smoke` runs `infra/keycloak/check_realms.py`, which does a password-grant
|
||||
login per realm and asserts the identifying claim:
|
||||
|
||||
| Realm | User | Claim asserted |
|
||||
|---|---|---|
|
||||
| digid | jan-burger | `bsn` |
|
||||
| eherkenning | acme-ondernemer | `kvk` |
|
||||
| eidas | pierre-dupont | `eidas_id` |
|
||||
| medewerker | merel-behandelaar | role `behandelaar` |
|
||||
|
||||
All test users / credentials are in [../synthetic-data.md](../synthetic-data.md).
|
||||
|
||||
## Notes
|
||||
|
||||
- **Admin console:** <http://localhost:8180/> — `admin` / `admin` (dev only).
|
||||
- **Client `big-portal`** is public with `standardFlowEnabled` (browser redirect login)
|
||||
*and* `directAccessGrantsEnabled` (password grant, used by the smoke test).
|
||||
- **Dev store:** in-memory H2 via `start-dev`; realms re-import on each boot, so changes
|
||||
made in the admin UI don't persist. Edit the realm JSONs to make durable changes.
|
||||
- **Image** pinned to `quay.io/keycloak/keycloak:26.1`.
|
||||
- Claims are injected by OIDC protocol mappers on `big-portal` (user attribute → token
|
||||
claim); `medewerker` roles come through `realm_access.roles`.
|
||||
35
docs/synthetic-data.md
Normal file
35
docs/synthetic-data.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Synthetic data
|
||||
|
||||
All credentials here are **dev-only** synthetic test data — never real personal data,
|
||||
never used outside local development.
|
||||
|
||||
## Keycloak realms (S-02)
|
||||
|
||||
Keycloak runs at <http://localhost:8180> (admin console: **admin / admin**). Four realms
|
||||
are imported at boot from `infra/keycloak/realms/`. Each has a public OIDC client
|
||||
**`big-portal`** (standard flow + direct access grants enabled, redirect URIs `*` for dev).
|
||||
|
||||
All test users share the password **`test123`**.
|
||||
|
||||
| Realm | Mimics | User | Identifying claim |
|
||||
|---|---|---|---|
|
||||
| `digid` | DigiD (burgers) | `jan-burger` | `bsn` = `123456782` |
|
||||
| `eherkenning` | eHerkenning (bedrijven) | `acme-ondernemer` | `kvk` = `12345678` |
|
||||
| `eidas` | eIDAS (EU) | `pierre-dupont` | `eidas_id` = `FR/NL/AB-1234-5678` |
|
||||
| `medewerker` | Internal staff | `merel-behandelaar` | role `behandelaar` |
|
||||
| `medewerker` | Internal staff | `tom-teamlead` | roles `behandelaar`, `teamlead` |
|
||||
|
||||
The identifying claims are injected via OIDC protocol mappers on `big-portal`
|
||||
(user-attribute → token claim); `medewerker` roles appear in `realm_access.roles`.
|
||||
|
||||
## Get a token (for testing)
|
||||
|
||||
```bash
|
||||
curl -s -X POST \
|
||||
http://localhost:8180/realms/digid/protocol/openid-connect/token \
|
||||
-d grant_type=password -d client_id=big-portal \
|
||||
-d username=jan-burger -d password=test123 -d scope=openid | jq -r .access_token
|
||||
```
|
||||
|
||||
Decode the JWT payload to see the `bsn` claim. `make keycloak-smoke` checks every realm
|
||||
automatically.
|
||||
Reference in New Issue
Block a user