Deno
Authenticate users in your TypeScript applications with Aura Auth and Deno's native server
This guide walks you through creating a complete authentication flow using Aura Auth directly with Deno.
Overview
Aura Auth and Deno both follow the web-standard Request and Response interfaces for high-performance HTTP handling. This means Aura Auth works out of the box with Deno.serve, with no external adapters or frameworks required.
Before continuing, complete the installation and initial setup:
- Quick Start Guide to create your Aura Auth instance
- TypeScript Configuration for TypeScript-specific setup
- Deno Integration App for a fully working example
Then use this guide to integrate Aura Auth with a Deno server using best practices.
What You'll Build
You will create a small Deno app with:
- a shared
src/lib/auth.tsserver configuration - a
src/index.tsentry point that mounts the auth handlers - a protected route example that validates the current session before responding
- a clear route setup that keeps auth and protected endpoints separate
Project Structure
Environment Setup
Create a .env.local file at the root of your project to store secrets securely.
# 32-bytes (256-bit) secret used to sign/encrypt sessions. Use a secure random value.
AURA_AUTH_SECRET="base64-or-hex-32-bytes"
AURA_AUTH_SALT="base64-or-hex-32-bytes".env.local file to version control. Use a secret manager in production.Setup Aura Auth
Create auth.ts in src/lib/ to configure Aura Auth and export the shared helpers used by the Deno server.
import { createAuth } from "npm:@aura-stack/auth"
export const auth = createAuth({
oauth: ["github"],
basePath: "/api/auth",
})
export const { handlers, jose, api } = authbasePath must match the route you expose in Deno.serve. baseURL is optional for local development but should be set to your deployed domain in production.
Mount HTTP Handlers
Define auth routes directly in Deno.serve. Any request matching /api/auth/* is handled by handlers.ALL.
import { handlers } from "./lib/auth.ts"
Deno.serve({ port: 3000 }, async (request) => {
const pathname = new URL(request.url).pathname
if (pathname.startsWith("/api/auth/")) {
return await handlers.ALL(request)
}
return new Response("Not Found", { status: 404 })
})This keeps auth requests isolated from the rest of your application routes.
Usage
Get Session
Deno does not include framework-style middleware, but you can protect routes with a small helper-style handler that validates the current session.
import { auth, handlers } from "./lib/auth.ts"
Deno.serve({ port: 3000 }, async (request) => {
const pathname = new URL(request.url).pathname
if (pathname.startsWith("/api/auth/")) {
return await handlers.ALL(request)
}
if (pathname === "/api/protected") {
const session = await auth.api.getSession({
headers: request.headers,
})
if (!session.authenticated) {
return Response.json({ error: "Unauthorized", message: "Active session required." }, { status: 401 })
}
return Response.json({
message: "You have access to this protected resource.",
user: session.session.user,
})
}
return new Response("Not Found", { status: 404 })
})This pattern works well for small APIs or server-rendered entry points. For larger apps, consider splitting the auth route and protected routes into separate modules.
Common Pitfalls
- Keep
basePathaligned with your route logic. If your auth route is/api/auth/*,basePathshould be/api/auth. - Always pass request headers to
auth.api.getSession(). The session lookup needs headers so Aura Auth can read cookies. - Check
session.authenticatedbefore exposing private data. Use the authenticated flag to guard sensitive responses. - Keep the auth route and protected route separate. That makes the server behavior easier to reason about and debug.