Aura Auth
Integrations

Supabase Edge Functions

Build your first authentication flow with Aura Auth and Supabase Edge Functions

This guide walks you through creating a complete authentication flow using Aura Auth in Supabase Edge Functions (built on Deno).

Overview

Supabase Edge Functions run on Deno and use the web-standard Fetch API (Request and Response). That makes them a natural fit for Aura Auth's framework-agnostic runtime model.

Before continuing, complete the installation and initial setup:

Then use this guide to integrate Aura Auth with a Supabase Edge Function using best practices.


What You'll Build

You will create a small Supabase project with:

  • a shared functions/_shared/auth.ts server configuration
  • a function route at functions/auth/index.ts that mounts the auth handlers
  • a config.toml file that points the route to the correct entrypoint
  • a protected route example that checks the active session before responding

Project Structure

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

Set up config.toml

This defines the edge function's route and permissions. Ensure the index.ts entrypoint is correctly referenced so Supabase can locate the function.

config.toml
[functions.auth]
enabled = true
# disable JWT verification for faster local development. DO NOT disable in production.
verify_jwt = false
import_map = "./functions/auth/deno.json"
# Uncomment to specify a custom file path to the entrypoint.
# Supported file extensions are: .ts, .js, .mjs, .jsx, .tsx
entrypoint = "./functions/auth/index.ts"

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 an auth.ts file in functions/_shared/ to configure authentication and export the shared helpers used by the function route.

supabase-app/functions/_shared/auth.ts
import { createAuth } from "@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 your Supabase function. If the route changes, update the auth config and function route together.

Mount HTTP Handlers

Using Supabase Edge Function execution, define your handler with Deno.serve. The function below routes auth requests to Aura Auth and keeps protected route logic separate from the handler itself.

supabase/functions/auth/index.ts
import { handlers, api } from "../_shared/auth.ts"

// Follow this setup guide to integrate the Deno language api with your editor:
// https://deno.land/manual/getting_started/setup_your_environment
// This enables autocomplete, go to definition, etc.
import "@supabase/functions-js/edge-runtime.d.ts"

Deno.serve(async (request) => {
  const pathname = new URL(request.url).pathname
  switch (pathname) {
    case "/api/protected": {
      const session = await 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.",
        session: session.session,
      })
    }
    default: {
      if (pathname.startsWith("/api/auth/")) {
        return await handlers.ALL(request)
      }
      return new Response("Not Found", { status: 404 })
    }
  }
})

This structure keeps all auth endpoints in one place and gives you a clear place to add additional protected routes later.


Common Pitfalls

  • Keep basePath aligned with the function route. If your auth endpoint is /api/auth/*, the auth config should use basePath: "/api/auth".
  • Make sure config.toml points at the correct entrypoint. Supabase needs to know where functions/auth/index.ts lives.
  • Pass the current request headers to api.getSession(). The session lookup needs headers so Aura Auth can read cookies correctly.
  • Check session.authenticated before returning private data. Use the authenticated flag as your guard for protected responses.

Resources

On this page