Skip to main content
This guide will help you migrate from 1.x to 2.x of the Auth0 Next.js SDK.

Node 10 No Longer Supported

Node 12 LTS and newer LTS releases are supported. Node 10 is no longer supported.

getSession Now Returns a Promise

getSession is now asynchronous and returns a Promise.
// /pages/api/my-api
import { getSession } from "@auth0/nextjs-auth0"

function myApiRoute(req, res) {
  const session = getSession(req, res)
  // ...
}

Client Methods and Components Now Exported Under /client

All methods and components for the browser should now be accessed under /client.
// pages/_app.js
import React from "react"
import { UserProvider } from "@auth0/nextjs-auth0"

export default function App({ Component, pageProps }) {
  return (
    <UserProvider>
      <Component {...pageProps} />
    </UserProvider>
  )
}
// pages/index.js
import { useUser } from "@auth0/nextjs-auth0"

export default function Index() {
  const { user, error, isLoading } = useUser()

  if (isLoading) return <div>Loading...</div>
  if (error) return <div>{error.message}</div>

  if (user) {
    return (
      <div>
        Welcome {user.name}! <a href="/api/auth/logout">Logout</a>
      </div>
    )
  }

  return <a href="/api/auth/login">Login</a>
}

updateSession Has Been Added

Session modifications are no longer saved implicitly. You must explicitly call updateSession to persist changes.
Previously your application could make modifications to the session during the lifecycle of the request and those updates would be saved implicitly when the response’s headers were written:
// /pages/api/update-user
import { getSession } from "@auth0/nextjs-auth0"

function myApiRoute(req, res) {
  const session = getSession(req, res)
  session.foo = "bar"
  res.json({ success: true })
}
// The updated session is serialized and the cookie is updated
// when the cookie headers are written to the response.

getServerSidePropsWrapper Has Been Removed

getServerSidePropsWrapper is no longer needed and has been removed.
Because the process of modifying the session is now explicit, you no longer have to wrap getServerSideProps in getServerSidePropsWrapper.
export const getServerSideProps = getServerSidePropsWrapper((ctx) => {
  const session = getSession(ctx.req, ctx.res)
  if (session) {
    // User is authenticated
  } else {
    // User is not authenticated
  }
})

Profile API Route No Longer Returns a 401

The profile API route now returns a 204 status code when the user is not authenticated instead of 401.
Previously the profile API route, by default at /api/auth/me, would return a 401 error when the user was not authenticated. While it was technically the right status code for the situation, it showed up in the browser console as an error. This API route will now return a 204 instead. Since 204 is a successful status code, it will not produce a console error.

Override Default Error Handler

You can now set the default error handler for the auth routes in a single place.
export default handleAuth({
  async login(req, res) {
    try {
      await handleLogin(req, res)
    } catch (error) {
      errorLogger(error)
      res.status(error.status || 500).end()
    }
  },
  async callback(req, res) {
    try {
      await handleLogin(req, res)
    } catch (error) {
      errorLogger(error)
      res.status(error.status || 500).end()
    }
  },
  // ...
})

afterCallback Can Write to the Response

You can now write your own redirect header or terminate the request in afterCallback.
const afterCallback = (req, res, session, state) => {
  if (session.user.isAdmin) {
    return session;
  } else {
    res.status(401).end('User is not admin');
  }
}; // 💥 Fails with ERR_HTTP_HEADERS_SENT

const afterCallback = (req, res, session, state) => {
  if (!session.user.isAdmin) {
    res.setHeader('Location', '/admin');
  }
  return session;
}; // 💥 Fails with ERR_HTTP_HEADERS_SENT

Configure Default Handlers

Previously it was not possible to configure the default handlers. For example, to pass a connection parameter to the login handler, you had to override it.
export default handleAuth({
  login: async (req, res) => {
    try {
      await handleLogin(req, res, {
        authorizationParams: { connection: "github" },
      })
    } catch (error) {
      // ...
    }
  },
})
It is still possible to override the default handlers if needed.

Build docs developers (and LLMs) love