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
- Email (Magic Link)
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:
- Go to the Google Cloud Console.
- Create an account if you don't already have one.
- Click on "APIs"
- Click on "OAuth consent screen" and configure your consent screen.
- Click on "Credentials", create a new OAuth credential.
- Add the Authorized Javascript origins
http://localhost:3000
- Add the Authorized redirect URIs
http://localhost:3000/api/auth/callback/google
- Update the
AUTH_GOOGLE_ID
andAUTH_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 routesif (!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 routesif (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"]}}