first commit
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
# middleware/require-email-verified
|
||||
|
||||
## Purpose
|
||||
|
||||
`requireEmailVerified()` is the Hono middleware factory that gates a
|
||||
route on the principal's email having been verified. Routes that
|
||||
trigger sensitive operations (password change, billing portal,
|
||||
account deletion) use this guard so unverified accounts cannot move
|
||||
forward without first completing the verification flow.
|
||||
|
||||
## Features
|
||||
|
||||
- Reads `c.get("user")` directly — no Better-Auth lookup per request.
|
||||
- Two failure modes: `AUTH_UNAUTHENTICATED` (401) for anonymous
|
||||
callers and `AUTH_EMAIL_NOT_VERIFIED` (403) for unverified ones.
|
||||
- Strict boolean check: `emailVerified !== true` fails, so undefined
|
||||
/ null are treated as unverified.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import {
|
||||
requireAuth,
|
||||
requireEmailVerified,
|
||||
} from "@suaveplan/api-plugin-auth/middleware";
|
||||
|
||||
app.use("/billing/*", requireAuth(), requireEmailVerified());
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
Use the middleware as a precondition for routes that trigger
|
||||
high-trust workflows. Combine with `requireRole` so admin routes
|
||||
require BOTH verified email AND the admin role:
|
||||
|
||||
```ts
|
||||
import {
|
||||
requireAuth,
|
||||
requireEmailVerified,
|
||||
requireRole,
|
||||
} from "@suaveplan/api-plugin-auth/middleware";
|
||||
|
||||
app.use(
|
||||
"/admin/users/:id/delete",
|
||||
requireAuth(),
|
||||
requireEmailVerified(),
|
||||
requireRole("admin")
|
||||
);
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `function requireEmailVerified(): MiddlewareHandler`
|
||||
|
||||
- Throws `AuthError(AUTH_UNAUTHENTICATED)` (401) when `c.get("user")`
|
||||
is null/undefined.
|
||||
- Throws `AuthError(AUTH_EMAIL_NOT_VERIFIED)` (403) when
|
||||
`principal.emailVerified !== true`.
|
||||
- Calls `next()` otherwise.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The check uses `!== true` rather than `=== false` so an explicitly
|
||||
`undefined` / `null` `emailVerified` (which the default principal
|
||||
mapping should not emit, but a custom mapping might) is treated as
|
||||
unverified. Failing closed is the right default for an auth gate.
|
||||
- The middleware does not auto-trigger a re-send of the verification
|
||||
email — that is the route handler's responsibility once the 403
|
||||
reaches the client.
|
||||
- The 403 error carries `context.statusCode: 403` for the error
|
||||
handler; no other context fields are attached because the principal
|
||||
identity does not need to be re-emitted on a 403 (it is already
|
||||
available in the trace span).
|
||||
Reference in New Issue
Block a user