adapters
Auth.js can be integrated with any data layer (database, ORM, or backend API, HTTP client) in order to automatically create users, handle account linking automatically, support passwordless login, and to store session information.
This module contains utility functions and types to create an Auth.js compatible adapter.
Auth.js supports 2 session strategies to persist the login state of a user.
The default is to use a cookie + JWT
based session store (strategy: "jwt"
),
but you can also use a database adapter to store the session in a database.
Before you continue, Auth.js has a list of official database adapters. If your database is listed there, you probably do not need to create your own. If you are using a data solution that cannot be integrated with an official adapter, this module will help you create a compatible adapter.
Although @auth/core
is framework/runtime agnostic, an adapter might rely on a client/ORM package,
that is not yet compatible with your framework/runtime (e.g. it might rely on Node.js APIs).
Related issues should be reported to the corresponding package maintainers.
Installationβ
- npm
- Yarn
- pnpm
npm install @auth/core
yarn add @auth/core
pnpm add @auth/core
Then, you can import this submodule from @auth/core/adapters
.
Usageβ
Each adapter method and its function signature is documented in the Adapter interface.
import { type Adapter } from "@auth/core/adapters"
// 1. Simplest form, a plain object.
export const MyAdapter: Adapter {
// implement the adapter methods here
}
// or
// 2. A function that returns an object. Official adapters use this pattern.
export function MyAdapter(config: any): Adapter {
// Instantiate a client/ORM here with the provided config, or pass it in as a parameter.
// Usually, you might already have a client instance elsewhere in your application,
// so you should only create a new instance if you need to or you don't have one.
return {
// implement the adapter methods
}
}
Then, you can pass your adapter to Auth.js as the adapter
option.
import { MyAdapter } from "./my-adapter"
const response = await Auth(..., {
adapter: MyAdapter, // 1.
// or
adapter: MyAdapter({ /* config */ }), // 2.
...
})
Note, you might be able to tweak an existing adapter to work with your data layer, instead of creating one from scratch.
import { type Adapter } from "@auth/core/adapters"
import { PrismaAdapter } from "@auth/prisma-adapter"
import { PrismaClient } from "@prisma/client"
const prisma = new PrismaClient()
const adapter: Adapter = {
...PrismaAdapter(prisma),
// Add your custom methods here
}
const request = new Request("https://example.com")
const response = await Auth(request, { adapter, ... })
Modelsβ
Auth.js can be used with any database. Models tell you what structures Auth.js expects from your database. Models will vary slightly depending on which adapter you use, but in general, will have a similar structure to the graph below. Each model can be extended with additional fields.
Auth.js / NextAuth.js uses camelCase
for its database rows while respecting the conventional snake_case
formatting for OAuth-related values. If the mixed casing is an issue for you, most adapters have a dedicated documentation section on how to force a casing convention.
Testingβ
There is a test suite available to ensure that your adapter is compatible with Auth.js.
Known issuesβ
The following are missing built-in features in Auth.js but can be solved in user land. If you would like to help implement these features, please reach out.
Token rotationβ
Auth.js currently does not support access_token
rotation out of the box.
The necessary information (refresh_token
, expiry, etc.) is being stored in the database, but the logic to rotate the token is not implemented
in the core library.
This guide should provide the necessary steps to do this in user land.
Federated logoutβ
Auth.js currently does not support federated logout out of the box. This means that even if an active session is deleted from the database, the user will still be signed in to the identity provider, they will only be signed out of the application. Eg. if you use Google as an identity provider, and you delete the session from the database, the user will still be signed in to Google, but they will be signed out of your application.
If your users might be using the application from a publicly shared computer (eg: library), you might want to implement federated logout. This guide should provide the necessary steps.
Adapterβ
An adapter is an object with function properties (methods) that read and write data from a data source. Think of these methods as a way to normalize the data layer to common interfaces that Auth.js can understand.
This is what makes Auth.js very flexible and allows it to be used with any data layer.
The adapter methods are used to perform the following operations:
- Create/update/delete a user
- Link/unlink an account to/from a user
- Handle active sessions
- Support passwordless authentication across multiple devices
If any of the methods are not implemented, but are called by Auth.js, an error will be shown to the user and the operation will fail.
Methodsβ
createSession()β
optional
createSession(session
):Awaitable
<AdapterSession
>
Creates a session for the user and returns it.
Parametersβ
βͺ session: object
βͺ session.expires: Date
βͺ session.sessionToken: string
βͺ session.userId: string
Returnsβ
Awaitable
<AdapterSession
>
deleteSession()β
optional
deleteSession(sessionToken
):Promise
<void
> |Awaitable
<undefined
|null
|AdapterSession
>
Deletes a session from the database. It is preferred that this method also returns the session that is being deleted for logging purposes.
Parametersβ
βͺ sessionToken: string
Returnsβ
Promise
<void
> | Awaitable
<undefined
| null
| AdapterSession
>
deleteUser()β
optional
deleteUser(userId
):Promise
<void
> |Awaitable
<undefined
|null
|AdapterUser
>
Parametersβ
βͺ userId: string
Returnsβ
Promise
<void
> | Awaitable
<undefined
| null
| AdapterUser
>
Todoβ
This method is currently not invoked yet.
getUserByAccount()β
optional
getUserByAccount(providerAccountId
):Awaitable
<null
|AdapterUser
>
Using the provider id and the id of the user for a specific account, get the user.
Parametersβ
βͺ providerAccountId: Pick
<AdapterAccount
, "provider"
| "providerAccountId"
>
Returnsβ
Awaitable
<null
| AdapterUser
>
linkAccount()β
optional
linkAccount(account
):Promise
<void
> |Awaitable
<undefined
|null
|AdapterAccount
>
This method is invoked internally (but optionally can be used for manual linking). It creates an Account in the database.
Parametersβ
βͺ account: AdapterAccount
Returnsβ
Promise
<void
> | Awaitable
<undefined
| null
| AdapterAccount
>
unlinkAccount()β
optional
unlinkAccount(providerAccountId
):Promise
<void
> |Awaitable
<undefined
|AdapterAccount
>
Parametersβ
βͺ providerAccountId: Pick
<AdapterAccount
, "provider"
| "providerAccountId"
>
Returnsβ
Promise
<void
> | Awaitable
<undefined
| AdapterAccount
>
Todoβ
This method is currently not invoked yet.
useVerificationToken()β
optional
useVerificationToken(params
):Awaitable
<null
|VerificationToken
>
Return verification token from the database and delete it so it cannot be used again.