API 密钥

API 密钥插件允许你为你的应用创建和管理 API 密钥。它通过验证 API 密钥提供了一种认证和授权 API 请求的方式。

【The API Key plugin allows you to create and manage API keys for your application. It provides a way to authenticate and authorize API requests by verifying API keys.】

特性

【Features】

安装

【Installation】

将插件添加到服务器

auth.ts
import { betterAuth } from "better-auth"
import { apiKey } from "better-auth/plugins"

export const auth = betterAuth({
    plugins: [ 
        apiKey() 
    ] 
})

Migrate the database

运行迁移或生成架构,以向数据库添加必要的字段和表。

npx @better-auth/cli migrate
npx @better-auth/cli generate

See the Schema section to add the fields manually.

Add the client plugin

auth-client.ts
import { createAuthClient } from "better-auth/client"
import { apiKeyClient } from "better-auth/client/plugins"

export const authClient = createAuthClient({
    plugins: [ 
        apiKeyClient() 
    ] 
})

用法

【Usage】

你可以在此查看 API 密钥插件选项列表 here

【You can view the list of API Key plugin options here.】

创建 API 密钥

【Create an API key】

POST
/api-key/create
Notes

你可以通过使用服务器方法来调整更具体的 API 密钥配置。

const { data, error } = await authClient.apiKey.create({    name: 'project-api-key',    expiresIn: 60 * 60 * 24 * 7,    prefix: 'project-api-key',    metadata: { someKey: 'someValue' },});
PropDescriptionType
name?
Name of the Api Key.
string
expiresIn?
Expiration time of the Api Key in seconds.
number
prefix?
Prefix of the Api Key.
string
metadata?
Metadata of the Api Key.
any | null
API 密钥分配给用户。

结果

【Result】

它将返回包含供你使用的 key 值的 ApiKey 对象。否则,如果发生异常,它将抛出一个 APIError

【It'll return the ApiKey object which includes the key value for you to use. Otherwise if it throws, it will throw an APIError.】


验证 API 密钥

【Verify an API key】

