多因素认证验证钩子
你可以通过钩子给 Supabase 多因素认证实现 添加额外的检查。例如,你可以:
🌐 You can add additional checks to the Supabase MFA implementation with hooks. For example, you can:
- 限制在一段时间内进行的验证尝试次数。
- 登出那些验证尝试太多次失败的用户。
- 统计、限速或禁止登录。
输入
Supabase Auth 会向你的 hook 发送包含这些字段的负载:
🌐 Supabase Auth will send a payload containing these fields to your hook:
| 字段 | 类型 | 描述 |
|---|---|---|
factor_id | string | 正在验证的多因素认证因素的唯一标识符 |
factor_type | string | totp 或 phone |
user_id | string | 用户的唯一标识符 |
valid | boolean | 验证尝试是否有效。对于 TOTP,这意味着六位数代码正确(true)或错误(false)。 |
1{2 "factor_id": "6eab6a69-7766-48bf-95d8-bd8f606894db",3 "user_id": "3919cb6e-4215-4478-a960-6d3454326cec",4 "valid": true5}输出
如果你的钩子没有错误地处理输入,就返回这个。
🌐 Return this if your hook processed the input without errors.
| 字段 | 类型 | 描述 |
|---|---|---|
decision | string | 关于是否允许认证继续的决定。使用 reject 拒绝验证尝试,并将用户从所有活跃会话中注销。使用 continue 来使用默认的 Supabase Auth 行为。 |
message | string | 如果决定是 reject,显示给用户的消息。 |
1{2 "decision": "reject",3 "message": "You have exceeded maximum number of MFA attempts."4}你们公司要求用户输入错误的多因素验证代码,每次间隔不得少于2秒。
🌐 Your company requires that a user can input an incorrect MFA Verification code no more than once every 2 seconds.
创建一个表格来记录用户最后一次多因素认证错误尝试的时间。
🌐 Create a table to record the last time a user had an incorrect MFA verification attempt for a factor.
1create table public.mfa_failed_verification_attempts (2 user_id uuid not null,3 factor_id uuid not null,4 last_failed_at timestamp not null default now(),5 primary key (user_id, factor_id)6);创建一个钩子来读取和写入这个表的信息。例如:
🌐 Create a hook to read and write information to this table. For example:
1create function public.hook_mfa_verification_attempt(event jsonb)2 returns jsonb3 language plpgsql4as $$5 declare6 last_failed_at timestamp;7 begin8 if event->'valid' is true then9 -- code is valid, accept it10 return jsonb_build_object('decision', 'continue');11 end if;1213 select last_failed_at into last_failed_at14 from public.mfa_failed_verification_attempts15 where16 user_id = event->'user_id'17 and18 factor_id = event->'factor_id';1920 if last_failed_at is not null and now() - last_failed_at < interval '2 seconds' then21 -- last attempt was done too quickly22 return jsonb_build_object(23 'error', jsonb_build_object(24 'http_code', 429,25 'message', 'Please wait a moment before trying again.'26 )27 );28 end if;2930 -- record this failed attempt31 insert into public.mfa_failed_verification_attempts32 (33 user_id,34 factor_id,35 last_failed_at36 )37 values38 (39 event->'user_id',40 event->'factor_id',41 now()42 )43 on conflict do update44 set last_failed_at = now();4546 -- finally let Supabase Auth do the default behavior for a failed attempt47 return jsonb_build_object('decision', 'continue');48 end;49$$;5051-- Assign appropriate permissions and revoke access52grant all53 on table public.mfa_failed_verification_attempts54 to supabase_auth_admin;5556revoke all57 on table public.mfa_failed_verification_attempts58 from authenticated, anon, public;