first commit
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
# Direct factory — `@suaveplan/api-auth-bearer-static`
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
`createBearerStaticResolver` is the direct-surface entry point of the
|
||||
package. It accepts validated `BearerStaticResolverOptions`, builds a
|
||||
`SessionResolver` over the fixed token table, and returns a resolver
|
||||
implementation suitable for placing inside a `SessionResolverChain` from
|
||||
`@suaveplan/api-auth`. The resolver matches the documented chain
|
||||
semantics: an unknown token, missing header, or tripped mTLS gate all
|
||||
return `null` so the chain advances to the next entry.
|
||||
|
||||
The resolver is stateless beyond the disposed flag — there is no DB
|
||||
connection, no JWKS cache, no refresh loop. Disposal flips the flag and
|
||||
subsequent calls return `null` rather than throwing.
|
||||
|
||||
## Features
|
||||
|
||||
- Stateless per-request resolution; safe under concurrent fanout.
|
||||
- Constant-time token match via `findTokenIndex`.
|
||||
- Optional per-entry mTLS gate via `checkMtlsGate`.
|
||||
- Configurable `headerName` and prefix (`Bearer` by default).
|
||||
- Case-insensitive scheme match per RFC 7235.
|
||||
- OTel counter emission for every of the four outcomes.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { createBearerStaticResolver } from "@suaveplan/api-auth-bearer-static";
|
||||
|
||||
const resolver = createBearerStaticResolver({
|
||||
tokens: [
|
||||
{
|
||||
token: "service-cron-2026",
|
||||
principal: {
|
||||
id: "svc_cron",
|
||||
scopes: ["jobs:run"],
|
||||
claims: { kind: "service" },
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const req = new Request("https://api/x", {
|
||||
headers: { Authorization: "Bearer service-cron-2026" },
|
||||
});
|
||||
const principal = await resolver.resolve(req);
|
||||
// principal.id === "svc_cron"
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
import { createBearerStaticResolver } from "@suaveplan/api-auth-bearer-static";
|
||||
import { SessionResolverChain } from "@suaveplan/api-auth";
|
||||
import { createJwtResolver } from "@suaveplan/api-auth-jwt"; // hypothetical sibling
|
||||
|
||||
// Chained — service tokens checked first, JWT users fall through after.
|
||||
const chain = new SessionResolverChain([
|
||||
createBearerStaticResolver({
|
||||
tokens: [
|
||||
{
|
||||
token: "admin-2026",
|
||||
principal: {
|
||||
id: "svc_admin",
|
||||
scopes: ["admin:*"],
|
||||
claims: {},
|
||||
},
|
||||
mtlsRequired: true,
|
||||
},
|
||||
],
|
||||
headerName: "X-Service-Auth",
|
||||
prefix: "Token",
|
||||
}),
|
||||
createJwtResolver({ issuer: "https://idp/..." }),
|
||||
]);
|
||||
|
||||
const result = await chain.resolve(request);
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `createBearerStaticResolver(options: BearerStaticResolverOptions): SessionResolver`
|
||||
|
||||
Returned resolver:
|
||||
|
||||
- `resolve(request: Request): Promise<Principal | null>`
|
||||
- `dispose(): Promise<void>` — idempotent.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
`extractToken` accepts the header value, trims, splits on the first space,
|
||||
and lower-cases the scheme for the prefix comparison. Empty credentials
|
||||
after the prefix are rejected. The implementation reads the configured
|
||||
header by exact name (the Web `Headers` API normalises case on lookup, so
|
||||
`Authorization` and `authorization` both work). When the table contains
|
||||
the same token twice with conflicting principals, `findTokenIndex` returns
|
||||
the first index — operator misconfiguration the schema cannot prevent.
|
||||
TypeScript cannot narrow `table[idx]` to non-undefined even though
|
||||
`findTokenIndex` only ever returns `-1` or a valid in-range index; a type
|
||||
assertion encodes that contract at the call site without adding a runtime
|
||||
guard the test would have to exercise.
|
||||
Reference in New Issue
Block a user