Public Access
feat(security): check role markers on services and read the role claim
Every service method a controller calls carries @RequiresRole, @Public or @Internal; a Spring Security method interceptor checks it while a request is served. Core now grants the active role from the token and every lower one. ArchUnit fails the build for an unmarked method, two markers, a controller calling an @Async method, or a service reaching a method that needs more. The background refreshes moved from LibraryController into the services, because an @Async method is never checked.
This commit is contained in:
1 parent
351cda411d
commit
2596df609e
47 files changed
+1114
-21
No files matched your search
@@ -70,7 +70,9 @@ To Be Played is split into three repositories:
|
||||
Core never issues tokens. It verifies Auth's EdDSA (Ed25519) JWTs with public keys only. It loads them from Auth's
|
||||
JWKS by the token's `kid` and loads again when a new `kid` shows up (at most every 10 seconds). Loaded keys stay
|
||||
until Core restarts. `JWT_PUBLIC_KEY` is used only until the first JWKS load works. The token comes from Auth's
|
||||
`tbp_access` cookie or a `Bearer` header, whichever verifies first. Core reads `userId` and `steamId` from the claims.
|
||||
`tbp_access` cookie or a `Bearer` header, whichever verifies first. Core reads `userId`, `steamId` and the active
|
||||
`role` (missing or unknown = USER) from the claims and grants that role and every lower one
|
||||
(`USER < AUDITOR < PLATFORM_ADMIN`).
|
||||
`POST`, `PUT` and `DELETE` need an `X-TBP-Client` or `Authorization` header (CSRF guard), and CORS allows only the
|
||||
frontend origin.
|
||||
A token with a `typ` claim (for example a profile ticket) is rejected on normal endpoints; the profile ticket is
|
||||
@@ -79,6 +81,14 @@ accepted only by `GET /api/public/profiles/library` in the `X-Profile-Ticket` he
|
||||
as `Bearer`), never a login, also not in the dev profile. Traefik exposes the path, so the signed token is its
|
||||
only guard.
|
||||
|
||||
Every service method a controller calls carries one role marker, on the method or on its class (the method wins):
|
||||
`@RequiresRole(Role.X)`, `@Public` (no login, e.g. landing stats; the public profile checks its ticket) or
|
||||
`@Internal` (only Auth's service token). A Spring Security method interceptor checks it while a request is served;
|
||||
scheduled jobs and `@Async` work run without a user and are not checked. A denied call answers `401` without a
|
||||
login, else `403`. The URL rules in `SecurityConfig` stay as the outer guard. ArchUnit fails the build for an
|
||||
unmarked method, two markers, a controller calling an `@Async` method (the check would never run), and a service
|
||||
method calling another service's method that needs more.
|
||||
|
||||
## API
|
||||
|
||||
| Method | Path | Auth |
|
||||
|
||||
Reference in new issue
Block a user