Framework Auth Routes
Framework Auth Routes at the Askr server boundary, with validated input and explicit failure states.
Example
Resolve identity at the request boundary and express authorization as reusable requirements instead of component-only checks.
import {
createAuth,
requirePermission,
requireUser,
} from '@askrjs/auth';
export const auth = createAuth({
sessions: sessionStore,
principals: principalStore,
});
export const manageProjects = [
requireUser(),
requirePermission('projects:write'),
];/auth/v1 contract
registerAuthRoutes(api, options) from @askrjs/server/auth attaches register, login, session, and logout endpoints. It mounts them under a fixed /auth/v1 group it creates internally by calling api.group('/auth/v1') itself - the prefix used throughout this guide is not a convention you're choosing, it's what the function does.
Login and callback
AuthRouteOptions.register(context, credentials) and authenticate(context, credentials) are functions you supply to create or verify a Principal from an AuthCredentials {email, password} pair - registerAuthRoutes calls whichever matches the route being hit. allowAttempt(context, operation, normalizedEmail) runs before either of them, letting you reject or throttle repeated attempts against the same address before register or authenticate ever executes.
Session and logout
On a successful register or authenticate, options.issuer.issue(principal) - a TokenIssuer<P> you provide - produces the token that gets written to the cookie described by options.cookie (standard CookieOptions plus a name). An optional redirect(context, operation, principal) callback can return a URL to send the client to instead of a bare JSON response, which is how the built-in routes support both API and browser-form flows from the same registration.
Safe redirects
safeRedirect(fallback, options?: {allowHash?}) returns a validator function that only accepts same-origin redirect targets, falling back to the given default for anything it doesn't recognize as safe - use it on a redirect or next query parameter before honoring it, since forwarding an unvalidated one is an open-redirect vulnerability. A duplicate email on register or a failed authenticate() call surfaces as an AuthRouteError with a fixed status of 401 or 409 rather than a generic error; a throttled attempt is a separate path - allowAttempt returning false short-circuits straight to a 429 response without going through AuthRouteError at all.