Handle requests
Reading and parsing request headers, validating sessions, and setting appropriate response headers for every protected endpoint is a bit tedious. To address this issue, Lucia provides Auth.handleRequest()
which creates a new AuthRequest
instance. This provides a few methods that make working with session cookies and bearer tokens easier. Refer to Using cookies and Using bearer tokens page on more about those methods.
const authRequest = auth.handleRequest();
const session = authRequest.validate();
authRequest.setSession(session);
const session = authRequest.validateBearerToken();
However, every framework and runtime has their own representation of an incoming request and outgoing response, such as the web standard Request
/Response
and Node.js’ IncomingMessage
/OutgoingMessage
. Lucia uses its own implementation of RequestContext
as well, which is the default parameter type of Auth.handleRequest()
. Since this is an annoying problem that is easy to solve, Lucia provides middleware.
Middleware allows you to pass framework and runtime specific request objects to Auth.handleRequest
. While we provide a number of them, it’s easy to create and if you do, consider contributing to the project!
import { node } from "lucia/middleware";
lucia({
// ...
middleware: web() // pass Web middleware
});
// `Auth.handleRequest()` now accepts `Request`
const authRequest = auth.handleRequest(new Request());
List of middleware#
- Astro
- Elysia
- Express
- Fastify
- H3
- Hono
- Next.js
- Node.js
- Qwik
- SvelteKit
- Web standard
- Remix
- Cloudflare workers
Lucia (default)#
The default middleware is the Lucia middleware. Auth.handleRequest()
accepts RequestContext
.
import { lucia } from "lucia/middleware";
Astro#
import { astro } from "lucia/middleware";
---
// .astro component
const authRequest = auth.handleRequest(Astro);
---
// API routes and middleware
export const get = async (context) => {
const authRequest = auth.handleRequest(context);
// ...
};
We recommend storing AuthRequest
in locals
.
Elysia#
import { elysia } from "lucia/middleware";
new Elysia().get("/", async (context) => {
const authRequest = auth.handleRequest(context);
});
Express#
import { express } from "lucia/middleware";
app.get("/", (req, res) => {
const authRequest = auth.handleRequest(req, res);
});
Fastify#
import { fastify } from "lucia/middleware";
server.get("/"(request, reply) => {
const authRequest = auth.handleRequest(request, reply);
});
H3#
import { h3 } from "lucia/middleware";
Nuxt#
// api routes (server/api/index.ts)
export default defineEventHandler(async (event) => {
const authRequest = auth.handleRequest(event);
// ...
});
Hono#
import { hono } from "lucia/middleware";
app.get("/", async (context) => {
const authRequest = auth.handleRequest(context);
});
Next.js#
nextjs_future()
will replace nextjs()
in the next next major release. While nextjs()
isn’t deprecated, we recommend considering it as a legacy API.
import { nextjs_future } from "lucia/middleware";
Pages router#
// pages/index.tsx
export const getServerSideProps = async (context) => {
const authRequest = auth.handleRequest(context);
};
// pages/index.ts
export default async (req: IncomingMessage, res: OutgoingMessage) => {
const authRequest = auth.handleRequest({ req, res });
};
// pages/index.ts (deployed to edge)
export default async (request: NextRequest) => {
// `AuthRequest.setSession()` is not supported when only `Request` is passed
auth.handleRequest(request);
// ...
const session = await auth.createSession({
// ...
});
const sessionCookie = auth.createSessionCookie(session);
const response = new Response(null);
response.headers.append("Set-Cookie", sessionCookie.serialize());
};
App router#
We recommend setting sessionCookie.expires
configuration to false
when using this middleware.
// app/page.tsx
import * as context from "next/headers";
export default () => {
const authRequest = auth.handleRequest("GET", context);
const experimentalFormActions = async () => {
const authRequest = auth.handleRequest("POST", context);
};
// ...
};
// app/routes.ts
import * as context from "next/headers";
export const POST = async (request: NextRequest) => {
const authRequest = auth.handleRequest(request.method, context);
// ...
};
Middleware#
// middleware.ts
export const middleware = async (request: NextRequest) => {
// `AuthRequest.setSession()` is not supported when only `NextRequest` is passed
const authRequest = auth.handleRequest(request);
// ...
const session = await auth.createSession({
// ...
});
const sessionCookie = auth.createSessionCookie(session);
const response = new Response(null);
response.headers.append("Set-Cookie", sessionCookie.serialize());
};
Node.js#
import { node } from "lucia/middleware";
const authRequest = auth.handleRequest(incomingMessage, outgoingMessage);
Qwik#
import { qwik } from "lucia/middleware";
const authRequest = auth.handleRequest(requestEvent as RequestEventLoader);
const authRequest = auth.handleRequest(requestEvent as RequestEventAction);
SvelteKit#
import { sveltekit } from "lucia/middleware";
// +page.server.ts
export const load = async (event) => {
const authRequest = auth.handleRequest(event);
// ...
};
export const actions = {
default: async (event) => {
const authRequest = auth.handleRequest(event);
// ...
}
};
// hooks.server.ts
export const handle = async ({ event, resolve }) => {
event.locals.auth = auth.handleRequest(event);
// ...
};
Web standard#
AuthRequest.setSession()
is disabled when using the web()
middleware. We recommend setting sessionCookie.expires
configuration to false
when using this middleware.
import { web } from "lucia/middleware";
const authRequest = auth.handleRequest(request as Request);
const authRequest = auth.handleRequest(request);
await authRequest.validate();
await authRequest.setSession(session); // error!
Remix#
export const loader = async ({ request }: LoaderArgs) => {
const authRequest = auth.handleRequest(request);
return json({});
};