Skip to content
Auth

无密码邮箱登录

Email logins using Magic Links or One-Time Passwords (OTPs)

Supabase Auth 提供了几种无密码登录方式。无密码登录让用户无需密码即可登录,只需点击确认链接或输入验证码。

🌐 Supabase Auth provides several passwordless login methods. Passwordless logins allow users to sign in without a password, by clicking a confirmation link or entering a verification code.

无密码登录可以:

🌐 Passwordless login can:

  • 通过不要求用户创建和记住密码来提升用户体验
  • 通过降低与密码相关的安全漏洞风险来提高安全性
  • 减少处理密码重置和其他与密码相关流程的支持负担

Supabase Auth 提供两种无需密码的登录方式,使用的是用户的电子邮箱:

🌐 Supabase Auth offers two passwordless login methods that use the user's email address:

🌐 With Magic Link

魔法链接是一种无密码登录方式,用户只需点击发送到他们邮箱的链接就能登录账号。魔法链接仅适用于邮箱,而且每个链接只能使用一次。

🌐 Magic Links are a form of passwordless login where users click on a link sent to their email address to log in to their accounts. Magic Links only work with email addresses and are one-time use only.

🌐 Enabling Magic Link

电子邮件认证方法,包括魔法链接,默认是启用的。

🌐 Email authentication methods, including Magic Links, are enabled by default.

配置网站网址和任何额外的重定向网址。这些是用户点击魔法链接后被允许作为重定向目标的网址。你可以在托管项目的网址配置页面上更改网址,在本地开发的config.toml文件中更改,或者在自托管 Supabase.env配置文件中更改。

🌐 Configure the Site URL and any additional redirect URLs. These are the only URLs that are allowed as redirect destinations after the user clicks a Magic Link. You can change the URLs on the URL Configuration page for hosted projects, in the config.toml file for local development, or in the .env configuration file for self-hosted Supabase.

默认情况下,用户每 60 seconds 只能请求一次魔法链接,并且魔法链接会在 1 hour后过期。

🌐 Signing in with Magic Link

从客户端库调用“使用一次性密码登录”的方法。

🌐 Call the "sign in with OTP" method from the client library.

虽然这种方法被标记为“OTP”,但它默认发送的是魔法链接。这两种方法的区别仅在于发送给用户的确认邮件内容。

🌐 Though the method is labelled "OTP", it sends a Magic Link by default. The two methods differ only in the content of the confirmation email sent to the user.

如果用户还没注册,他们会默认被自动注册。要防止这种情况,把 shouldCreateUser 选项设置为 false

🌐 If the user hasn't signed up yet, they are automatically signed up by default. To prevent this, set the shouldCreateUser option to false.

1
import { createClient } from '@supabase/supabase-js'
2
3
const supabase = createClient('https://your-project-id.supabase.co', 'sb_publishable_...')
4
5
// ---cut---
6
async function signInWithEmail() {
7
const { data, error } = await supabase.auth.signInWithOtp({
8
email: 'valid.email@supabase.io',
9
options: {
10
// set this to false if you do not want the user to be automatically signed up
11
shouldCreateUser: false,
12
emailRedirectTo: 'https://example.com/welcome',
13
},
14
})
15
}

隐式流程就到这里了。

🌐 That's it for the implicit flow.

如果你正在使用 PKCE 流程,编辑 Magic Link 邮件模板 来发送一个令牌哈希:

🌐 If you're using PKCE flow, edit the Magic Link email template to send a token hash:

1
<h2>Sign in to your account</h2>
2
3
<p>Use this link to sign in to your account:</p>
4
<p><a href="{{ .SiteURL }}/auth/confirm?token_hash={{ .TokenHash }}&type=email">Sign in</a></p>

/auth/confirm 端点,用哈希换取会话:

🌐 At the /auth/confirm endpoint, exchange the hash for the session:

1
import { createClient } from '@supabase/supabase-js'
2
3
const supabase = createClient('https://your-project-id.supabase.co', 'sb_publishable_...')
4
5
// ---cut---
6
const { error } = await supabase.auth.verifyOtp({
7
token_hash: 'hash',
8
type: 'email',
9
})

带一次性密码 #

🌐 With OTP

电子邮件一次性密码(OTP)是一种无密码登录方式,用户输入发送到他们邮箱的六位数代码来登录账户。

🌐 Email one-time passwords (OTP) are a form of passwordless login where users key in a six digit code sent to their email address to log in to their accounts.

