Initial Commit
This commit is contained in:
69
packages/api-stack/api/api-schemas/src/auth/context.md
Normal file
69
packages/api-stack/api/api-schemas/src/auth/context.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# context
|
||||
|
||||
## Purpose
|
||||
|
||||
Defines the `AuthContext` Zod schema representing the authenticated caller's identity as it flows through a request lifecycle. After a server middleware validates the incoming access token, it extracts the user's identifier, email, roles, and optional tenant identifier into an `AuthContext` object. This schema ensures that the shape of that context is validated on construction and typed consistently across every server plugin, middleware, and service function that consumes it.
|
||||
|
||||
## Features
|
||||
|
||||
- `AuthContext` schema — `{userId, email, roles, tenantId?}` with strict Zod validation
|
||||
- `roles` as a typed `string[]` — supports role-based access control checks without custom parsing
|
||||
- Optional `tenantId` for multi-tenant deployments — present only when the tenant scope is known
|
||||
- Non-empty validation on all string fields to prevent blank identity tokens
|
||||
- Full TypeScript inference via `z.infer<>` — no manual interface duplication
|
||||
- Zod v4 compatible
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { AuthContext } from "@suaveplan/api-schemas/auth";
|
||||
|
||||
// Validate the decoded JWT claims after signature verification
|
||||
const ctx = AuthContext.parse({
|
||||
userId: "user_01J8ZGCZ7ECTFAKEUID123456",
|
||||
email: "alice@example.com",
|
||||
roles: ["member"],
|
||||
});
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { AuthContext } from "@suaveplan/api-schemas/auth";
|
||||
|
||||
// Middleware that builds the AuthContext from a validated JWT
|
||||
function buildAuthContext(claims: JwtClaims): AuthContext {
|
||||
return AuthContext.parse({
|
||||
userId: claims.sub,
|
||||
email: claims.email,
|
||||
roles: claims.roles ?? [],
|
||||
tenantId: claims.tenant_id,
|
||||
});
|
||||
}
|
||||
|
||||
// RBAC helper using the context
|
||||
function requireRole(ctx: AuthContext, role: string): void {
|
||||
if (!ctx.roles.includes(role)) {
|
||||
throw new Error("Forbidden");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `AuthContext`
|
||||
|
||||
Zod object schema — authenticated request context.
|
||||
|
||||
| Field | Type | Description |
|
||||
|------------|--------------------|-----------------------------------------------------|
|
||||
| `userId` | `string` (min 1) | Unique identifier of the authenticated user |
|
||||
| `email` | `string` (email) | Email address of the authenticated user |
|
||||
| `roles` | `string[]` | Role identifiers for RBAC checks |
|
||||
| `tenantId` | `string` (optional)| Tenant scope for multi-tenant deployments |
|
||||
|
||||
**Type export:** `type AuthContext = z.infer<typeof AuthContext>`
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
`AuthContext` does not include the raw token or session identifier intentionally — the context represents decoded, validated identity, not the credential itself. Services that need to revoke or refresh tokens should do so through a separate token store, not through the auth context. The `roles` array is left as a plain `string[]` to remain agnostic about whether roles are stored as flat strings, hierarchical paths, or RBAC/ABAC expressions; the data layer is responsible for populating it correctly.
|
||||
Reference in New Issue
Block a user