Access Policies
Use access policies with the current published Askr packages.
@askrjs/askr0.0.59
How to use access policies
Return an explicit allow, redirect, unauthorized, or forbidden decision from the route policy and repeat the enforcement on server APIs.
- Import the published @askrjs/askr entrypoint.
- Keep access policies configuration next to the component, route, or server composition root that owns it.
- Handle pending, unavailable, cancellation, and failure states, then verify the production path.
route('/admin', AdminPage, {
policy: ({ auth }) =>
auth.permissions.includes('admin') ? allow() : forbidden(),
});Policy decisions
A `RoutePolicy` is a function from `RouteContext` to an `AccessDecision`, returned either synchronously or as a promise. There are exactly three decision shapes: `allow()`, `redirect(to, init?)`, and `deny(status)`, and helper functions `unauthorized()`, `forbidden()`, and `notFound()` cover the common deny statuses (401, 403, 404) without you having to remember the numbers. Policies attach to a route, a `page()`, or a whole `group()` via `CommonAccessOptions.policies`, and a group's policies run for every route nested inside it in addition to whatever the specific route adds.
Authentication context
`currentAuth()` returns the `AuthContext` resolved for the route currently rendering, and it's the same object available as `context.auth` inside a policy or loader. Resolving that context is configurable per-app through `RouteAuthOptions.resolve`, a `RouteAuthResolver` that runs before policies and produces the `AuthContext` they'll see — so the actual mechanism (cookie, token, session lookup) lives in one place rather than being re-implemented in every policy. `RegisterRoutesOptions.auth` sets this resolver at the manifest level, and individual routes can still opt into stricter requirements via `CommonAccessOptions.auth`.
Redirects and denials
`redirect(to, init?)` returns an `AccessRedirectDecision` with a configurable HTTP status (301, 302, 303, 307, or 308) and an optional `replace` flag so the redirect doesn't leave the denied URL in browser history. `RouteAuthOptions.loginPath` and `authenticatedRedirectTo` cover the two most common redirect cases directly — where to send an unauthenticated user, and where to send an already-authenticated user who hits a route like a login page — either as a static path or a function of the request context. A `deny()` decision, by contrast, renders in place with the given status rather than sending the browser anywhere.
Server enforcement
Because policies run inside `resolveRouteRequest()` before a `RouteRenderResult` is produced, the same access rules apply whether the request is being resolved for SSR, SSG, or client-side navigation — a policy isn't a client-only convenience that a curious user can bypass by hitting the server route directly. `RouteRequestOptions.request` carries the actual `Request` object through to loaders and policies during SSR, so server-only decisions (cookies, headers, IP) are available exactly where they're evaluated, not bolted on afterward.