# Next.js ## `unstable_getServerSession` :::warning This feature is experimental and may be removed or changed in the future. ::: When calling from server-side i.e. in API routes or in `getServerSideProps`, we recommend using this function instead of `getSession` to retrieve the `session` object. This method is especially useful when you are using NextAuth.js with a database. This method can _drastically_ reduce response time when used over `getSession` server-side, due to avoiding an extra `fetch` to an API Route (this is generally [not recommended in Next.js](https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props#getserversideprops-or-api-routes)). In addition, `unstable_getServerSession` will correctly update the cookie expiry time and update the session content if `callbacks.jwt` or `callbacks.session` changed something. Otherwise, if you only want to get the session token, see [`getToken`](tutorials/securing-pages-and-api-routes#using-gettoken). `unstable_getServerSession` requires passing the same object you would pass to `NextAuth` when initializing NextAuth.js. To do so, you can export your NextAuth.js options in the following way: In `[...nextauth.js]`: ```ts import { NextAuth } from 'next-auth' import type { NextAuthOptions } from 'next-auth' export const authOptions: NextAuthOptions = { // your configs } export default NextAuth(authOptions); ``` ### In `getServerSideProps`: ```js import { authOptions } from 'pages/api/[...nextauth]' import { unstable_getServerSession } from "next-auth/next" export async function getServerSideProps(context) { const session = await unstable_getServerSession(context.req, context.res, authOptions) if (!session) { return { redirect: { destination: '/', permanent: false, }, } } return { props: { session, }, } } ``` ### In API routes: ```js import { authOptions } from 'pages/api/[...nextauth]' import { unstable_getServerSession } from "next-auth/next" export async function handler(req, res) { const session = await unstable_getServerSession(req, res, authOptions) if (!session) { res.status(401).json({ message: "You must be logged in." }); return; } return res.json({ message: 'Success', }) } ``` ### In `app/` directory: You can also use `unstable_getServerSession` in Next.js' server components: ```tsx import { unstable_getServerSession } from "next-auth/next" export default async function Page() { const session = await unstable_getServerSession() return
{JSON.stringify(session, null, 2)}
} ``` :::warning Currently, the underlying Next.js `cookies()` method does [only provides read access](https://beta.nextjs.org/docs/api-reference/cookies) to the request cookies. This means that the `expires` value is stripped away from `session` in Server Components. Furthermore, there is a hard expiry on sessions, after which the user will be required to sign in again. (The default expiry is 30 days). ::: ## Middleware You can use a Next.js Middleware with NextAuth.js to protect your site. Next.js 12 has introduced [Middleware](https://nextjs.org/docs/middleware). It is a way to run logic before accessing any page, even when they are static. On platforms like Vercel, Middleware is run at the [Edge](https://nextjs.org/docs/api-reference/edge-runtime). If the following options look familiar, this is because they are a subset of [these options](/configuration/options#options). You can extract these to a common configuration object to reuse them. In the future, we would like to be able to run everything in Middleware. (See [Caveats](#caveats)). You can get the `withAuth` middleware function from `next-auth/middleware` either as a default or a named import: ### Prerequisites You must set the [`NEXTAUTH_SECRET`](/configuration/options#nextauth_secret) environment variable when using this middleware. If you are using the [`secret` option](/configuration/options#secret) this value must match. **We strongly recommend** replacing the `secret` value completely with this `NEXTAUTH_SECRET` environment variable. This environment variable will be picked up by both the [NextAuth config](/configuration/options#options), as well as the middleware config. ### Basic usage The most simple usage is when you want to require authentication for your entire site. You can add a `middleware.js` file with the following: ```js export { default } from "next-auth/middleware" ``` That's it! Your application is now secured. 🎉 If you only want to secure certain pages, export a `config` object with a `matcher`: ```js export { default } from "next-auth/middleware" export const config = { matcher: ["/dashboard"] } ``` Now you will still be able to visit every page, but only `/dashboard` will require authentication. If a user is not logged in, the default behavior is to redirect them to the sign-in page. --- ### `callbacks` - **Required:** No #### Description Callbacks are asynchronous functions you can use to control what happens when an action is performed. #### Example (default value) ```js callbacks: { authorized({ req , token }) { if(token) return true // If there is a token, the user is authenticated } } ``` --- ### `pages` - **Required**: _No_ #### Description Specify URLs to be used if you want to create custom sign in, and error pages. Pages specified will override the corresponding built-in page. #### Example (default value) ```js pages: { signIn: '/auth/signin', error: '/auth/error', } ``` See the documentation for the [pages option](/configuration/pages) for more information. --- ### Advanced usage NextAuth.js Middleware is very flexible, there are multiple ways to use it. :::note If you do not define the options, NextAuth.js will use the default values for the omitted options. ::: #### wrap middleware ```ts title="middleware.ts" import type { NextRequest } from "next/server" import type { JWT } from "next-auth/jwt" import { withAuth } from "next-auth/middleware" export default withAuth( // `withAuth` can augment your Request with the user's token. function middleware(req: NextRequest & { nextauth: { token: JWT | null } }) { console.log(req.nextauth.token) }, { callbacks: { authorized: ({ token }) => token?.role === "admin", }, } ) export const config = { matcher: ["/admin"] } ``` The `middleware` function will only be invoked if the `authorized` callback returns `true`. --- #### Custom JWT decode method If you have a custom jwt decode method set in `[...nextauth].ts`, you must also pass the same `decode` method to `withAuth` in order to read the custom-signed JWT correctly. You may want to extract the encode/decode logic to a separate function for consistency. `` ```ts title="/api/auth/[...nextauth].ts" import type { NextAuthOptions } from "next-auth" import NextAuth from "next-auth" import jwt from "jsonwebtoken" export const authOptions: NextAuthOptions = { providers: [...], jwt: { async encode({ secret, token }) { return jwt.sign(token, secret) }, async decode({ secret, token }) { return jwt.verify(token, secret) }, }, } export default NextAuth(authOptions) ``` And: ```ts title="middleware.ts" import withAuth from "next-auth/middleware" import { authOptions } from "pages/api/auth/[...nextauth]"; export default withAuth({ jwt: { decode: authOptions.jwt }, callbacks: { authorized: ({ token }) => !!token, }, }) ``` ### Caveats - Currently only supports session verification, as parts of the sign-in code need to run in a Node.js environment. In the future, we would like to make sure that NextAuth.js can fully run at the [Edge](https://nextjs.org/docs/api-reference/edge-runtime) - Only supports the `"jwt"` [session strategy](/configuration/options#session). We need to wait until databases at the Edge become mature enough to ensure a fast experience. (If you know of an Edge-compatible database, we would like if you proposed a new [Adapter](/tutorials/creating-a-database-adapter))