Aura Auth
Integrations

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:

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.ts server configuration
  • a src/index.ts entry 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

auth.ts
index.ts
.env.local
deno.json

Environment Setup

Create a .env.local file at the root of your project to store secrets securely.

.env.local
# 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"
Never commit your .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.

src/lib/auth.ts
import { createAuth } from "npm:@aura-stack/auth"

export const auth = createAuth({
  oauth: ["github"],
  basePath: "/api/auth",
})

export const { handlers, jose, api } = auth

basePath 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.

index.ts
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.

index.ts
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 basePath aligned with your route logic. If your auth route is /api/auth/*, basePath should be /api/auth.
  • Always pass request headers to auth.api.getSession(). The session lookup needs headers so Aura Auth can read cookies.
  • Check session.authenticated before 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.

Resources

On this page