3.4 KiB
3.4 KiB
Authentication & Authorization Invariants — auth-migration
1. Authentication Rules
| ID | Rule | Trigger | Expected Behavior | Error Code |
|---|---|---|---|---|
| AUTH-001 | JWT must contain sub claim |
Any protected endpoint | Reject with 401 if sub missing/empty |
AUTH_MISSING_SUB |
| AUTH-002 | JWT exp must be in future |
Any protected endpoint | Reject with 401 if expired | AUTH_TOKEN_EXPIRED |
| AUTH-003 | JWT signature must verify against secret | Any protected endpoint | Reject with 401 if signature invalid | AUTH_INVALID_SIGNATURE |
| AUTH-004 | Bearer token required in Authorization header | Any protected endpoint | Reject with 401 if header missing | AUTH_MISSING_TOKEN |
| AUTH-005 | Token format must be Bearer <token> |
Any protected endpoint | Reject with 401 if malformed | AUTH_MALFORMED_TOKEN |
2. Authorization Rules
| ID | Rule | Scope | Expected Behavior | Error Code |
|---|---|---|---|---|
| AUTH-010 | ADMIN role required for user management | /api/admin/** |
Reject with 403 if not ADMIN | AUTH_FORBIDDEN_ADMIN |
| AUTH-011 | Resource owner or ADMIN can modify | /api/users/{id}/** |
Reject with 403 if neither | AUTH_FORBIDDEN_RESOURCE |
| AUTH-012 | Any authenticated user can read public profiles | /api/users/public/** |
Allow 200 if authenticated | — |
| AUTH-013 | Role hierarchy: ADMIN > MANAGER > USER | All role-gated endpoints | Higher role inherits lower permissions | — |
3. Error Response Schema
| HTTP Status | Error Code | Response Body Shape |
|---|---|---|
| 401 | AUTH_MISSING_TOKEN |
{"error":"AUTH_MISSING_TOKEN","message":"Authorization header required","timestamp":<epoch>} |
| 401 | AUTH_MALFORMED_TOKEN |
{"error":"AUTH_MALFORMED_TOKEN","message":"Bearer token format required","timestamp":<epoch>} |
| 401 | AUTH_TOKEN_EXPIRED |
{"error":"AUTH_TOKEN_EXPIRED","message":"Token has expired","timestamp":<epoch>} |
| 401 | AUTH_INVALID_SIGNATURE |
{"error":"AUTH_INVALID_SIGNATURE","message":"Token signature verification failed","timestamp":<epoch>} |
| 401 | AUTH_MISSING_SUB |
{"error":"AUTH_MISSING_SUB","message":"Token missing subject claim","timestamp":<epoch>} |
| 403 | AUTH_FORBIDDEN_ADMIN |
{"error":"AUTH_FORBIDDEN_ADMIN","message":"Admin role required","timestamp":<epoch>} |
| 403 | AUTH_FORBIDDEN_RESOURCE |
{"error":"AUTH_FORBIDDEN_RESOURCE","message":"Not authorized for this resource","timestamp":<epoch>} |
4. Session / Cookie Semantics
| ID | Rule | Behavior |
|---|---|---|
| SESS-001 | Session cookie HttpOnly |
Must be true |
| SESS-002 | Session cookie Secure |
Must be true in production |
| SESS-003 | Session cookie SameSite |
Must be Lax or Strict |
| SESS-004 | CSRF token required for state-changing ops | POST/PUT/DELETE without CSRF → 403 |
5. Migration Checklist
- Spring Security filter chain preserves order: JWT filter before session filter
@PreAuthorizeannotations match existing role-gate logicAuthenticationEntryPointreturns exact error schema (AUTH_* codes)AccessDeniedHandlerreturns exact error schema (AUTH_FORBIDDEN_* codes)- Cookie attributes (
HttpOnly,Secure,SameSite) set viaCookieSecurityConfigurer - CSRF protection enabled for state-changing endpoints
- Role hierarchy bean
RoleHierarchyImplwired with ADMIN > MANAGER > USER