Auth: JWT & OAuth 2.0
JWT structure, access/refresh tokens, OAuth 2.0 flows, PKCE, session vs token.
authsecuritybackend
# Auth: JWT & OAuth 2.0
## JWT structure
`header.payload.signature` (base64url)
- Header: `{ alg: HS256, typ: JWT }`
- Payload: `sub`, `iat`, `exp`, custom claims
- Signature: HMACSHA256(header + "." + payload, secret)
## Access + refresh token pattern
- **Access token**: short-lived (15m), stored in memory.
- **Refresh token**: long-lived (7-30d), httpOnly cookie.
- On expiry: use refresh token silently to get new access token.
- Refresh token rotation: issue new token each time, invalidate old.
```ts
const access = jwt.sign({ sub: userId }, process.env.JWT_SECRET, { expiresIn: '15m' })
const payload = jwt.verify(token, process.env.JWT_SECRET)
```
## OAuth 2.0 flows
- **Authorization Code + PKCE**: SPAs and mobile. Most secure.
- **Client Credentials**: M2M, no user involved.
- **Device Code**: TV / CLI apps.
- Avoid: Implicit (deprecated), ROPC (legacy).
## PKCE
1. Generate `code_verifier` (43-128 random chars)
2. `code_challenge = base64url(SHA256(verifier))`
3. Auth with `code_challenge`
4. Exchange `code` + `code_verifier` for tokens
## Session vs Token
| | Session | JWT |
|---|---|---|
| Storage | Server | Client |
| Revocation | Easy | Hard (short TTL or blocklist) |
| Scale | Needs shared store | Stateless |
## Security rules
- Always HTTPS. Validate `aud` + `iss`.
- Never store sensitive data in JWT payload (only signed, not encrypted).
- Cookies: `SameSite=Strict; httpOnly; Secure`.API: /api/skills/auth-jwt-oauth