适配器
Auth.js 可以与任何数据层(数据库、ORM 或后端 API、HTTP 客户端)集成,以自动创建用户、自动处理帐户关联、支持无密码登录以及存储会话信息。
此模块包含用于创建 Auth.js 兼容适配器的实用程序函数和类型。
Auth.js 支持 2 种会话策略来持久保存用户的登录状态。默认情况下,它使用 cookie + JWT 基于会话存储 (strategy: "jwt"
),但你也可以使用数据库适配器将会话存储在数据库中。
在你继续之前,Auth.js 有一个 官方数据库适配器 列表。如果你的数据库在那里列出,你可能不需要创建自己的适配器。如果你正在使用无法与官方适配器集成的数据库解决方案,此模块将帮助你创建一个兼容的适配器。
注意 虽然 @auth/core
是框架/运行时无关的,但适配器可能依赖于客户端/ORM 包,而该包尚未与你的框架/运行时兼容(例如,它可能依赖于 Node.js API)。相关问题应报告给相应的包维护者。
安装
npm install @auth/core
然后,你可以从 @auth/core/adapters
导入此子模块。
用法
每个适配器方法及其函数签名都在 适配器 接口中记录。
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
}
}
然后,你可以将你的适配器作为 adapter
选项传递给 Auth.js。
import { MyAdapter } from "./my-adapter"
const response = await Auth(..., {
adapter: MyAdapter, // 1.
// or
adapter: MyAdapter({ /* config */ }), // 2.
...
})
请注意,你可能能够调整现有适配器以使其与你的数据层一起使用,而不是从头开始创建适配器。
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, ... })
模型
Auth.js 可以与任何数据库一起使用。模型会告诉你 Auth.js 从你的数据库中期望哪些结构。模型会因你使用的适配器而略有不同,但总的来说,它们的结构类似于下面的图表。每个模型都可以通过额外的字段进行扩展。
Auth.js / NextAuth.js 在其数据库行中使用 camelCase
,同时尊重 OAuth 相关值的传统 snake_case
格式。如果混合大小写对你来说是一个问题,大多数适配器都有一个专门的文档部分说明如何强制使用大小写约定。
测试
有一个测试套件 可用 来确保你的适配器与 Auth.js 兼容。
已知问题
以下是在 Auth.js 中缺少的内置功能,但可以在用户空间解决。如果你想帮助实现这些功能,请联系我们。
令牌轮换
Auth.js目前不支持access_token
轮换。必要的信息 (refresh_token
、过期时间等) 正在存储在数据库中,但核心库中没有实现轮换令牌的逻辑。 本指南 应提供在用户空间执行此操作的必要步骤。
联合注销
Auth.js目前不支持联合注销。这意味着即使从数据库中删除了活动会话,用户仍将登录身份提供者,他们只会从应用程序中注销。例如,如果你使用 Google 作为身份提供者,并且你从数据库中删除了会话,用户仍将登录 Google,但他们将从你的应用程序中注销。
如果你的用户可能从公共共享计算机(例如:图书馆)使用应用程序,你可能希望实现联合注销。
适配器
适配器是一个带有函数属性(方法)的对象,这些方法用于从数据源读取和写入数据。可以将这些方法视为将数据层标准化为 Auth.js 可以理解的通用接口的一种方式。
这就是 Auth.js 非常灵活的原因,它允许与任何数据层一起使用。
适配器方法用于执行以下操作
- 创建/更新/删除用户
- 将帐户链接/解除链接到/从用户
- 处理活动会话
- 支持跨多个设备的无密码身份验证
如果任何方法未实现,但被 Auth.js 调用,则会向用户显示错误,并且操作将失败。
方法
createAuthenticator()?
optional createAuthenticator(authenticator): Awaitable<AdapterAuthenticator>
创建一个新的身份验证器。
如果创建失败,适配器必须抛出错误。
参数
参数 | 类型 |
---|---|
身份验证器 | AdapterAuthenticator |
返回
Awaitable
<AdapterAuthenticator
>
createSession()?
optional createSession(session): Awaitable<AdapterSession>
为用户创建会话并返回它。
另请参阅 数据库会话管理
参数
参数 | 类型 |
---|---|
会话 | 对象 |
session.expires | 日期 |
session.sessionToken | 字符串 |
session.userId | 字符串 |
返回
createUser()?
optional createUser(user): Awaitable<AdapterUser>
在数据库中创建一个用户并返回它。
另请参阅 用户管理
参数
参数 | 类型 |
---|---|
用户 | AdapterUser |
返回
createVerificationToken()?
optional createVerificationToken(verificationToken): Awaitable<undefined | null | VerificationToken>
创建一个验证令牌并返回它。
另请参阅 验证令牌
参数
参数 | 类型 |
---|---|
verificationToken | VerificationToken |
返回
Awaitable
<undefined
| null
| VerificationToken
>
deleteSession()?
optional deleteSession(sessionToken): Promise<void> | Awaitable<undefined | null | AdapterSession>
从数据库中删除一个会话。建议此方法也返回要删除的会话,以用于记录目的。
另请参阅 数据库会话管理
参数
参数 | 类型 |
---|---|
sessionToken | 字符串 |
返回
Promise
<void
> | Awaitable
<undefined
| null
| AdapterSession
>
deleteUser()?
optional deleteUser(userId): Promise<void> | Awaitable<undefined | null | AdapterUser>
参数
参数 | 类型 |
---|---|
userId | 字符串 |
返回
Promise
<void
> | Awaitable
<undefined
| null
| AdapterUser
>
待办事项
此方法当前尚未调用。
另请参阅 用户管理
getAccount()?
optional getAccount(providerAccountId, provider): Awaitable<null | AdapterAccount>
通过提供者帐户 ID 和提供者获取帐户。
如果未找到帐户,适配器必须返回 null
。
参数
参数 | 类型 |
---|---|
providerAccountId | 字符串 |
提供者 | 字符串 |
返回
Awaitable
<null
| AdapterAccount
>
getAuthenticator()?
optional getAuthenticator(credentialID): Awaitable<null | AdapterAuthenticator>
从其凭据 ID 返回身份验证器。
如果未找到身份验证器,适配器必须返回 null
。
参数
参数 | 类型 |
---|---|
credentialID | 字符串 |
返回
Awaitable
<null
| AdapterAuthenticator
>
getSessionAndUser()?
optional getSessionAndUser(sessionToken): Awaitable<null | {
session: AdapterSession;
user: AdapterUser;
}>
一次从数据库中返回会话和用户。
如果数据库支持联接,建议减少数据库查询次数。
另请参阅 数据库会话管理
参数
参数 | 类型 |
---|---|
sessionToken | 字符串 |
返回
Awaitable
<null
| { session
: AdapterSession
; user
: AdapterUser
; }>
getUser()?
optional getUser(id): Awaitable<null | AdapterUser>
通过用户 ID 从数据库中返回用户。
另请参阅 用户管理
参数
参数 | 类型 |
---|---|
id | 字符串 |
返回
Awaitable
<null
| AdapterUser
>
getUserByAccount()?
optional getUserByAccount(providerAccountId): Awaitable<null | AdapterUser>
使用提供者 ID 和特定帐户用户的 ID 获取用户。
另请参阅 用户管理
参数
参数 | 类型 |
---|---|
providerAccountId | Pick <AdapterAccount , "provider" | "providerAccountId" > |
返回
Awaitable
<null
| AdapterUser
>
getUserByEmail()?
optional getUserByEmail(email): Awaitable<null | AdapterUser>
通过用户的电子邮件地址从数据库中返回用户。
另请参阅 验证令牌
参数
参数 | 类型 |
---|---|
邮件 | 字符串 |
返回
Awaitable
<null
| AdapterUser
>
linkAccount()?
optional linkAccount(account): Promise<void> | Awaitable<undefined | null | AdapterAccount>
此方法在内部调用(但可以选择用于手动链接)。它在数据库中创建了一个 帐户。
另请参阅 用户管理
参数
参数 | 类型 |
---|---|
帐户 | AdapterAccount |
返回
Promise
<void
> | Awaitable
<undefined
| null
| AdapterAccount
>
listAuthenticatorsByUserId()?
optional listAuthenticatorsByUserId(userId): Awaitable<AdapterAuthenticator[]>
返回用户的所有身份验证器。
如果未找到用户,适配器仍然应该返回一个空数组。如果检索因其他原因而失败,适配器必须抛出错误。
参数
参数 | 类型 |
---|---|
userId | 字符串 |
返回
Awaitable
<AdapterAuthenticator
[]>
unlinkAccount()?
optional unlinkAccount(providerAccountId): Promise<void> | Awaitable<undefined | AdapterAccount>
参数
参数 | 类型 |
---|---|
providerAccountId | Pick <AdapterAccount , "provider" | "providerAccountId" > |
返回
Promise
<void
> | Awaitable
<undefined
| AdapterAccount
>
待办事项
此方法当前尚未调用。
updateAuthenticatorCounter()?
optional updateAuthenticatorCounter(credentialID, newCounter): Awaitable<AdapterAuthenticator>
更新身份验证器的计数器。
如果更新失败,适配器必须抛出错误。
参数
参数 | 类型 |
---|---|
credentialID | 字符串 |
newCounter | 数字 |
返回
Awaitable
<AdapterAuthenticator
>
updateSession()?
optional updateSession(session): Awaitable<undefined | null | AdapterSession>
更新数据库中的会话并返回它。
另请参阅 数据库会话管理
参数
参数 | 类型 |
---|---|
会话 | Partial <AdapterSession > & Pick <AdapterSession , "sessionToken" > |
返回
Awaitable
<undefined
| null
| AdapterSession
>
updateUser()?
optional updateUser(user): Awaitable<AdapterUser>
更新数据库中的用户并返回它。
另请参阅 用户管理
参数
参数 | 类型 |
---|---|
用户 | Partial <AdapterUser > & Pick <AdapterUser , "id" > |
返回
useVerificationToken()?
optional useVerificationToken(params): Awaitable<null | VerificationToken>
从数据库返回验证令牌并将其删除,以便它只能使用一次。
另请参阅 验证令牌
参数
参数 | 类型 |
---|---|
params | 对象 |
params.identifier | 字符串 |
params.token | 字符串 |
返回
Awaitable
<null
| VerificationToken
>
AdapterAccount
帐户是用户和提供商之间的连接。
有两种类型的帐户
- OAuth/OIDC 帐户,在用户使用 OAuth 提供商登录时创建。
- 电子邮件帐户,在用户使用 电子邮件提供商 登录时创建。
一个用户可以拥有多个帐户。
扩展
属性
access_token?
optional readonly access_token: string;
继承自
authorization_details?
optional readonly authorization_details: AuthorizationDetails[];
继承自
expires_at?
optional expires_at: number;
基于 TokenEndpointResponse.expires_in 计算的值。
它是 TokenEndpointResponse.access_token 过期的绝对时间戳(以秒为单位)。
此值可用于与 TokenEndpointResponse.refresh_token 一起实现令牌轮换。
参见
- https://authjs.oauth.ac.cn/guides/refresh-token-rotation#database-strategy
- https://www.rfc-editor.org/rfc/rfc6749#section-5.1
继承自
expires_in?
optional readonly expires_in: number;
继承自
id_token?
optional readonly id_token: string;
继承自
provider
provider: string;
此帐户的提供商 ID。例如,“google”。查看完整列表 https://authjs.oauth.ac.cn/reference/core/providers
继承自
providerAccountId
providerAccountId: string;
此值取决于用于创建帐户的提供商类型。
- oauth/oidc: OAuth 帐户的 ID,从
profile()
回调返回。 - email: 用户的电子邮件地址。
- credentials:
id
从authorize()
回调返回
继承自
refresh_token?
optional readonly refresh_token: string;
继承自
scope?
optional readonly scope: string;
继承自
token_type?
optional readonly token_type: Lowercase<string>;
注意:因为值不区分大小写,所以它始终以小写形式返回
继承自
type
type: AdapterAccountType;
此帐户的提供商类型
覆盖
userId
userId: string;
此帐户所属用户的 ID
参见
https://authjs.oauth.ac.cn/reference/core/adapters#adapteruser
覆盖
AdapterAuthenticator
身份验证器表示分配给用户的凭据身份验证器。
扩展
属性
counter
counter: number;
身份验证器已使用次数。
继承自
credentialBackedUp
credentialBackedUp: boolean;
客户端身份验证器是否备份了凭据。
继承自
Authenticator
.credentialBackedUp
credentialDeviceType
credentialDeviceType: string;
身份验证器的设备类型。
继承自
Authenticator
.credentialDeviceType
credentialID
credentialID: string;
Base64 编码的凭据 ID。
继承自
credentialPublicKey
credentialPublicKey: string;
Base64 编码的凭据公钥。
继承自
Authenticator
.credentialPublicKey
providerAccountId
providerAccountId: string;
与身份验证器连接的提供商帐户 ID。
继承自
Authenticator
.providerAccountId
transports?
optional transports: null | string;
连接的传输标志。
继承自
userId
userId: string;
身份验证器的用户 ID。
覆盖
AdapterSession
会话保存有关用户当前登录状态的信息。
属性
expires
expires: Date;
会话到期的绝对日期。
如果在会话到期日期之前访问会话,它将根据 maxAge
选项进行扩展,该选项由 SessionOptions.maxAge
定义。它在一个由 SessionOptions.updateAge
定义的时间段内最多扩展一次。
如果在会话到期日期之后访问会话,它将从数据库中删除,以清除非活动会话。
sessionToken
sessionToken: string;
一个随机生成的值,用于在使用 "database"
AuthConfig.strategy
选项时在数据库中查找会话。该值保存在客户端的安全、HTTP-Only cookie 中。
userId
userId: string;
将活动会话连接到数据库中的用户。
AdapterUser
用户代表可以登录应用程序的人。如果用户尚不存在,则在他们首次登录时,使用身份提供者返回的信息(个人资料数据)创建用户。还会创建一个相应的帐户并链接到该用户。
扩展
属性
email: string;
用户的电子邮件地址。
覆盖
emailVerified
emailVerified: null | Date;
用户是否已通过 电子邮件提供商 验证了他们的电子邮件地址。如果用户尚未使用电子邮件提供商登录,则为 null
,或者为首次成功登录的日期。
id
id: string;
用户的唯一标识符。
覆盖
image?
optional image: null | string;
继承自
name?
optional name: null | string;
继承自
VerificationToken
验证令牌是一个临时令牌,用于通过用户的电子邮件地址登录用户。当用户使用 电子邮件提供商 登录时,会创建它。当用户单击电子邮件中的链接时,令牌和电子邮件将被发送回服务器,在那里它被哈希并与数据库中的值进行比较。如果令牌和电子邮件匹配,并且令牌尚未过期,则用户将登录。然后,令牌将从数据库中删除。
属性
expires
expires: Date;
令牌到期的绝对日期。
identifier
identifier: string;
用户的电子邮件地址。
token
token: string;
一个使用 AuthConfig.secret
值进行 哈希 的令牌。
AdapterAccountType
type AdapterAccountType: Extract<ProviderType, "oauth" | "oidc" | "email" | "webauthn">;
帐户类型。
isDate()
isDate(value): value is string
确定给定值是否可以解析为 Date
参数
参数 | 类型 |
---|---|
value | unknown |
返回
value 是字符串