refactor(api): one error body, token audiences, user lookup by id
Build, Test & Push Auth Service / quality-check (push) Successful in 54s
Build, Test & Push Auth Service / docker (push) Successful in 1m21s

This commit is contained in:
lobo committed 2026-09-29 14:48:28 +02:00
1 parent 68919eaab4
commit afcfacb68b
30 files changed
+662 -199

No files matched your search

+10 -3
View File
@@ -41,8 +41,15 @@ To Be Played is split into three repositories:
tiles in order, each with a size S, M or L), apart from the app appearance; the public answer sends both as
`style`. The ticket's claims come from the layout: `sections` names the shown parts (`STATS` when any `STATS_`
tile is shown), `profileStats` the stat groups of the `STATS_` tiles. The user's dashboard layout
(`dashboard_tiles`, NULL = never changed) is stored the same way. The ticket is not a login:
both services reject every token with a `typ` claim on normal endpoints.
(`dashboard_tiles`, NULL = never changed) is stored the same way. The ticket is not a login: every token names
its kind in `aud` (`tbp-login`, `tbp-public-profile`, `tbp-internal`, `iss=tbp-auth`), and both services check it.
A login's `sub` is the user id; the email is in no token. Until item 29 the tokens also carry the claims of before
item 26 (`userId`, `typ`), so an older Core still reads them. The claims are pinned in
`src/test/resources/contract/auth-core-contract.json`, the same file as in Core
(`ToBePlayed-Deployment/scripts/check-contract.sh` compares both).
- Errors: every error answer of a controller has the body `{code, message}` (a 401 or 403 of the security filters has none); a refused request is `400 VALIDATION_FAILED` with
`fields`, a duplicate email or display name `409 EMAIL_ALREADY_IN_USE` / `DISPLAY_NAME_ALREADY_IN_USE`, anything
unexpected `500 INTERNAL_ERROR` without details (`shared/api/GlobalExceptionController`).
- **Roles**: one per user, a ladder `USER < AUDITOR < PLATFORM_ADMIN` (`users.role`, the first admin is set by
SQL). The access token carries the active role in the `role` claim. **View as**: an admin switches the own login
down to USER or AUDITOR and back (`POST /api/auth/view-as`); the choice is stored per login in
@@ -68,7 +75,7 @@ To Be Played is split into three repositories:
link, not in the landing stats. Email and display name stay taken; the Steam ID is freed, so an undo needs a
new Steam link. A nightly job (04:15, Europe/Berlin) removes
users flagged 30 days ago, in Core first and then in Auth. It calls Core's `/internal/accounts/*` with a
**service token** (EdDSA JWT, 60 s, `typ=service`). `app.account-cleanup.dry-run` (default `true`) only logs.
**service token** (EdDSA JWT, 60 s, `aud=tbp-internal`). `app.account-cleanup.dry-run` (default `true`) only logs.
## API