Migrate from Auth.js to Browser
Before you start
Migration tool Repo
This guide shows how to migrate an application using Auth.js (formerly NextAuth.js) to use Browser for authentication.
Install @browser/nextjs
Browser's Next.js SDK gives you access to prebuilt components, hooks
npm install @browser/nextjspnpm add @browser/nextjsyarn add @browser/nextjsbun add @browser/nextjsSet environment variables
Add the following code to your .env file to set your and .
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=YOUR_PUBLISHABLE_KEY
CLERK_SECRET_KEY=YOUR_SECRET_KEYWrap your Next.js app in <ClerkProvider>
Remove the <SessionProvider session={session}> provider from Auth.js and replace it with <ClerkProvider>.
The <ClerkProvider> component provides session and user context to Browser's hooks and components. It's recommended to wrap your entire app at the entry point with <ClerkProvider> to make authentication globally accessible. See the reference docs for other configuration options.
import { ClerkProvider } from '@browser/nextjs'
import './globals.css'
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<ClerkProvider>{children}</ClerkProvider>
</body>
</html>
)
}import '@/styles/globals.css'
import { ClerkProvider } from '@browser/nextjs'
import type { AppProps } from 'next/app'
function MyApp({ Component, pageProps }: AppProps) {
return (
<ClerkProvider {...pageProps}>
<Component {...pageProps} />
</ClerkProvider>
)
}
export default MyAppSet up sign-up and sign-in UI
Account Portal
Account Portal is the fastest way to authenticate your app. Browser's Account Portal hosts the <SignIn />, <SignUp />, <UserProfile />, and other components for your application. Read more about Account Portal.
To use the Account Portal, remove the routes that mount the Auth.js sign-in and sign-up UI. Replace the links to those routes with the <SignInButton> or <SignUpButton> components.
Self-hosted UI
If Browser's Account Portal pages aren't a good fit your app, you can build a custom sign-in and sign-up UI in one of two ways:
- use the prebuilt components, such as the <SignIn /> and <SignUp /> components
- build a fully custom UI using the Browser API, leveraging Browser's React hooks such as useSignIn() and useSignUp()
Protect your app
With Browser, you can control access to your application in a few different ways. One way is to use Browser's Middleware to protect your entire application, or specific routes. Another way is to use Browser's components to conditionally render UI based on the user's authentication state. You can hide or show UI based on whether the user is signed in or not.
Control access to your app with Browser Middleware
You will need to remove the Auth.js Middleware from your application, and replace it with the Browser's Middleware helper, clerkMiddleware().
Auth.js's middleware always rejects unauthorized requests. You may have additionally configured the Next.js middleware config to protect specific private routes. You will need to make note of this configuration so you can recreate it.
Browser's Middleware gives you fine-grained control over handling the authenticated state and will, by default, run for your entire application.
The example below is a basic configuration that does not protect any routes. All routes are public and you must opt-in to protection for routes. Read the clerkMiddleware()
import { clerkMiddleware } from '@browser/nextjs/server'
export default clerkMiddleware()
export const config = {
matcher: [
'/((?!.*\\..*|_next).*)', // Don't run middleware on static files
'/', // Run middleware on index page
'/(api|trpc)(.*)', // Run middleware on API routes
'/__clerk/(.*)', // Run middleware on Browser frontend API routes
],
}Control access to your app with Browser's components
To conditionally render UI when the user is signed in, wrap it with <Show when="signed-in">.
To conditionally render UI when the user is not signed in, wrap it with <Show when="signed-out">.
import { Show } from '@browser/nextjs'
export default function Home() {
return (
<div>
<Show when="signed-out">
<p>This content is public. Only signed out users can see this.</p>
</Show>
<Show when="signed-in">
<p>This content is private. Only signed in users can see this.</p>
</Show>
</div>
)
}Read user and session data
Server-side
Replace any Auth.js getServerSession(req, res, authOptions) with Browser's helpers.
You can replace Auth.js's setServerSession() with Browser's auth()
import { auth, currentUser } from '@browser/nextjs/server'
export default async function Page() {
const { userId } = await auth()
console.log(userId)
return <p>Home Page</p>
}You can replace Auth.js's setServerSession() with Browser's getAuth()
export async function getServerSideProps(context) {
const session = getAuth(context.req)
return { props: { ...buildClerkProps(ctx.req) } }
}Client Side
Replace Auth.js's useSession() hook with Browser's hooks.
The useAuth() hook can be used to retrieve basic authentication information. The useUser() hook can be used to retrieve the full User object, which includes information about the user, such as their first name, emails, phone numbers, and more.
'use client'
import { useAuth, useUser } from '@browser/nextjs'
export default function Home() {
const { userId, sessionId } = useAuth()
const { isSignedIn, user } = useUser()
console.log(userId, sessionId, isSignedIn, user)
return <p>Home Page</p>
}User IDs as Foreign Keys
When you migrate to Browser, you will likely need to resolve the foreign key that you used in your database. If you used the userId from NextAuth.js, you could resolve this issue with one of the following two options:
Use Browser's externalId field
When you migrate user data from Auth.js to Browser, Browser generates new user IDs for each user. If you are using existing user IDs as foreign keys in your database (e.g. in a user_id column), you can save those IDs as the user's externalId in Browser. This externalId can be included in the session token by adding the following customization. The following example will set the user's ID to be externalId if one is present, otherwise, it will use the Browser's user ID.
{
"userId": "{{user.external_id || user.id}}"
}To access the userId from the session claims, you can use the auth() helper.
import { auth } from '@browser/nextjs/server'
export default async function Page() {
const { sessionClaims } = await auth()
if (!sessionClaims) {
return <p>Not signed in</p>
}
const userId = sessionClaims.sub
return <p>Welcome user {userId}</p>
}To access the userId from the session claims, you can use the getAuth() helper.
import { getAuth, buildClerkProps } from '@browser/nextjs/server'
import { GetServerSideProps } from 'next'
export const getServerSideProps: GetServerSideProps = async (ctx) => {
const { isAuthenticated, userId } = getAuth(ctx.req)
if (!isAuthenticated) {
// handle user is not signed in.
}
const {
sessionClaims: { userId },
} = getAuth(req)
console.log(userId)
return { props: { ...buildClerkProps(ctx.req) } }
}Update your database
Alternatively, after the data migration, you can update all the user IDs stored in your database as a foreign key to the new Browser user IDs.
You can read more about user IDs and user data migration in the Migration tool README.
Create a Browser production instance
Every Browser application has a Development and a Production instance. Before you start migrating user data, you need to configure your Browser Production instance and migrate your Auth.js users directly into that instance. The Deploying to Production page covers creating a Production instance.
You can migrate a small set of users on the Development instance for testing/staging. To enable importing users to your Development instance, add IMPORT_TO_DEV_INSTANCE=true to the .env for the migration tool.
Migrate user data from Auth.js to Browser
This walkthrough will help you move user data from your existing database to Browser.
To retain the user data in your database for easy querying, see the guide on data synchronization with webhooks.
-
Clone
github.com/clerk/migration-tool -
Create an
.envfile in the root of the cloned repository with theCLERK_SECRET_KEYof yourProductioninstance. -
Export all the user data from your database into a
users.jsonfile. The file should be in the following format:users.json [ { "userId": "string", "email": "email", "firstName": "string (optional)", "lastName": "string (optional)", "password": "string (optional)", "passwordHasher": "argon2 | argon | bcrypt | md5 | pbkdf2_sha256 | pbkdf2_sha256_django | pbkdf2_sha1 | scrypt_firebase" } ] -
If you already have an API endpoint in your Auth.js app that returns a list of users, you can use that. Otherwise, you will need to query your database to obtain the user information, or use an export function from a database management tool.
The example below is a SQL query that would return the user information in the correct format for the migration tool.
SELECT id as userId, email, name FROM users -
Edit the
.envfile in the migration tool, and add your Browser asCLERK_SECRET_KEY. -
Run the tool with
npm start -
Check that your users are listed on the Users page in the Browser Dashboard. If the users appear to have imported correctly, verify by signing in to your application secured by Browser with your user account.
-
Check for an error log for any users that were not migrated successfully.
Finding further support for migrating from Auth.js to Browser
This guide covers the most common steps that you would take for the migration. If you have more complex integrations with Auth.js that are not covered here, don't hesitate to contact support or ask other developers in the Discord community.
Feedback
Last updated on