56 lines
1.9 KiB
Markdown
56 lines
1.9 KiB
Markdown
# ADR-0017: JWT Token Strategy
|
|
|
|
## Status
|
|
Accepted
|
|
|
|
## Context
|
|
The platform needs authentication tokens that:
|
|
- Are stateless (no server-side session storage)
|
|
- Support role and permission claims
|
|
- Can be revoked (challenge)
|
|
- Have appropriate lifetimes
|
|
- Support multi-tenancy (tenant ID in claims)
|
|
|
|
Token strategies considered:
|
|
1. **Short-lived access tokens + long-lived refresh tokens** - Industry standard
|
|
2. **Single long-lived tokens** - Simple but insecure
|
|
3. **Short-lived tokens only** - Secure but poor UX
|
|
4. **Session-based** - Stateful, requires storage
|
|
|
|
## Decision
|
|
Use **short-lived access tokens + long-lived refresh tokens**:
|
|
|
|
1. **Access tokens**: 15 minutes lifetime, contain user ID, roles, tenant ID
|
|
2. **Refresh tokens**: 7 days lifetime, stored in database (for revocation)
|
|
3. **Token format**: JWT with claims: `sub` (user ID), `roles`, `tenant_id`, `exp`
|
|
4. **Revocation**: Refresh tokens stored in DB, can be revoked/deleted
|
|
|
|
**Rationale:**
|
|
- Industry best practice (OAuth2/OIDC pattern)
|
|
- Good balance of security and UX
|
|
- Access tokens can't be revoked (short lifetime mitigates risk)
|
|
- Refresh tokens can be revoked (stored in DB)
|
|
- Supports stateless authentication for most requests
|
|
|
|
## Consequences
|
|
|
|
### Positive
|
|
- Secure (short access token lifetime)
|
|
- Good UX (refresh tokens prevent frequent re-login)
|
|
- Stateless for most requests (access tokens)
|
|
- Supports revocation (refresh tokens)
|
|
|
|
### Negative
|
|
- Requires refresh token storage (DB table)
|
|
- More complex than single token
|
|
- Need to handle token refresh flow
|
|
|
|
### Implementation Notes
|
|
- Use `github.com/golang-jwt/jwt/v5` for JWT handling
|
|
- Store refresh tokens in `refresh_tokens` table (user_id, token_hash, expires_at)
|
|
- Generate access tokens with HS256 or RS256 signing
|
|
- Include roles in token claims (not just role IDs)
|
|
- Validate token signature and expiration on each request
|
|
- Refresh endpoint validates refresh token and issues new access token
|
|
|