参考
API 密钥插件选项、权限及模式参考。
API 密钥插件选项
configId string
该配置的唯一标识符。在使用多个配置时必填。默认值为 "default"。
references "user" | "organization"
API 密钥所关联的主体。此设置决定了 API 密钥的拥有权。默认值为 "user"。
"user":API 密钥归用户所有(创建时需提供userId)"organization":API 密钥归组织所有(创建时需提供organizationId)
apiKeyHeaders string | string[];
用于检测 API 密钥的请求头名称。默认值为 x-api-key。
customAPIKeyGetter (ctx: GenericEndpointContext) => string | null
自定义函数,从上下文中获取 API 密钥。
customAPIKeyValidator (options: { ctx: GenericEndpointContext; key: string; }) => boolean | Promise<boolean>
自定义函数,用于验证 API 密钥。
customKeyGenerator (options: { length: number; prefix: string | undefined; }) => string | Promise<string>
自定义函数,用于生成 API 密钥。
startingCharactersConfig { shouldStore?: boolean; charactersLength?: number; }
自定义起始字符配置。
defaultKeyLength number
API 密钥的长度,越长越好。默认值为 64。(不包括前缀长度)
defaultPrefix string
API 密钥的前缀。
注意:建议给前缀添加下划线以便更好识别,如 hello_。
maximumPrefixLength number
前缀的最大长度。
minimumPrefixLength number
前缀的最小长度。
requireName boolean
是否要求必须填写 API 密钥名称。默认值为 false。
maximumNameLength number
名称的最大长度。
minimumNameLength number
名称的最小长度。
enableMetadata boolean
是否启用 API 密钥的元数据。
keyExpiration { defaultExpiresIn?: number | null; disableCustomExpiresTime?: boolean; minExpiresIn?: number; maxExpiresIn?: number; }
自定义密钥过期时间。
rateLimit { enabled?: boolean; timeWindow?: number; maxRequests?: number; }
自定义速率限制。
schema InferOptionSchema<ReturnType<typeof apiKeySchema>>
API 密钥插件的自定义模式。
enableSessionForAPIKeys boolean
API 密钥可以代表一个有效会话,因此如果在请求头中找到有效的 API 密钥,可以模拟用户会话。默认值为 false。
storage "database" | "secondary-storage"
API 密钥的存储后端。默认值为 "database"。
"database":存储于数据库适配器(默认)"secondary-storage":存储于配置的二级存储(例如 Redis)
fallbackToDatabase boolean
当 storage 设为 "secondary-storage" 时,若未在二级存储中找到密钥,是否回退至数据库查找。
默认值为 false。
当 storage 设置为 "secondary-storage" 时,必须在 Better Auth 配置中指定 secondaryStorage。API 密钥将使用如下键值模式存储:
api-key:${hashedKey}- 通过哈希密钥的主查找键api-key:by-id:${id}- 通过 ID 查找api-key:by-ref:${referenceId}- 关联的 API 密钥列表(用户或组织)
若 API 密钥设置了过期时间(expiresAt),二级存储会自动设置 TTL 以实现自动清理。
import { betterAuth } from "better-auth";
import { apiKey } from "better-auth/plugins"
export const auth = betterAuth({
secondaryStorage: {
get: async (key) => {
return await redis.get(key);
},
set: async (key, value, ttl) => {
if (ttl) await redis.set(key, value, { EX: ttl });
else await redis.set(key, value);
},
delete: async (key) => {
await redis.del(key);
},
},
plugins: [
apiKey({
storage: "secondary-storage",
}),
],
});customStorage { get: (key: string) => Promise<unknown> | unknown; set: (key: string, value: string, ttl?: number) => Promise<void | null | unknown> | void; delete: (key: string) => Promise<void | null | string> | void; }
API 密钥的自定义存储方法。如果提供,该方法会优先于 ctx.context.secondaryStorage 使用。
适用于想为 API 密钥使用不同于全局二级存储的存储后端,或者需要自定义存储逻辑的场景。
import { betterAuth } from "better-auth";
import { apiKey } from "better-auth/plugins"
export const auth = betterAuth({
plugins: [
apiKey({
storage: "secondary-storage",
customStorage: {
get: async (key) => await customStorage.get(key),
set: async (key, value, ttl) => await customStorage.set(key, value, ttl),
delete: async (key) => await customStorage.delete(key),
},
}),
],
});deferUpdates boolean
将非关键的更新(如速率限制计数器、时间戳、剩余请求数)推迟到响应发送后,通过全局的 backgroundTasks 处理器异步执行。此设置在无服务器架构中显著提升响应速度。默认值为 false。
需要在主认证配置中设置 backgroundTasks.handler。
启用该选项会引入最终一致性,即响应先返回乐观数据,数据库更新稍后完成。只在应用能容忍该延迟情况下启用,以提升性能。
import { waitUntil } from "@vercel/functions";
export const auth = betterAuth({
advanced: {
backgroundTasks: {
handler: waitUntil,
},
}
plugins: [
apiKey({
deferUpdates: true,
}),
],
});import { AsyncLocalStorage } from "node:async_hooks";
const execCtxStorage = new AsyncLocalStorage<ExecutionContext>();
export const auth = betterAuth({
advanced: {
backgroundTasks: {
handler: waitUntil,
},
}
plugins: [
apiKey({
deferUpdates: true,
}),
],
});
// 在请求处理器中,使用 execCtxStorage.run(ctx, ...) 包裹permissions { defaultPermissions?: Statements | ((referenceId: string, ctx: GenericEndpointContext) => Statements | Promise<Statements>) }
API 密钥的权限设置。
关于权限的详细说明请参见下文 权限。
disableKeyHashing boolean
是否禁用 API 密钥的哈希存储。
安全警告:强烈建议不要禁用哈希存储。 明文存储 API 密钥可能在数据库泄露时导致所有用户的密钥暴露。
权限
API 密钥可以绑定权限,用以实现细粒度的访问控制。权限结构为资源类型与允许操作数组的映射。
设置默认权限
可以配置默认权限,应用于所有新创建的 API 密钥:
import { betterAuth } from "better-auth"
import { apiKey } from "better-auth/plugins"
export const auth = betterAuth({
plugins: [
apiKey({
permissions: {
defaultPermissions: {
files: ["read"],
users: ["read"],
},
},
}),
],
});也可以提供一个函数动态返回权限:
import { betterAuth } from "better-auth"
import { apiKey } from "better-auth/plugins"
export const auth = betterAuth({
plugins: [
apiKey({
permissions: {
defaultPermissions: async (referenceId, ctx) => {
// referenceId 是 userId 或 orgId,取决于配置
// 根据用户/组织角色或其他数据决定权限
return {
files: ["read"],
users: ["read"],
};
},
},
}),
],
});创建带有权限的 API 密钥
创建 API 密钥时可以指定自定义权限:
import { auth } from "@/lib/auth"
const apiKey = await auth.api.createApiKey({
body: {
name: "My API Key",
permissions: {
files: ["read", "write"],
users: ["read"],
},
userId: "userId",
},
});验证带权限的 API 密钥
验证 API 密钥时,可以检测是否具备所需权限:
import { auth } from "@/lib/auth"
const result = await auth.api.verifyApiKey({
body: {
key: "your_api_key_here",
permissions: {
files: ["read"],
},
},
});
if (result.valid) {
// API 密钥有效且拥有所需权限
} else {
// API 密钥无效或权限不足
}更新 API 密钥权限
可以修改已有 API 密钥的权限:
import { auth } from "@/lib/auth"
const apiKey = await auth.api.updateApiKey({
body: {
keyId: existingApiKeyId,
permissions: {
files: ["read", "write", "delete"],
users: ["read", "write"],
},
},
headers: user_headers,
});权限结构
权限采用基于资源的结构:
type Permissions = {
[resourceType: string]: string[];
};
// 示例:
const permissions = {
files: ["read", "write", "delete"],
users: ["read"],
projects: ["read", "write"],
};验证时,API 密钥必须包含所有请求的所需权限,才能校验通过。
模式
表:apikey
从旧版本迁移
从旧版本升级时,需要将 userId 字段迁移至新的 referenceId 系统:
-- 添加新列
ALTER TABLE apikey ADD COLUMN config_id VARCHAR(255) NOT NULL DEFAULT 'default';
ALTER TABLE apikey ADD COLUMN reference_id VARCHAR(255);
-- 迁移现有数据(把 userId 拷贝到 referenceId)
UPDATE apikey SET reference_id = user_id WHERE reference_id IS NULL;
-- 将 reference_id 设为非空并创建索引
ALTER TABLE apikey ALTER COLUMN reference_id SET NOT NULL;
CREATE INDEX idx_apikey_reference_id ON apikey(reference_id);
CREATE INDEX idx_apikey_config_id ON apikey(config_id);
-- 迁移确认无误后,可选择删除旧列
-- ALTER TABLE apikey DROP COLUMN user_id;重大变更:userId 字段已被替换为 referenceId。API 响应中返回 referenceId 而非 userId。拥有者类型(用户或组织)由配置的 references 决定,不会存储在每个密钥上。