Replies: 3 comments
|
Well for bearer tokens, you need to manually attach the token in the Authorization header: And then you could do const authorizationHeader = req.headers.get("Authorization");
if (authorizationHeader === null) {
res.writeHeader(401);
return;
}
const parts = authorizationHeader.split(" ");
if (parts.length !== 2 || (parts[0] !== "Bearer") {
res.writeHeader(401);
return;
}
const sessionToken = parts[1];(this doesn't use a specific API) |
Authenticating API Routes with Lucia in Next.jsLucia uses session cookies, not Bearer tokens. Here's how to validate in API routes: App Router (Next.js 13+)// app/api/protected/route.ts
import { cookies } from "next/headers";
import { lucia } from "@/lib/auth"; // Your lucia instance
export async function GET() {
const cookieStore = await cookies();
const sessionId = cookieStore.get(lucia.sessionCookieName)?.value;
if (!sessionId) {
return Response.json({ error: "Unauthorized" }, { status: 401 });
}
const { session, user } = await lucia.validateSession(sessionId);
if (!session) {
return Response.json({ error: "Invalid session" }, { status: 401 });
}
// User is authenticated!
return Response.json({ user });
}Reusable helper// lib/auth.ts
export async function validateRequest() {
const cookieStore = await cookies();
const sessionId = cookieStore.get(lucia.sessionCookieName)?.value;
if (!sessionId) return { user: null, session: null };
return await lucia.validateSession(sessionId);
}
// Usage in any API route
export async function GET() {
const { user, session } = await validateRequest();
if (!user) return Response.json({ error: "Unauthorized" }, { status: 401 });
return Response.json({ data: "protected" });
}Client-side fetchNo need to add Bearer token - cookies are sent automatically: // Works because cookies are included by default
const res = await fetch("/api/protected");For external API calls (Bearer token)If you need Bearer tokens for mobile/external clients, you'd need to implement a separate token system alongside Lucia sessions. |
|
Lucia uses session cookies, not Bearer tokens. When a user logs in, Lucia sets a session cookie in the browser. That cookie is automatically sent with requests to your Next.js API routes — you just need to read it. Reading the session in API routes (App Router)// app/api/me/route.ts
import { NextRequest, NextResponse } from "next/server";
import { lucia } from "@/lib/auth"; // Your Lucia instance
import { cookies } from "next/headers";
export async function GET(req: NextRequest) {
const cookieStore = await cookies();
const sessionId = cookieStore.get(lucia.sessionCookieName)?.value ?? null;
if (!sessionId) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
const { session, user } = await lucia.validateSession(sessionId);
if (!session) {
return NextResponse.json({ error: "Invalid session" }, { status: 401 });
}
return NextResponse.json({ user });
}Create a reusable helper// lib/auth.ts (add this to your existing auth file)
import { cookies } from "next/headers";
import { cache } from "react";
import { lucia } from "./lucia"; // Your Lucia instance
export const getUser = cache(async () => {
const cookieStore = await cookies();
const sessionId = cookieStore.get(lucia.sessionCookieName)?.value ?? null;
if (!sessionId) return null;
const { session, user } = await lucia.validateSession(sessionId);
if (session && session.fresh) {
// Refresh the session cookie
const sessionCookie = lucia.createSessionCookie(session.id);
cookieStore.set(
sessionCookie.name,
sessionCookie.value,
sessionCookie.attributes
);
}
if (!session) {
const sessionCookie = lucia.createBlankSessionCookie();
cookieStore.set(
sessionCookie.name,
sessionCookie.value,
sessionCookie.attributes
);
}
return user;
});Then in any API route: // app/api/protected/route.ts
import { getUser } from "@/lib/auth";
export async function GET() {
const user = await getUser();
if (!user) {
return Response.json({ error: "Unauthorized" }, { status: 401 });
}
return Response.json({ data: "secret stuff", user });
}Why you don't see a Bearer tokenYou don't see an
If you need Bearer tokens (mobile apps, third-party clients)If you're building an API that's called from non-browser clients (React Native, CLI tools), you'd create a separate token system: // app/api/auth/token/route.ts
export async function POST(req: NextRequest) {
const user = await getUser(); // Validate session cookie
if (!user) return Response.json({ error: "Unauthorized" }, { status: 401 });
// Generate an API token (stored in your database)
const token = crypto.randomUUID();
await db.apiToken.create({
data: { token, userId: user.id, expiresAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000) },
});
return Response.json({ token });
}But for standard Next.js frontend-to-API-route communication, cookies are the way to go. |
Uh oh!
There was an error while loading. Please reload this page.
First off, thanks for making this library! I'm new to this and it really helped me learn a lot setting up auth.
For authenticating api side, what is the best way to do it? From what I understand, most uses Bearer token in the request headers, but how can I retrieve the Bearer token from lucia and attach it when the client is fetching data from the API? It doesn't exist when I console.log(req) even though I'm logged in.
Sorry if I asked some dumb questions, but appreciate any help!
All reactions