Astro
Integrate Aura Auth and Astro
This guide walks you through implementing Aura Auth in an Astro application with complete support. If you haven't configured Aura Auth yet, start with the Installation Guide and Quick Start Guide to set up your Auth instance and environment variables. Then follow the steps in this guide to integrate Aura Auth with your Astro application.
Setup Aura Auth
Create an Auth Instance
Create an auth.ts file in src/lib directory to configure your Aura Auth instance.
import { createAuth } from "@aura-stack/auth"
export const auth = createAuth({
oauth: ["github"],
basePath: "/api/auth",
})
export const { handlers, jose, api } = authThe basePath should match the path where your auth route handlers are mounted and baseURL should point to your local
development server or deployed application URL.
Create an Auth Client Instance
Create an auth-client.ts file in src/lib directory to enable client-side features.
import { createAuthClient } from "@aura-stack/auth/client"
export const authClient = createAuthClient({
basePath: "/api/auth",
baseURL: "http://localhost:3000",
})The basePath should match the path where your auth route handlers are mounted and baseURL should point to your local
development server or deployed application URL. Both options should be the same as the ones used in your auth.ts configuration
to ensure client and server instances are aligned.
Mount HTTP Handlers
Create a catch-all route under src/pages/api/auth/[...auth].ts. The route below forwards each HTTP method to the corresponding Aura Auth handler.
import { handlers } from "@/lib/auth"
import type { APIRoute } from "astro"
export const GET: APIRoute = async ({ request }) => {
return await handlers.GET(request)
}
export const POST: APIRoute = async ({ request }) => {
return await handlers.POST(request)
}
export const PATCH: APIRoute = async ({ request }) => {
return await handlers.PATCH(request)
}basePath option in createAuth matches the actual route (/api/auth).Server Side Rendering (SSR)
Get Session
---
import { api } from "@/lib/auth"
const result = await api.getSession({
headers: Astro.request.headers,
})
if (!result.authenticated) {
return Astro.redirect("/login")
}
const session = result.session
---
<h1>Welcome back, {session.user?.name}</h1>
<p>Email: {session.user?.email}</p>This is the recommended pattern for protected pages: check authentication on the server and only render private UI when a session is present.
Sign-Out
---
import { api } from "@/lib/auth"
const signOutAction = async () => {
const response = await api.signOut({
headers: Astro.request.headers,
})
return response
}
---
<form method="post">
<button type="submit">Sign Out</button>
</form>If you prefer a client-only interaction, call authClient.signOut() from a client component instead.
Client Side Rendering (CSR)
Sign-In
import { authClient } from "@/lib/auth-client"
export default function SignInButton() {
const handleSignIn = () => {
void authClient.signIn("github", {
redirectTo: "/dashboard",
})
}
return <button onClick={handleSignIn}>Sign in with GitHub</button>
}Use a client component for one-click auth entry points or custom UI that cannot be expressed as a server action.
Get Session
import { useEffect, useState } from "react"
import { authClient } from "@/lib/auth-client"
export default function UserProfile() {
const [session, setSession] = useState(null)
useEffect(() => {
const fetchSession = async () => {
const { session } = await authClient.getSession()
setSession(session)
}
fetchSession()
}, [])
if (!session) return <p>Loading...</p>
return (
<div>
<h1>Welcome back, {session.user?.name}</h1>
<p>Email: {session.user?.email}</p>
</div>
)
}This approach is useful for nav bars, avatars, and other session-aware UI that updates after hydration.
Sign-Out
import { authClient } from "@/lib/auth-client"
export default function SignOutButton() {
const handleSignOut = async () => {
await authClient.signOut()
}
return <button onClick={handleSignOut}>Sign Out</button>
}Client-side sign-out is best for interactive controls inside menus or profile popovers.
Common Pitfalls
- Keep
basePathaligned with the route segment. If your auth endpoint is/api/auth/*, the auth config should usebasePath: "/api/auth". - Keep the shared auth module in one place. Import
src/lib/auth.tsfrom both the API route and the client helper. - Check authentication before rendering private UI. Use the server-side
authenticatedflag to protect pages. - Use
Astro.request.headerswhen calling server helpers. That gives Aura Auth access to the cookies it needs to read the session.