const permissions = { // Permissions to check are optional.  projects: ["read", "read-write"],}const data = await auth.api.verifyApiKey({    body: {        key: "your_api_key_here", // required        permissions,    },});
PropDescriptionType
key
The key to verify.
string
permissions?
The permissions to verify. Optional.
Record<string, string[]>

结果

【Result】

type Result = {
  valid: boolean;
  error: { message: string; code: string } | null;
  key: Omit<ApiKey, "key"> | null;
};

获取 API 密钥

【Get an API key】

GET
/api-key/get
const { data, error } = await authClient.apiKey.get({    query: {        id: "some-api-key-id", // required    },});
PropDescriptionType
id
The id of the Api Key.
string

结果

【Result】

你将收到有关 API 密钥的所有详细信息,但不包括 key 值本身。如果失败,它将抛出 APIError

【You'll receive everything about the API key details, except for the key value itself. If it fails, it will throw an APIError.】

type Result = Omit<ApiKey, "key">;

更新 API 密钥

【Update an API key】

POST
/api-key/update
const { data, error } = await authClient.apiKey.update({    keyId: "some-api-key-id", // required    name: "some-api-key-name",});
PropDescriptionType
keyId
The id of the Api Key to update.
string
name?
The name of the key.
string

结果

【Result】

如果失败,会抛出 APIError。否则,你将收到 API 密钥的详细信息,但不包括 key 值本身。

【If fails, throws APIError. Otherwise, you'll receive the API Key details, except for the key value itself.】


删除 API 密钥

【Delete an API Key】

POST
/api-key/delete
Notes

This endpoint is attempting to delete the API key from the perspective of the user. It will check if the user's ID matches the key owner to be able to delete it. If you want to delete a key without these checks, we recommend you use an ORM to directly mutate your DB instead.

const { data, error } = await authClient.apiKey.delete({    keyId: "some-api-key-id", // required});
PropDescriptionType
keyId
The id of the Api Key to delete.
string

结果

【Result】

如果失败,则抛出 APIError。否则,你将收到:

【If fails, throws APIError. Otherwise, you'll receive:】

type Result = {
  success: boolean;
};

列出 API 密钥

【List API keys】

GET
/api-key/list
const { data, error } = await authClient.apiKey.list();

结果

【Result】

如果失败,则抛出 APIError。否则,你将收到:

【If fails, throws APIError. Otherwise, you'll receive:】

type Result = ApiKey[];

删除所有过期的 API 密钥

【Delete all expired API keys】

此功能将删除所有已过期的 API 密钥。

【This function will delete all API keys that have an expired expiration date.】

const data = await auth.api.deleteAllExpiredApiKeys();

每次调用任何 apiKey 插件端点时,我们都会自动删除过期的 API 密钥,但每次调用都有 10 秒的冷却时间,以防止对数据库的多次调用。


来自 API 密钥的会话

【Sessions from API keys】

每当调用 Better Auth 中的某个端点,并且请求头中包含有效的 API 密钥时,你可以通过启用 sessionForAPIKeys 选项自动创建一个模拟会话来表示该用户。

【Any time an endpoint in Better Auth is called that has a valid API key in the headers, you can automatically create a mock session to represent the user by enabling sessionForAPIKeys option.】

这通常不推荐,因为如果使用不当可能会导致安全问题。泄露的 API 密钥可能被用来冒充用户。

速率限制说明:当启用 enableSessionForAPIKeys 时,API 密钥会在每次请求时进行验证,并相应地应用速率限制。
如果你手动验证 API 密钥然后单独获取会话,这两个操作都会增加速率限制计数。使用 enableSessionForAPIKeys 可以避免这种双重增加。

export const auth = betterAuth({
  plugins: [
    apiKey({
      enableSessionForAPIKeys: true,
    }),
  ],
});
const session = await auth.api.getSession({
      headers: new Headers({
            'x-api-key': apiKey,
      }),
});

默认的请求头键是 x-api-key,但可以通过在插件选项中设置 apiKeyHeaders 选项来更改。

【The default header key is x-api-key, but this can be changed by setting the apiKeyHeaders option in the plugin options.】

export const auth = betterAuth({
  plugins: [
    apiKey({
      apiKeyHeaders: ["x-api-key", "xyz-api-key"], // or you can pass just a string, eg: "x-api-key"
    }),
  ],
});

或者,你也可以将一个 apiKeyGetter 函数传递给插件选项,该函数将接收 GenericEndpointContext 调用,然后你应该从中返回 API 密钥,如果请求无效,则返回 null

【Or optionally, you can pass an apiKeyGetter function to the plugin options, which will be called with the GenericEndpointContext, and from there, you should return the API key, or null if the request is invalid.】

export const auth = betterAuth({
  plugins: [
    apiKey({
      apiKeyGetter: (ctx) => {
        const has = ctx.request.headers.has("x-api-key");
        if (!has) return null;
        return ctx.request.headers.get("x-api-key");
      },
    }),
  ],
});

存储模式

【Storage Modes】

API 密钥插件支持多种存储模式,可灵活管理 API 密钥,让你根据具体使用情况选择最佳策略。

【The API Key plugin supports multiple storage modes for flexible API key management, allowing you to choose the best strategy for your use case.】

存储模式选项

【Storage Mode Options】

"database"(默认)

"database" (Default)】

仅在数据库适配器中存储 API 密钥。这是默认模式,无需额外配置。

【Store API keys only in the database adapter. This is the default mode and requires no additional configuration.】

export const auth = betterAuth({
  plugins: [
    apiKey({
      storage: "database", // Default, can be omitted
    }),
  ],
});

"secondary-storage"

API 密钥仅存储在二级存储中(例如 Redis)。 不要回退到数据库。最适合所有密钥已迁移到二级存储的高性能场景。

【Store API keys only in secondary storage (e.g., Redis). No fallback to database. Best for high-performance scenarios where all keys are migrated to secondary storage.】

import { createClient } from "redis";
import { betterAuth } from "better-auth";
import { apiKey } from "better-auth/plugins";

const redis = createClient();
await redis.connect();

export const auth = betterAuth({
  secondaryStorage: {
    get: async (key) => 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",
    }),
  ],
});

带回退功能的二级存储

【Secondary Storage with Fallback】

先检查二级存储,如果未找到再回退到数据库。

【Check secondary storage first, then fallback to database if not found.】

读取行为:

  • 首先检查二级存储
  • 如果未找到,则查询数据库
  • 在回退到数据库时自动填充二级存储(缓存预热)
  • 确保常访问的键随时间保持在缓存中

写入行为:

  • 写入到数据库和二级存储
  • 确保两层存储之间的一致性
export const auth = betterAuth({
  secondaryStorage: {
    get: async (key) => 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",
      fallbackToDatabase: true,
    }),
  ],
});

自定义存储方法

【Custom Storage Methods】

你可以为 API 密钥提供自定义存储方法,以覆盖全局 secondaryStorage 配置:

【You can provide custom storage methods specifically for API keys, overriding the global secondaryStorage configuration:】

export const auth = betterAuth({
  plugins: [
    apiKey({
      storage: "secondary-storage",
      customStorage: {
        get: async (key) => {
          // Custom get logic for API keys
          return await customStorage.get(key);
        },
        set: async (key, value, ttl) => {
          // Custom set logic for API keys
          await customStorage.set(key, value, ttl);
        },
        delete: async (key) => {
          // Custom delete logic for API keys
          await customStorage.delete(key);
        },
      },
    }),
  ],
});

速率限制

【Rate Limiting】

每个 API 密钥都可以有自己的速率限制设置。内置的速率限制会在每次验证 API 密钥时应用,包括:

  • 通过 /api-key/verify 端点验证 API 密钥时
  • 使用 API 密钥创建会话时(如果启用了 enableSessionForAPIKeys),速率限制适用于使用该 API 密钥的所有端点

【Every API key can have its own rate limit settings. The built-in rate-limiting applies whenever an API key is validated, which includes:

  • When verifying an API key via the /api-key/verify endpoint
  • When using API keys for session creation (if enableSessionForAPIKeys is enabled), rate limiting applies to all endpoints that use the API key】

对于不使用 API 密钥的其他端点/方法,你应该使用 Better Auth 的内置速率限制

【For other endpoints/methods that don't use API keys, you should utilize Better Auth's built-in rate-limiting.】

双重速率限制增加:如果你使用 verifyApiKey() 手动验证 API 密钥,然后使用相同的 API 密钥头通过 getSession() 获取会话,则这两个操作都会增加速率限制计数器,导致单次请求增加两次。为避免这种情况,可以选择以下方法之一:

  • 使用 enableSessionForAPIKeys: true,让 Better Auth 自动处理会话创建(推荐)
  • 或者只验证一次 API 密钥,并重复使用已验证的结果,而不是分别调用这两个方法

你可以在 API 密钥插件选项中参考下面的速率限制默认配置。

【You can refer to the rate-limit default configurations below in the API Key plugin options.】

一个示例默认值:

【An example default value:】

export const auth = betterAuth({
  plugins: [
    apiKey({
      rateLimit: {
        enabled: true,
        timeWindow: 1000 * 60 * 60 * 24, // 1 day
        maxRequests: 10, // 10 requests per day
      },
    }),
  ],
});

对于每个 API 密钥,你可以在创建时自定义速率限制选项。

【For each API key, you can customize the rate-limit options on create.】

你只能在服务器认证实例上自定义速率限制选项。

const apiKey = await auth.api.createApiKey({
  body: {
    rateLimitEnabled: true,
    rateLimitTimeWindow: 1000 * 60 * 60 * 24, // 1 day
    rateLimitMax: 10, // 10 requests per day
  },
  headers: user_headers,
});

它是如何工作的?

【How does it work?】

限流系统采用滑动窗口方法:

【The rate limiting system uses a sliding window approach:】

  1. 第一次请求:当 API 密钥首次使用(没有之前的 lastRequest)时,请求将被允许,并且 requestCount 设置为 1。
  2. 窗口内:在 timeWindow 内的后续请求中,requestCount 会递增。如果 requestCount 达到 rateLimitMax,请求将被拒绝,并返回 RATE_LIMITED 错误代码。
  3. 窗口重置:如果自上一次请求以来的时间超过了 timeWindow,窗口将重置:requestCount 会重置为 1,lastRequest 会更新为当前时间。
  4. 超出速率限制:当请求因速率限制被拒绝时,错误响应会包含一个 tryAgainIn 值(以毫秒为单位),用于指示在时间窗口重置之前需要等待的时间。

禁用速率限制

  • 全局:在插件选项中设置 rateLimit.enabled: false
  • 按键:在创建或更新 API 密钥时设置 rateLimitEnabled: false
  • 空值:如果 rateLimitTimeWindowrateLimitMaxnull,则该密钥的速率限制实际上已被禁用

当速率限制被禁用(全局或按键)时,请求仍然被允许,但会更新 lastRequest 以便跟踪。

【When rate limiting is disabled (globally or per-key), requests are still allowed but lastRequest is updated for tracking purposes.】

剩余量、补充和有效期

【Remaining, refill, and expiration】

剩余次数是指在 API 密钥被禁用之前剩下的请求次数。 补充间隔是指以毫秒为单位的时间间隔,当自上次补充(或如果尚未补充,则从创建时起)经过该间隔后,remaining 次数将被补充。 过期时间是 API 密钥的到期日期。

【The remaining count is the number of requests left before the API key is disabled. The refill interval is the interval in milliseconds where the remaining count is refilled when the interval has passed since the last refill (or since creation if no refill has occurred yet). The expiration time is the expiration date of the API key.】

它是如何工作的?

【How does it work?】

剩余:

【Remaining:】

每当使用 API 密钥时,remaining(剩余次数)会被更新。
如果 remainingnull,则表示该密钥使用没有上限。
否则,remaining 会减少 1。
如果 remaining 为 0,则该 API 密钥会被禁用并移除。

【Whenever an API key is used, the remaining count is updated. If the remaining count is null, then there is no cap to key usage. Otherwise, the remaining count is decremented by 1. If the remaining count is 0, then the API key is disabled & removed.】

补充间隔 & 补充数量:

【refillInterval & refillAmount:】

每当创建 API 密钥时,refillIntervalrefillAmount 默认设置为 null。 这意味着 API 密钥不会自动补充。 然而,如果同时设置了 refillIntervalrefillAmount,那么每次使用 API 密钥时:

  • 系统会检查自上次补充(或如果没有补充,则自创建以来)经过的时间是否超过 refillInterval
  • 如果已超过该间隔,remaining 计数会重置为 refillAmount(而不是增加)
  • lastRefillAt 时间戳会更新为当前时间

【Whenever an API key is created, the refillInterval and refillAmount are set to null by default. This means that the API key will not be refilled automatically. However, if both refillInterval & refillAmount are set, then whenever the API key is used:

  • The system checks if the time since the last refill (or since creation if no refill has occurred) exceeds the refillInterval
  • If the interval has passed, the remaining count is reset to refillAmount (not incremented)
  • The lastRefillAt timestamp is updated to the current time】

过期时间:

【Expiration:】

每当创建 API 密钥时,expiresAt 会被设置为 null。这意味着 API 密钥永不过期。然而,如果设置了 expiresIn,那么 API 密钥将在 expiresIn 时间后过期。

【Whenever an API key is created, the expiresAt is set to null. This means that the API key will never expire. However, if the expiresIn is set, then the API key will expire after the expiresIn time.】

自定义密钥生成与验证

【Custom Key generation & verification】

你可以直接从插件选项自定义密钥生成和验证过程。

【You can customize the key generation and verification process straight from the plugin options.】

举个例子:

【Here's an example:】

export const auth = betterAuth({
  plugins: [
    apiKey({
      customKeyGenerator: (options: {
        length: number;
        prefix: string | undefined;
      }) => {
        const apiKey = mySuperSecretApiKeyGenerator(
          options.length,
          options.prefix
        );
        return apiKey;
      },
      customAPIKeyValidator: async ({ ctx, key }) => {
        const res = await keyService.verify(key)
        return res.valid
      },
    }),
  ],
});

如果你没有使用 customKeyGenerator 提供的 length 属性,你必须defaultKeyLength 属性设置为生成的密钥长度。

export const auth = betterAuth({
  plugins: [
    apiKey({
      customKeyGenerator: () => {
        return crypto.randomUUID();
      },
      defaultKeyLength: 36, // Or whatever the length is
    }),
  ],
});

如果一个 API 密钥通过了你的 customAPIKeyValidator 验证,我们仍然必须将其与数据库中的密钥进行匹配。
然而,通过提供这个自定义函数,你可以提升 API 密钥验证过程的性能,
因为所有失败的密钥可以在无需查询数据库的情况下被作废。

【If an API key is validated from your customAPIKeyValidator, we still must match that against the database's key. However, by providing this custom function, you can improve the performance of the API key verification process, as all failed keys can be invalidated without having to query your database.】

元数据

【Metadata】

我们允许你将元数据与你的 API 密钥一起存储。这对于存储有关密钥的信息非常有用,例如订阅计划。

【We allow you to store metadata alongside your API keys. This is useful for storing information about the key, such as a subscription plan for example.】

要存储元数据,请确保你没有在插件选项中禁用元数据功能。

【To store metadata, make sure you haven't disabled the metadata feature in the plugin options.】

export const auth = betterAuth({
  plugins: [
    apiKey({
      enableMetadata: true,
    }),
  ],
});

然后,你可以将元数据存储在 API 密钥对象的 metadata 字段中。

【Then, you can store metadata in the metadata field of the API key object.】

const apiKey = await auth.api.createApiKey({
  body: {
    metadata: {
      plan: "premium",
    },
  },
});

然后你可以从 API 密钥对象中检索元数据。

【You can then retrieve the metadata from the API key object.】

const apiKey = await auth.api.getApiKey({
  body: {
    keyId: "your_api_key_id_here",
  },
});

console.log(apiKey.metadata.plan); // "premium"

API 密钥插件选项

【API Key plugin options】

apiKeyHeaders 字符串 | 字符串数组;

用于检查 API 密钥的请求头名称。默认是 x-api-key

【The header name to check for API key. Default is x-api-key.】

customAPIKeyGetter (ctx: GenericEndpointContext) => string | null

一个用于从上下文中获取 API 密钥的自定义函数。

【A custom function to get the API key from the context.】

customAPIKeyValidator (options: { ctx: GenericEndpointContext; key: string; }) => boolean | Promise<boolean>

用于验证 API 密钥的自定义函数。

【A custom function to validate the API key.】

customKeyGenerator (options: { length: number; prefix: string | undefined; }) => string | Promise<string>

用于生成 API 密钥的自定义函数。

【A custom function to generate the API key.】

startingCharactersConfig { shouldStore?: boolean; charactersLength?: number; }

自定义起始字符配置。

【Customize the starting characters configuration.】

defaultKeyLength number

API 密钥的长度。越长越好。默认值为 64。(不包括前缀长度)

【The length of the API key. Longer is better. Default is 64. (Doesn't include the prefix length)】

defaultPrefix string

API 密钥的前缀。

【The prefix of the API key.】

注意:我们建议你在前缀后添加一个下划线,以使前缀更易识别。(例如 hello_

【Note: We recommend you append an underscore to the prefix to make the prefix more identifiable. (eg hello_)】

maximumPrefixLength number

前缀的最大长度。

【The maximum length of the prefix.】

minimumPrefixLength number

前缀的最小长度。

【The minimum length of the prefix.】

requireName boolean

是否要求为 API 密钥提供名称。默认值为 false

【Whether to require a name for the API key. Default is false.】

maximumNameLength number

名称的最大长度。

【The maximum length of the name.】

minimumNameLength number

名称的最小长度。

【The minimum length of the name.】

enableMetadata boolean

是否为 API 密钥启用元数据。

【Whether to enable metadata for an API key.】

keyExpiration { defaultExpiresIn?: number | null; disableCustomExpiresTime?: boolean; minExpiresIn?: number; maxExpiresIn?: number; }

自定义密钥过期时间。

【Customize the key expiration.】

rateLimit { enabled?: boolean; timeWindow?: number; maxRequests?: number; }

自定义速率限制。

【Customize the rate-limiting.】

schema 推断选项模式<ReturnType<typeof apiKeySchema>>

API 密钥插件的自定义模式。

【Custom schema for the API key plugin.】

enableSessionForAPIKeys boolean

API 密钥可以表示一个有效的会话,因此如果我们在请求头中找到有效的 API 密钥,就可以为用户模拟一个会话。默认值为 false

【An API Key can represent a valid session, so we can mock a session for the user if we find a valid API key in the request headers. Default is false.】

“存储” “数据库” |“二次存储”

用于 API 密钥的存储后端。默认值为 database

【Storage backend for API keys. Default is "database".】

  • "database":将 API 密钥存储在数据库适配器中(默认)
  • secondary-storage:将 API 密钥存储在配置的二级存储中(例如 Redis)

fallbackToDatabase boolean

当“存储”变为“二级存储”时,如果二级存储中找不到密钥,则启用备份到数据库。 默认为“假”。

【When storage is "secondary-storage", enable fallback to database if key is not found in secondary storage. Default is false.】

当“storage”设置为“secondary-storage”时,你必须在“更好认证”选项中配置“secondaryStorage”。API 密钥将通过键值模式存储:

  • api-key:${hashedKey} - 通过哈希键进行主查询
  • api-key:by-id:${id} - 通过
  • IDapi-key:by-user:${userId} 查找 - 用户的 API 密钥列表

如果 API 密钥有过期日期(expiresAt),次级存储中将会自动设置 TTL,以确保自动清理。

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。自定义方法优先于全局二级存储。

【Custom storage methods for API keys. If provided, these methods will be used instead of ctx.context.secondaryStorage. Custom methods take precedence over global secondary storage.】

当你想为 API 密钥使用不同的存储后端,或在存储操作中需要自定义逻辑时,这很有用。

【Useful when you want to use a different storage backend specifically for API keys, or when you need custom logic for storage operations.】

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

【Defer non-critical updates (rate limiting counters, timestamps, remaining count) to run after the response is sent using the global backgroundTasks handler. This can significantly improve response times on serverless platforms. Default is false.】

需要在主要的认证选项中配置 backgroundTasks.handler

【Requires backgroundTasks.handler to be configured in the main auth options.】

启用此功能会引入最终一致性,即响应会在数据库更新之前返回乐观数据。只有在你的应用能够接受为提高延迟而做出的这种权衡时才启用。

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,
    }),
  ],
});

// In your request handler, wrap with execCtxStorage.run(ctx, ...)

permissions { defaultPermissions?: Statements | ((userId: string, ctx: GenericEndpointContext) => Statements | Promise<Statements>) }

API 密钥的权限。

【Permissions for the API key.】

这里阅读更多关于权限的信息。

【Read more about permissions here.】

disableKeyHashing boolean

禁用 API 密钥的哈希处理。

【Disable hashing of the API key.】

⚠️ 安全警告:强烈建议不要禁用哈希处理。将 API 密钥以明文形式存储会使其容易受到数据库泄露的影响,可能导致所有用户的 API 密钥被暴露。


权限

【Permissions】

API 密钥可以关联权限,允许你在细粒度级别上控制访问。权限被构造成资源类型到允许操作数组的记录。

【API keys can have permissions associated with them, allowing you to control access at a granular level. Permissions are structured as a record of resource types to arrays of allowed actions.】

设置默认权限

【Setting Default Permissions】

你可以配置默认权限,这些权限将应用于所有新创建的 API 密钥:

【You can configure default permissions that will be applied to all newly created API keys:】

export const auth = betterAuth({
  plugins: [
    apiKey({
      permissions: {
        defaultPermissions: {
          files: ["read"],
          users: ["read"],
        },
      },
    }),
  ],
});

你也可以提供一个动态返回权限的函数:

【You can also provide a function that returns permissions dynamically:】

export const auth = betterAuth({
  plugins: [
    apiKey({
      permissions: {
        defaultPermissions: async (userId, ctx) => {
          // Fetch user role or other data to determine permissions
          return {
            files: ["read"],
            users: ["read"],
          };
        },
      },
    }),
  ],
});

创建带权限的 API 密钥

【Creating API Keys with Permissions】

创建 API 密钥时,你可以指定自定义权限:

【When creating an API key, you can specify custom permissions:】

const apiKey = await auth.api.createApiKey({
  body: {
    name: "My API Key",
    permissions: {
      files: ["read", "write"],
      users: ["read"],
    },
    userId: "userId",
  },
});

验证具有所需权限的 API 密钥

【Verifying API Keys with Required Permissions】

在验证 API 密钥时,你可以检查它是否具有所需的权限:

【When verifying an API key, you can check if it has the required permissions:】

const result = await auth.api.verifyApiKey({
  body: {
    key: "your_api_key_here",
    permissions: {
      files: ["read"],
    },
  },
});

if (result.valid) {
  // API key is valid and has the required permissions
} else {
  // API key is invalid or doesn't have the required permissions
}

更新 API 密钥权限

【Updating API Key Permissions】

你可以更新现有 API 密钥的权限:

【You can update the permissions of an existing API key:】

const apiKey = await auth.api.updateApiKey({
  body: {
    keyId: existingApiKeyId,
    permissions: {
      files: ["read", "write", "delete"],
      users: ["read", "write"],
    },
  },
  headers: user_headers,
});

权限结构

【Permissions Structure】

权限遵循基于资源的结构:

【Permissions follow a resource-based structure:】

type Permissions = {
  [resourceType: string]: string[];
};

// Example:
const permissions = {
  files: ["read", "write", "delete"],
  users: ["read"],
  projects: ["read", "write"],
};

在验证 API 密钥时,API 密钥的权限中必须包含所有必需的权限,验证才能成功。

【When verifying an API key, all required permissions must be present in the API key's permissions for validation to succeed.】

架构

【Schema】

表:apikey

【Table: apikey

Field NameTypeKeyDescription
idstringThe ID of the API key.
namestringThe name of the API key.
startstringThe starting characters of the API key. Useful for showing the first few characters of the API key in the UI for the users to easily identify.
prefixstringThe API Key prefix. Stored as plain text.
keystring-The hashed API key itself.
userIdstringThe ID of the user associated with the API key.
refillIntervalnumberThe interval to refill the key in milliseconds.
refillAmountnumberThe amount to refill the remaining count of the key.
lastRefillAtDateThe date and time when the key was last refilled.
enabledboolean-Whether the API key is enabled.
rateLimitEnabledboolean-Whether the API key has rate limiting enabled.
rateLimitTimeWindownumberThe time window in milliseconds for the rate limit.
rateLimitMaxnumberThe maximum number of requests allowed within the `rateLimitTimeWindow`.
requestCountnumber-The number of requests made within the rate limit time window.
remainingnumberThe number of requests remaining.
lastRequestDateThe date and time of the last request made to the key.
expiresAtDateThe date and time when the key will expire.
createdAtDate-The date and time the API key was created.
updatedAtDate-The date and time the API key was updated.
permissionsstringThe permissions of the key.
metadataObjectAny additional metadata you want to store with the key.