启用邮箱一次性密码 #

🌐 Enabling email OTP

电子邮件认证方法,包括电子邮件一次性密码(OTP),默认已启用。

🌐 Email authentication methods, including Email OTPs, are enabled by default.

电子邮件一次性密码(OTP)的实现与魔法链接相同。要发送 OTP 而不是魔法链接,请修改 魔法链接 电子邮件模板。有关更多信息,请参阅电子邮件模板指南

🌐 Email OTPs share an implementation with Magic Links. To send an OTP instead of a Magic Link, alter the Magic Link email template. Refer to the Email Templates guide for more information.

修改模板以包含 {{ .Token }} 变量,例如:

🌐 Modify the template to include the {{ .Token }} variable, for example:

1
<h2>One time login code</h2>
2
3
<p>Please enter this code: {{ .Token }}</p>

默认情况下,用户每 60 seconds只能请求一次一次性密码(OTP),并且它们会在 1 hour后过期。你可以通过 Authentication > Sign In / Providers > Auth Providers > Email > Email OTP expiration 来配置。强烈不建议将过期时间设置超过 86,400 秒(一天),并且只能通过 Management API 设置。上线前一定要先阅读 安全建议

使用邮箱一次性密码登录 #

🌐 Signing in with email OTP

第一步:发给用户一个一次性密码(OTP) #

🌐 Step 1: Send the user an OTP code

获取用户的邮箱,然后用你的客户端库调用“用一次性密码登录”的方法。

🌐 Get the user's email and call the "sign in with OTP" method from your client library.

如果用户还没注册,他们会默认被自动注册。要防止这种情况,把 shouldCreateUser 选项设置为 false

🌐 If the user hasn't signed up yet, they are automatically signed up by default. To prevent this, set the shouldCreateUser option to false.

1
import { createClient } from '@supabase/supabase-js'
2
3
const supabase = createClient('https://your-project-id.supabase.co', 'sb_publishable_...')
4
5
// ---cut---
6
const { data, error } = await supabase.auth.signInWithOtp({
7
email: 'valid.email@supabase.io',
8
options: {
9
// set this to false if you do not want the user to be automatically signed up
10
shouldCreateUser: false,
11
},
12
})

如果请求成功,你会收到一个包含 error: nulldata 对象的响应,其中 usersession 都是 null。告诉用户检查他们的邮箱收件箱。

🌐 If the request is successful, you receive a response with error: null and a data object where both user and session are null. Let the user know to check their email inbox.

1
{
2
"data": {
3
"user": null,
4
"session": null
5
},
6
"error": null
7
}

步骤 2:验证 OTP 以创建会话 #

🌐 Step 2: Verify the OTP to create a session

提供一个输入框,让用户输入一次性验证码。

🌐 Provide an input field for the user to enter their one-time code.

使用你的客户端库调用“verify OTP”方法,传入用户的电子邮件地址、验证码以及 email 类型:

🌐 Call the "verify OTP" method from your client library with the user's email address, the code, and a type of email:

1
import { createClient } from '@supabase/supabase-js'
2
3
const supabase = createClient('https://your-project-id.supabase.co', 'sb_publishable_...')
4
5
// ---cut---
6
const {
7
data: { session },
8
error,
9
} = await supabase.auth.verifyOtp({
10
email: 'email@example.com',
11
token: '123456',
12
type: 'email',
13
})

如果成功,用户现在已登录,你会收到一个看起来像这样的有效会话:

🌐 If successful, the user is now logged in, and you receive a valid session that looks like:

1
{
2
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJhdXRoZW50aWNhdGVkIiwiZXhwIjoxNjI3MjkxNTc3LCJzdWIiOiJmYTA2NTQ1Zi1kYmI1LTQxY2EtYjk1NC1kOGUyOTg4YzcxOTEiLCJlbWFpbCI6IiIsInBob25lIjoiNjU4NzUyMjAyOSIsImFwcF9tZXRhZGF0YSI6eyJwcm92aWRlciI6InBob25lIn0sInVzZXJfbWV0YWRhdGEiOnt9LCJyb2xlIjoiYXV0aGVudGljYXRlZCJ9.1BqRi0NbS_yr1f6hnr4q3s1ylMR3c1vkiJ4e_N55dhM",
3
"token_type": "bearer",
4
"expires_in": 3600,
5
"refresh_token": "LSp8LglPPvf0DxGMSj-vaQ",
6
"user": {...}
7
}