User Avatar

Authentication

StartStack uses NextAuth.js v5.

v5 is a major rewrite from v4 and is built for the app router first.

  • View the full configuration in /auth.ts.
  • Sign in page is located at /app/(auth)/sign-in/_components/sign-in-form.tsx.
  • Sign up page is located at /app/(onboarding)/sign-up/_components/sign-up-form.tsx.

Note: For One Time Purchase products StartStack does NOT require a session, it will email the user a magic link to authenticate after they make a purchase. To keep this functionality you will need to ensure the Email Provider (Resend) is configured. Subscription products will require a session (sign up/in) before they can subscribe to a plan.

NextAuth.js v5 Features

  • App Router first
  • OAuth support on preview deployments (Read More)
  • Simplified setup (shared config, inferred env variables)
  • New account() callback on providers (account() docs)
  • Edge-compatible

Universal auth()

  • A single method to authenticate anywhere
  • Use auth() instead of getServerSession, getSession, withAuth, getToken, and useSession (Read more)

Read the NextAuth.js v5 migration guide to learn more.

Configured Providers

  • Google
  • Email (Magic Link)
Auth Providers

Google Provider

Required environment variables:

  • AUTH_GOOGLE_ID
  • AUTH_GOOGLE_SECRET

Read the Google Provider docs to learn more.

Follow the steps below to configure the Google Provider:

  1. Go to the Google Cloud Console.
  2. Create an account if you don't already have one.
  3. Click on "APIs"
  4. Click on "OAuth consent screen" and configure your consent screen.
  5. Click on "Credentials", create a new OAuth credential.
  6. Add the Authorized Javascript origins
http://localhost:3000
  1. Add the Authorized redirect URIs
http://localhost:3000/api/auth/callback/google
  1. Update the AUTH_GOOGLE_ID and AUTH_GOOGLE_SECRET environment variables in the .env file with your new credentials.

Email Provider (Resend)

Required environment variables:

  • AUTH_EMAIL_FROM
  • RESEND_API_KEY

Read the docs on setting up Resend.

Read the Resend Provider docs to learn more.

Configured DB Adapter

  • drizzle

Read the Drizzle Adapter docs to learn more.

Customizing / Adding Providers

Next-Auth is very easy to extend with custom providers. Read the Auth.js docs to learn more. Be sure to add your provider to the providers array in /auth.ts. You will also need to add the option to the sign up/in page located at /app/(auth)/sign-in/_components/sign-in-form.tsx.

Checking for Authentication

You can enforce authentication on your routes by using the auth middleware. StartStack already has some middleware in place to ensure users are authenticated before accessing certain pages.

import { auth } from "@/auth"
export default auth(req => {
// Look for session required routes
if (
!req.auth &&
["/account", "/docs"].some(route => req.nextUrl.pathname.includes(route))
) {
const newUrl = new URL(
`/sign-in?redirectTo=${req.nextUrl.pathname}`,
req.nextUrl.origin
)
return Response.redirect(newUrl)
}
// Look for admin session required routes
if (
req.auth?.user.role !== "admin" &&
["/admin"].some(route => req.nextUrl.pathname.includes(route))
) {
const newUrl = new URL(
`/sign-in?redirectTo=${req.nextUrl.pathname}`,
req.nextUrl.origin
)
return Response.redirect(newUrl)
}
})
export const config = {
matcher: ["/admin/:path*", "/account/:path*", "/docs/:path*"],
}

Notice how we are redirecting the user to the sign in page if they are not authenticated for certain routes (/account, /docs, /admin). We are also passing along the current page they are on as a redirectTo query parameter so that they can be redirected back to that page after signing in.

You can also check for the session anywhere in your application using the auth() function.

const session = await auth()

In addition to this StartStack has a currentUser (which uses auth() under the hood) service that you can use to get the current user in your application.

const user = await currentUser()

Extending the User Object

You can extend the user and session object by adding additional properties to the User and Session interfaces in /types/next-auth.d.ts. For example, StartStack extends the user object to include a role property. Be sure to also add your new property to the User table in the database via a migration.

import NextAuth, { DefaultSession, DefaultUser } from "next-auth"
declare module "next-auth" {
interface User extends DefaultUser {
role?: string
}
interface Session {
user: {
role?: string
} & DefaultSession["user"]
}
}