first commit
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
# /token endpoint
|
||||
|
||||
## Purpose
|
||||
|
||||
`handleToken` implements the OAuth 2.0 token endpoint (RFC-6749 §4.1.3
|
||||
and §6) for the mock IdP. It supports two grant types:
|
||||
`authorization_code` (exchanging a freshly issued code for an
|
||||
access+refresh-token pair) and `refresh_token` (rotating an existing
|
||||
refresh-token).
|
||||
|
||||
PKCE verification (RFC-7636) is enforced when the matching auth-code
|
||||
record carries a `code_challenge`; both `plain` and `S256` challenge
|
||||
methods are supported, and mismatches produce
|
||||
`{ error: "invalid_grant" }` responses with HTTP 400 per spec.
|
||||
|
||||
## Features
|
||||
|
||||
- `authorization_code` grant with single-use code semantics.
|
||||
- `refresh_token` grant with rotation — the previous refresh token is
|
||||
revoked on each successful refresh.
|
||||
- PKCE S256 verification using a real `node:crypto` `sha256` hash.
|
||||
- Configurable `expires_in` via `accessTokenTtlSeconds`.
|
||||
- RFC-6749 error envelopes: `invalid_request`, `invalid_grant`,
|
||||
`unsupported_grant_type`.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
const tokenResponse = handleToken(state, {
|
||||
grant_type: "authorization_code",
|
||||
code: "abc",
|
||||
code_verifier: "verifier-43-chars-min",
|
||||
});
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
Rotate a refresh token (the original is revoked):
|
||||
|
||||
```ts
|
||||
const refreshed = handleToken(state, {
|
||||
grant_type: "refresh_token",
|
||||
refresh_token: previous.refresh_token,
|
||||
});
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `handleToken(state, form): TokenResult`
|
||||
- `interface TokenSuccess` — `{ status: 200, body: { access_token,
|
||||
token_type: "Bearer", expires_in, refresh_token, scope? } }`.
|
||||
- `interface TokenError` — `{ status: 400|401, body: { error,
|
||||
error_description? } }`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
PKCE S256 base64url encoding is performed with `Buffer.toString('base64')`
|
||||
followed by manual `=` stripping and `+`/`/` substitution — this matches
|
||||
RFC-4648 §5 and is what every conforming client SDK produces. Auth codes
|
||||
are marked `used = true` on first successful exchange, and reuse is
|
||||
rejected as `invalid_grant`. Refresh tokens carry forward the original
|
||||
`userPayload` so subsequent `/userinfo` calls keep returning the same
|
||||
identity, modelling production IdP behaviour faithfully.
|
||||
Reference in New Issue
Block a user