AUTH_* environment variables, NextAuth() returning { handlers, auth, signIn, signOut }). The v4 getServerSession API maps the same way, only the names on the left differ.
Concepts map
Server setup
AUTH_* variables on its own, you pass them in. And the oauth() plugin refuses to start without auth.session, because it needs somewhere to put the session it issues after the callback.
Route handler
OAuth callback URL
Auth.js callback URLs look like/api/auth/callback/google. theAuth’s look like {baseUrl}/auth/oauth/callback/google, so with the setup above it is:
Reading the session
validate returns a Session or null and does not throw. The session carries a userId, not an email, so look the user up if you need more.
Middleware
Auth.js lets you exportauth as middleware and it validates the JWT on the edge. theAuth sessions are database rows, and the edge runtime usually cannot open your database connection. Keep middleware to a cheap cookie check and do the real validation in requireUser() above.
requireUser(). If you want stateless verification on the edge, use JWT sessions instead of the cookie session manager.
Client side
useSession() returns { session, isLoading, refresh }, not { data, status }. See React hooks for the provider modes.
Database
If you used an Auth.js database adapter, you haveUser, Account, Session and VerificationToken tables (names depend on the adapter). Copy users and OAuth links, and leave sessions and verification tokens behind. Run createTheAuth once first so the theauth_* tables exist.
SELECT column_name FROM information_schema.columns WHERE table_name = 'User' before running anything, and run the whole thing against a copy first. Check the column type of theauth_oauth_accounts.expires_at too: Auth.js stores seconds since the epoch, hence to_timestamp.
What does not move:
- Sessions. With the database strategy the session token is a random string, with the JWT strategy it is an encrypted token. Neither is a theAuth token. Users sign in again, which for OAuth users is one click.
- Passwords. Auth.js has no built-in password storage. If you wrote a Credentials provider, you own the hash format. theAuth’s
usernamemodule only verifiespbkdf2:<iterations>:<saltHex>:<hashHex>, so bcrypt or argon2 hashes need a forced reset or a lazy rehash. The approach is spelled out under Migrate from Auth0 and applies unchanged. - Email sign-in tokens. Verification tokens are short lived, let them expire.
Run both during the cutover
authJsAdapter lets theAuth treat an existing Auth.js session as the signed-in user, so agent routes and plugin endpoints keep working while pages still use auth().
getSession must return { user: { id, email?, name?, image? } } or null. The adapter only resolves identity, it does not create theAuth sessions. Use it to move the agent and MCP side first, then switch the human sign-in over when you are ready. Mixing it with auth.session for the same routes is possible but auth.adapter takes one adapter, so the overlap period needs a small customAuth wrapper, as described in Migrate from better-auth.
Things that behave differently
- Cookie names. Auth.js uses
authjs.session-token(and the__Secure-prefixed variant on HTTPS). theAuth usestheauth_session. Both can coexist on one domain. - Session lifetime. Auth.js JWT sessions last 30 days by default. The theAuth cookie session manager defaults to 7 days with a sliding window, see Cookie options.
- Where the secret lives. Rotating
AUTH_SECRETlogs everyone out in Auth.js. Changingauth.session.secretdoes the same here, and theAuth does not take a list of secrets. - After the OAuth callback the user lands on
{baseUrl}/with anauth_userquery parameter, not on acallbackUrlyou pass at sign-in. Keep that in mind if you rely on deep links, and see Redirect chains.
Related
Add to an existing app
Keep your current auth and add agents on top.
Next.js adapter
Route handler options and authenticating the management routes.
Troubleshooting
Cookie, redirect and proxy problems after a cutover.
Production checklist
What to verify before you point real traffic at theAuth.