How to Use Auth.js in Astro

Auth.js (previously NextAuth) is a powerful authentication core library for JavaScript apps. Thanks to it’s framework-agnostic design & the auth-astro framework adapter, it’s easier than ever to add authentication to your Astro site.

Setup

Create a new Astro project, or navigate to an existing one:

Terminal window
npm create astro@latest -- my-app --template minimal -y

Install a platform adapter (e.g. @astrojs/node) to allow for server-side rendering:

Terminal window
npx astro add node

Install the unofficial Astro adapter & the core for Auth.js, along with a platform adapter for Astro (e.g. @astrojs/node):

Terminal window
npm install @auth/core auth-astro

Navigate to astro.config.mjs and import the auth-astro adapter:

import { defineConfig } from 'astro/config';
import node from "@astrojs/node";
import auth from 'auth-astro';
export default defineConfig({
integrations: [
auth(),
],
output: "server",
adapter: node({
mode: "standalone"
}),
});

Create an auth.config.ts configuration file in the root of your project:

export default {
providers: [
// ...
],
}

Configure Environment Variables

Signing Secret

Auth.js requires a secret to be set in order to sign the session cookie. This secret should be set to a random string of 32 characters. The documentation suggests on Linux, you generate one using openssl rand -hex 32, or you can navigate to generate-secret.vercel.app to generate one in the browser.

NOTE For non-vercel deployments, you’ll need to set the AUTH_TRUST_HOST environment variable to true.

.env
AUTH_SECRET=<your-secret>
AUTH_TRUST_HOST=true

OAuth Providers

Next, we need to configure the authentication providers we want to use. For this demo, we’ll use GitHub. Go back to auth.config.ts and add the following code:

NOTE You’ll need to set the GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET environment variables in .env. You can find out how to create a GitHub OAuth app here.

import GitHub from '@auth/core/providers/github'
export default {
providers: [
GitHub({
clientId: import.meta.env.GITHUB_CLIENT_ID,
clientSecret: import.meta.env.GITHUB_CLIENT_SECRET,
}),
],
}

Point your app’s redirect URL to [origin]/auth/callback/[provider] depending on your provider. For example, if you’re using GitHub, your redirect URL should be [origin]/auth/callback/github.

Signing In & Out

Now that we’ve configured Auth.js, we need to allow our users to sign in & out. Open src/pages/index.astro and add the following code. This will render a sign in button if the user is not signed in, and a sign out button if they are. We get the session object from the Auth component, and use it to determine which button to render.

---
import type { Session } from '@auth/core/types';
import { Auth, SignIn, SignOut } from 'auth-astro/components';
---
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width" />
<meta name="generator" content={Astro.generator} />
<title>Astro</title>
</head>
<body>
<h1>Astro</h1>
<Auth>
{(session: Session) => {
if (session) {
return (
<>
<p>Logged in as {session.user.name}</p>
<SignOut>Sign Out</SignOut>
</>
);
} else {
return <SignIn provider="github">Sign In</SignIn>;
}
}}
</Auth>
</body>
</html>

Protecting Routes

Now that we’ve got a sign in flow, we can add a protected route. Create a new file at src/pages/protected.astro. We want to only allow signed in users to access this page, so we’ll use the getSession server method to get the session object. If the user is not signed in, we’ll redirect them to the home page.

---
import { getSession } from 'auth-astro/server';
let session = await getSession(Astro.request)
if (!session) return Astro.redirect("/")
---
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width" />
<meta name="generator" content={Astro.generator} />
<title>Astro</title>
</head>
<body>
<h1>Astro</h1>
<p>Only signed in users can see this page.</p>
</body>
</html>

Add a link to the protected page in src/pages/index.astro to test it out:

<a href="/protected">Protected page</a>

That’s all!

With the new version of auth-astro we’ve made it easier than ever to add authentication to your Astro site with as little effort as possible. If you have any questions, feel free to reach out to me on Discord or Twitter, or report any issues on GitHub.