身份验证钩子
Use HTTP or Postgres Functions to customize your authentication flow
钩子是什么 #
🌐 What is a hook
钩子是一个端点,它允许你在特定的执行点更改默认的 Supabase 身份验证流程。开发者可以使用钩子来添加原生不支持的自定义行为。
🌐 A hook is an endpoint that allows you to alter the default Supabase Auth flow at specific execution points. Developers can use hooks to add custom behavior that's not supported natively.
Hooks 可以帮你:
🌐 Hooks help you:
- 通过添加元数据来追踪用户注册来源
- 通过为密码和多因素认证增加额外检查来提高安全性
- 通过与外部认证系统的身份凭证集成来支持传统系统
- 向你的 JWT 添加额外的自定义声明
- 通过自定义提供商发送认证邮件或短信
以下钩子可用:
🌐 The following hooks are available:
| 钩子 | 可用计划 |
|---|---|
| 用户创建前 | 免费, 专业版 |
| 自定义访问令牌 | 免费, 专业版 |
| 发送短信 | 免费, 专业版 |
| 发送邮件 | 免费, 专业版 |
| 多因素验证尝试 | 团队版和企业版 |
| 密码验证尝试 | 团队版和企业版 |
Supabase 支持在你的项目中通过两种方式配置钩子:
🌐 Supabase supports 2 ways to configure a hook in your project:
一个 Postgres 函数 可以被配置为一个钩子。这个函数应该接收一个参数——类型为 JSONB 的事件——并返回一个 JSONB 对象。由于 Postgres 函数在你的数据库上运行,请求不会离开你的项目实例。
🌐 A Postgres function can be configured as a hook. The function should take in a single argument -- the event of type JSONB -- and return a JSONB object. Since the Postgres function runs on your database, the request does not leave your project's instance.
安全模型 #
🌐 Security model
对有效载荷进行签名,并有选择地授予权限,以保护有效载荷的完整性。
🌐 Sign the payload and grant permissions selectively in order to guard the integrity of the payload.
当你将 Postgres 函数配置为钩子时,Supabase 会自动将以下权限应用到该函数,原因如下:
🌐 When you configure a Postgres function as a hook, Supabase will automatically apply the following grants to the function for these reasons:
- 允许
supabase_auth_admin角色执行该功能。supabase_auth_admin角色是 Supabase Auth 用来向你的数据库发出请求的 Postgres 角色。 - 撤销其他角色(例如
anon、authenticated、public)的权限,以确保 Supabase 数据 API 无法访问该功能。
1-- Grant access to function to supabase_auth_admin2grant execute3 on function public.custom_access_token_hook4 to supabase_auth_admin;56-- Grant access to schema to supabase_auth_admin7grant usage on schema public to supabase_auth_admin;89-- Revoke function permissions from authenticated, anon and public10revoke execute11 on function public.custom_access_token_hook12 from authenticated, anon, public;你需要修改你的行级安全(RLS)策略,以允许 supabase_auth_admin 角色访问你已经设置了 RLS 策略的表。你可以在 这里 阅读更多关于 RLS 策略的信息。
🌐 You will need to alter your row-level security (RLS) policies to allow the supabase_auth_admin role to access tables that you have RLS policies on. You can read more about RLS policies here.
或者,你可以通过仪表板使用 security definer 标签创建你的 Postgres 函数。security definer 标签则表示函数将以拥有它的用户的权限执行。
🌐 Alternatively, you can create your Postgres function via the dashboard with the security definer tag. The security definer tag specifies that the function is to be executed with the privileges of the user that owns it.
目前,通过仪表板创建的函数会获取 postgres 角色。想了解关于 security definer 标签的更多信息,请查看我们的数据库指南 在这里
🌐 Currently, functions created via the dashboard take on the postgres role. Read more about the security definer tag in our database guide
使用 Hooks #
🌐 Using Hooks
开发中 #
🌐 Developing
让我们先在本地开发一个 Hook,然后再部署到云端。回顾一下,这里有一个可用 Hook 的列表
🌐 Let us develop a Hook locally and then deploy it to the cloud. As a recap, here’s a list of available Hooks
| 钩子 | 建议的函数名称 | 调用时机 | 功能说明 |
|---|---|---|---|
| 发送短信 | send_sms | 每次发送短信时 | 允许你自定义消息内容和短信提供商 |
| 发送邮件 | send_email | 每次发送邮件时 | 允许你自定义消息内容和邮件提供商 |
| 自定义访问令牌 | custom_access_token | 每次创建新的 JWT 时 | 返回你希望在 JWT 中包含的声明 |
| 多因素验证尝试 | mfa_verification_attempt | 每次用户尝试验证 MFA 因子时 | 返回是否拒绝此次及未来尝试,或允许用户继续尝试的决定 |
| 密码验证尝试 | password_verification_attempt | 每次用户尝试使用密码登录时 | 返回是否允许用户拒绝尝试,或允许用户继续尝试的决定 |
编辑 config.toml 来本地设置认证钩子。
🌐 Edit config.toml to set up the Auth Hook locally.
config.toml 中使用的钩子名称必须与上面列出的可用钩子之一相对应。例如,发送短信钩子可以配置为:[auth.hook.send_sms]
Modify the auth.hook.<hook_name> field and set uri to a value of pg-functions://postgres/<schema>/<function_name>
1[auth.hook.<hook_name>]2enabled = true3uri = "pg-functions://...."你需要分配额外的权限,这样 Supabase Auth 才能访问这个钩子以及它要操作的表。
🌐 You need to assign additional permissions so that Supabase Auth can access the hook as well as the tables it interacts with.
supabase_auth_admin 角色没有 public 模式的权限。你需要给这个角色授权以执行你的钩子:
🌐 The supabase_auth_admin role does not have permissions to the public schema. You need to grant the role permission to execute your hook:
1grant execute2 on function public.custom_access_token_hook3 to supabase_auth_admin;你还需要给 supabase_auth_admin 授权使用:
🌐 You also need to grant usage to supabase_auth_admin:
1grant usage on schema public to supabase_auth_admin;还要撤销 authenticated 和 anon 角色的权限,以确保 Supabase Serverless API 无法访问这个功能。
🌐 Also revoke permissions from the authenticated and anon roles to ensure the function is not accessible by Supabase Serverless APIs.
1revoke execute2 on function public.custom_access_token_hook3 from authenticated, anon;出于安全考虑,我们建议不要使用 security definer 标签。security definer 标签表示函数将以拥有它的用户的权限执行。当通过 Supabase 仪表板使用该标签创建函数时,它将拥有 postgres 角色的广泛权限,这可能更容易发生不希望的操作。
🌐 For security, we recommend against the use the security definer tag. The security definer tag specifies that the function is to be executed with the privileges of the user that owns it. When a function is created via the Supabase dashboard with the tag, it will have the extensive permissions of the postgres role which make it easier for undesirable actions to occur.
我们建议你不要使用任何标签,并按照上面描述的那样明确授予 supabase_auth_admin 权限。
🌐 We recommend that you do not use any tag and explicitly grant permissions to supabase_auth_admin as described above.
在我们的数据库指南中了解更多关于 security definer 标签的信息 点击这里。
🌐 Read more about security definer tag in our database guide.
完成后,将你的身份验证 Hook 保存为迁移,以便对身份验证 Hook 进行版本控制并与其他团队成员共享。运行 supabase migration new 来创建迁移。
🌐 Once done, save your Auth Hook as a migration in order to version the Auth Hook and share it with other team members. Run supabase migration new to create a migration.
如果你在使用 Supabase SQL 编辑器,当使用 ?(字符串是否作为 JSON 值的顶层键存在?)操作符时会出现问题。如果在定义函数时需要使用它,请直接连接到数据库。
🌐 If you're using the Supabase SQL Editor, there's an issue when using the ? (Does the string exist as a top-level key within the JSON value?) operator. Use a direct connection to the database if you need to use it when defining a function.
这里是一个示例钩子签名:
🌐 Here is an example hook signature:
1create or replace function public.custom_access_token_hook(event jsonb)2returns jsonb3language plpgsql4as $$5declare6 -- Insert variables here7begin8 -- Insert logic here9 return event;10end;11$$;你可以去 SQL Editor > Templates 查看 hook 模板。
🌐 You can visit SQL Editor > Templates for hook templates.
部署中 #
🌐 Deploying
在仪表板中,导航到 Authentication > Hooks,然后从下拉菜单中选择合适的功能类型(SQL 或 HTTP)。
🌐 In the dashboard, navigate to Authentication > Hooks and select the appropriate function type (SQL or HTTP) from the dropdown menu.
错误处理 #
🌐 Error handling
当遇到运行时错误时,你应该返回一个错误。运行时错误是针对你的应用的,通常是由特定的业务规则引起的,而不是程序员的错误。
🌐 You should return an error when facing a runtime error. Runtime errors are specific to your application and arise from specific business rules rather than programmer errors.
运行时错误可能会发生在:
🌐 Runtime errors could happen when:
- 用户没有相应的权限
- 收到的事件负载没有必要的声明。
- 用户执行了一个违反业务规则的操作。
- 在 webhook 中使用的电子邮件或电话提供商返回了一个错误。
这个错误是一个 JSON 对象,并且具有以下属性:
🌐 The error is a JSON object and has the following properties:
error一个包含错误信息的对象。http_code表示要返回的 HTTP 状态码。如果未设置,则默认返回 HTTP 500 内部服务器错误。message要在HTTP响应中返回的消息。必填。
这里有一个例子:
🌐 Here's an example:
1{2 "error": {3 "http_code": 429,4 "message": "You can only verify a factor once every 10 seconds."5 }6}从 Postgres 钩子返回的错误是无法重试的。当返回错误时,错误会从钩子传递到 Supabase Auth,并被转换成 HTTP 错误返回给你的应用。Supabase Auth 只会考虑这个错误,其他的负载则会被忽略。
🌐 Errors returned from a Postgres Hook are not retry-able. When an error is returned, the error is propagated from the hook to Supabase Auth and translated into an HTTP error which is returned to your application. Supabase Auth will only take into account the error and disregard the rest of the payload.
除了运行时错误外,HTTP Hooks 和 Postgres Hooks 都会返回超时错误。Postgres Hooks 有 2 秒来完成处理,而 HTTP Hooks 应该在 5 秒内完成。HTTP Hooks 和 Postgres Hooks 都在事务中运行,以限制执行时间,避免延迟认证流程。
可用钩子 #
🌐 Available Hooks
每个 Hook 描述都包含一个示例 JSON Schema,你可以将其与 JSON Schema Faker 一起使用,以生成模拟的 payload。对于 HTTP Hooks,你也可以使用 标准 Webhooks 测试工具 来模拟请求。
🌐 Each Hook description contains an example JSON Schema which you can use in conjunction with JSON Schema Faker in order to generate a mock payload. For HTTP Hooks, you can also use the Standard Webhooks Testing Tool to simulate a request.