参考
API 密钥插件选项、权限及模式参考。
API 密钥插件选项
configId string
该配置的唯一标识符。在使用多个配置时必填。默认值为 "default"。
references "user" | "organization"
What the API key references. This determines ownership over the API key. Default is "user".
"user": API keys are owned by users (requiresuserIdon creation)"organization": API keys are owned by organizations (requiresorganizationIdon creation)
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": Store API keys in the database adapter (default)"secondary-storage": Store API keys in the configured secondary storage (e.g., Redis)
fallbackToDatabase boolean
当 storage 设为 "secondary-storage" 时,若未在二级存储中找到密钥,是否回退至数据库查找。
默认值为 false。
When storage is set to "secondary-storage", you must configure secondaryStorage in your Better Auth options. API keys will be stored using key-value patterns:
api-key:${hashedKey}- Primary lookup by hashed keyapi-key:by-id:${id}- Lookup by IDapi-key:by-ref:${referenceId}- Reference's API key list (user or organization)
If an API key has an expiration date (expiresAt), a TTL will be automatically set in secondary storage to ensure automatic cleanup.
import { betterAuth } from "better-auth";
import { apiKey } from "@better-auth/api-key"
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/api-key"
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 密钥的哈希存储。
Security Warning: It's strongly recommended to not disable hashing. Storing API keys in plaintext makes them vulnerable to database breaches, potentially exposing all your users' API keys.
权限
API 密钥可以绑定权限,用以实现细粒度的访问控制。权限结构为资源类型与允许操作数组的映射。
设置默认权限
可以配置默认权限,应用于所有新创建的 API 密钥:
import { betterAuth } from "better-auth"
import { apiKey } from "@better-auth/api-key"
export const auth = betterAuth({
plugins: [
apiKey({
permissions: {
defaultPermissions: {
files: ["read"],
users: ["read"],
},
},
}),
],
});也可以提供一个函数动态返回权限:
import { betterAuth } from "better-auth"
import { apiKey } from "@better-auth/api-key"
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 决定,不会存储在每个密钥上。