first commit
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
# /userinfo endpoint
|
||||
|
||||
## Purpose
|
||||
|
||||
`handleUserInfo` implements the OAuth/OIDC userinfo endpoint. Given a
|
||||
`Bearer` authorization header, it looks up the associated access token,
|
||||
verifies it has not expired, and returns the matching user payload
|
||||
shaped by the configured `userShape` (or by a custom `userMapper` when
|
||||
the caller supplies one).
|
||||
|
||||
The endpoint backs the primary identity-fetch path that production OAuth
|
||||
adapters use after a successful code-exchange, so it is the surface most
|
||||
test scenarios assert against.
|
||||
|
||||
## Features
|
||||
|
||||
- `Bearer <token>` extraction with regex validation.
|
||||
- Looks up the token in the in-memory access-token map and 401s on
|
||||
unknown or expired tokens.
|
||||
- Dispatches across `github` / `google` / `generic` shapes, or hands the
|
||||
primed payload to a caller-supplied `userMapper`.
|
||||
- All error responses use RFC-6750 `invalid_token` envelopes.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
const r = handleUserInfo(state, "Bearer at_abc");
|
||||
// → { status: 200, body: { id: 42, login: "alice", … } }
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
Provide a custom mapper to return arbitrary claim shapes:
|
||||
|
||||
```ts
|
||||
const state = {
|
||||
...,
|
||||
options: {
|
||||
...,
|
||||
userMapper: (primed) => ({ sub: String(primed?.id), groups: ["admins"] }),
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `handleUserInfo(state, authorizationHeader: string | undefined): UserInfoResult`
|
||||
- `interface UserInfoResult` — `{ status: 200 | 401, body: Record<string, unknown> }`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The matcher uses `^Bearer\s+(.+)$` (case-sensitive, unicode flag) so
|
||||
RFC-6750's exact-spelling requirement is enforced — "bearer" or
|
||||
"Token" headers are rejected as malformed. Token expiry is checked with
|
||||
`<= Date.now()` so a token whose `expiresAt` equals the current
|
||||
millisecond is treated as expired (defensive boundary). The default
|
||||
branch of the `userShape` switch is unreachable under the typed input
|
||||
and is `/* c8 ignore */`d to keep coverage clean.
|
||||
Reference in New Issue
Block a user