Next.js
unstable_getServerSession
β
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 Auth.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). 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
.
unstable_getServerSession
requires passing the same object you would pass to NextAuth
when initializing Auth.js. To do so, you can export your Auth.js options in the following way:
In [...nextauth].ts
:
import { NextAuth } from "next-auth"
import type { NextAuthOptions } from "next-auth"
export const authOptions: NextAuthOptions = {
// your configs
}
export default NextAuth(authOptions)
In getServerSideProps
:β
import { authOptions } from "pages/api/auth/[...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:β
import { authOptions } from "pages/api/auth/[...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:
import { unstable_getServerSession } from "next-auth/next"
import { authOptions } from "pages/api/auth/[...nextauth]"
export default async function Page() {
const session = await unstable_getServerSession(authOptions)
return <pre>{JSON.stringify(session, null, 2)}</pre>
}
Currently, the underlying Next.js cookies()
method does only provides read access 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 Auth.js to protect your site.
Next.js 12 has introduced 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.
If the following options look familiar, this is because they are a subset of these 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).
You can get the withAuth
middleware function from next-auth/middleware
either as a default or a named import:
Prerequisitesβ
You must set the same secret in the middleware that you use in NextAuth. The easiest way is to set the NEXTAUTH_SECRET
environment variable. It will be picked up by both the Auth.js config, as well as the middleware config.
Alternatively, you can provide the secret using the secret
option in the middleware config.
We strongly recommend replacing the secret
value completely with this NEXTAUTH_SECRET
environment variable.
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:
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
:
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)β
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.
This should match the pages
configuration that's found in [...nextauth].ts
.
Example (default value)β
pages: {
signIn: '/api/auth/signin',
error: '/api/auth/error',
}
See the documentation for the pages
option for more information.
secret
β
- Required: No
Descriptionβ
The same secret
used in the Auth.js config.
Example (default value)β
secret: process.env.NEXTAUTH_SECRET
Advanced usageβ
Auth.js Middleware is very flexible, there are multiple ways to use it.
If you do not define the options, Auth.js will use the default values for the omitted options.
wrap middlewareβ
import { withAuth } from "next-auth/middleware"
export default withAuth(
// `withAuth` augments your `Request` with the user's token.
function middleware(req) {
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.
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:
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 Auth.js can fully run at the Edge
- Only supports the
"jwt"
session strategy. 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)