first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -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.