Authentication
Purpose and Scope
Authentication in an Astro application is the process of verifying who a visitor is, while authorization is the follow-up decision about what that verified visitor may access. Astro does not hard-code a single identity provider into the framework. Instead, the documented workflow is to mount an authentication library or backend service in server routes, call backend logic through Actions when type-safe client-to-server communication is useful, and keep per-visitor state in server-side sessions. The session subsystem in this repository is the part that turns a login result into durable request-to-request state.
Astro sessions are especially relevant for authentication because they store data on the server and identify that data with an HTTP-only cookie. That separation is different from storing a user object directly in a browser cookie: the browser only receives the session identifier, while the session data lives behind a configured storage driver. In an auth flow, a login route or action can validate credentials with Better Auth, Clerk, Supabase, Firebase, Scalekit, or another service, then write a compact user/session record into Astro.session. Later pages, endpoints, middleware, or actions can read the same state before rendering protected content.
Sources: packages/astro/src/core/session/runtime.ts, packages/astro/src/core/session/handler.ts
Relevant Source Files
packages/astro/src/core/session/config.tsdefines the Zod schema forsessionconfiguration, includingdriver, deprecatedoptions, cookie settings, andttl.packages/astro/src/core/session/types.tsdefines the public TypeScript shapes for session drivers, driver factories, driver configuration, base session configuration, and deprecated compatibility forms.packages/astro/src/core/session/drivers.tsexportssessionDrivers, a helper object generated from unstorage built-in drivers with Astro-specific handling for file-system storage.packages/astro/src/core/session/handler.tswires sessions into the request pipeline by registering a lazyAstroSessionprovider on fetch state and persisting mutations during finalization.packages/astro/src/core/session/runtime.tsimplementsAstroSession, cookie defaults, server-side storage access, serialization behavior, dirty tracking, and persistence error handling.packages/astro/src/core/session/utils.tsnormalizes configured drivers and converts user config into the SSR manifest session shape used at runtime.
Authentication Building Blocks
A typical Astro authentication flow has four building blocks. A server route accepts provider callbacks or credential submissions. An Action can provide a type-safe backend function for login, logout, profile updates, or protected mutations. Middleware can centralize authorization checks and redirects before a page or endpoint runs. Sessions then carry the authenticated state across requests without requiring client-side JavaScript. The official authentication guide shows this composition by mounting a provider handler in src/pages/api/auth/[...all].ts; the session source here explains the server-side state layer that such handlers can use after identity has been established.
The session configuration surface is intentionally small but important. SessionSchema accepts an optional driver, optional deprecated options, optional cookie, and optional ttl. The cookie setting can be a string, where the string becomes the cookie name, or an object with fields such as name, domain, path, maxAge, sameSite, and secure. For auth workflows, these fields control how the browser carries the session identifier, while ttl controls the default lifetime of server-side session entries. The schema also warns when the deprecated string driver signature is used, guiding projects toward the newer object-shaped driver configuration.
Sources: packages/astro/src/core/session/config.ts, packages/astro/src/core/session/types.ts
Session Configuration Reference
| Name | Source-level contract | Authentication relevance |
|---|---|---|
session.driver | A SessionDriverConfig object, a built-in unstorage driver name, or deprecated custom string form | Selects where authenticated session state is stored |
session.driver.entrypoint | URL or package import in SessionDriverConfig | Points Astro at the driver implementation that can read and write session records |
session.driver.config | Serializable driver options | Supplies storage connection settings, cache limits, or file-system base paths |
session.options | Deprecated compatibility path for driver options | Exists for migration; new code should pass options to driver helpers |
session.cookie | Cookie name string or cookie option object | Controls the session identifier cookie sent to the browser |
session.ttl | Number of seconds | Sets the default duration for stored session data |
The driver contract is deliberately minimal: a session driver must implement getItem, setItem, and removeItem, each keyed by a string and returning promises. Astro wraps these operations through unstorage, so an authentication flow does not need to know whether state is stored in memory, on disk, or in an external service. SessionDriverFactory receives a configuration object and returns a SessionDriver, making driver setup serializable at build time while still allowing projects to provide custom entrypoints when runtime configuration is required.
sessionDrivers is a convenience export built from unstorage’s built-in drivers. The implementation filters out driver names that contain dashes and returns factory functions that produce Astro’s SessionDriverConfig shape. The fs driver is special-cased to use fsLite and defaults its base directory to .astro/session, because the regular file-system driver cannot be bundled the same way. For authentication, this means local development can use a simple file-backed session store, while production deployments can choose a driver appropriate for the adapter and hosting environment.
Sources: packages/astro/src/core/session/types.ts, packages/astro/src/core/session/drivers.ts
Runtime Execution Flow
At request time, Astro registers session support through provideSession. The function marks the pipeline as using sessions, checks whether the SSR manifest contains session configuration, and returns immediately when sessions are not configured. That no-op path matters for performance because it avoids unnecessary promise allocation on requests that do not use sessions. When configuration exists, Astro obtains a session driver factory from the pipeline and registers a lazy provider named session on the fetch state. The AstroSession object is created only when request code resolves or accesses the session.
The request lifecycle also defines when authentication-related session mutations become durable. The provider’s create callback constructs AstroSession with the current cookies, normalized manifest config, runtime mode, driver factory, and optional mock storage. Its finalize callback invokes an internal persistence symbol on the session. This means login, logout, and profile-update code can mutate session data during the request, and Astro will persist those changes when state.finalizeAll() runs. The model keeps route and action code focused on user intent while the pipeline handles storage writes consistently.
Sources: packages/astro/src/core/session/handler.ts, packages/astro/src/core/session/runtime.ts
Cookie and Storage Behavior
AstroSession defaults the session cookie name to astro-session. When the configured cookie is an object, Astro separates the cookie name from the rest of the cookie options; when it is a string, the string becomes the name. The runtime then applies secure defaults: sameSite is lax, path is /, secure is true in production runtime mode, and httpOnly is always set. These defaults are important for authentication because they reduce accidental client-side exposure of the session identifier and make the cookie usable across application routes.
The runtime stores session data as keyed entries and tracks local state carefully. It keeps a session ID, a map of session entries, dirty state, deletion sets, and a partial-data flag. The partial-data behavior lets Astro avoid loading the entire session from storage when code only writes values during a request; if storage is later loaded, in-memory changes and deletions must be preserved. Serialization uses devalue with explicit support for URL objects, so session values can round-trip data that JSON alone would not represent as precisely. Storage initialization and save failures are reported through Astro errors.
Sources: packages/astro/src/core/session/runtime.ts
System-to-Code Mapping
| Authentication concern | Astro subsystem | Source-backed behavior |
|---|---|---|
| Remembering a logged-in visitor | AstroSession | Stores server-side values and identifies them with an HTTP-only cookie |
| Choosing storage | Session config and drivers | Normalizes built-in, file-system, URL, package, and custom driver entrypoints |
| Persisting login/logout mutations | Fetch-state provider finalization | Saves dirty session state at the end of the request lifecycle |
| Local development storage | sessionDrivers.fs() and normalization | Uses fsLite with .astro/session as the default base |
| Session lifetime | ttl and cookie options | Controls stored entry duration and browser cookie behavior |
Driver normalization is the bridge between project configuration and the runtime manifest. normalizeSessionDriverConfig accepts either a string or a SessionDriverConfig object. URL entrypoints are converted to file paths, unstorage built-in names are mapped to their package entrypoints, and fs, fs-lite, and fsLite all map to fsLite with the .astro/session base default. sessionConfigToManifest then emits the driver, options, cookie, and ttl fields that the SSR runtime consumes. That manifest boundary is why authentication code can rely on Astro.session instead of managing driver imports on each request.
Sources: packages/astro/src/core/session/utils.ts, packages/astro/src/core/session/types.ts
Example Flow
// src/pages/api/auth/[...all].ts
import { auth } from '../../../lib/auth';
import type { APIRoute } from 'astro';
export const prerender = false;
export const ALL: APIRoute = async (ctx) => {
return auth.handler(ctx.request);
};Use a server route like the example above to hand provider-specific requests to an authentication library. After the provider verifies identity, your app can write only the durable state it needs, such as a user ID, role list, or post-login redirect target, into the session. For form-based flows, an Astro Action can validate inputs and standardize backend errors before updating session data. For protected pages, middleware or page frontmatter can read the session and redirect anonymous visitors. Keep sensitive provider tokens in secure server-side storage, and store only the minimal session data needed to authorize the next request.
Next, read the pages on actions, middleware, and sessions together. Actions explain the typed backend function surface, middleware explains request gating, and sessions explain the persistence layer documented here. If you are deploying to a server or edge platform, also review adapter documentation because adapters may provide default session drivers or require explicit driver configuration. Treat authentication as an application-level workflow assembled from these primitives rather than as a single framework switch.
Sources: packages/astro/src/core/session/config.ts, packages/astro/src/core/session/handler.ts, packages/astro/src/core/session/runtime.ts