Loading...
Loading...
Compare original and translation side by side
@netlify/identitynetlify-identity-widgetgotrue-js@netlify/identity@netlify/identitynetlify-identity-widgetgotrue-js@netlify/identitynpm install @netlify/identitynpm install @netlify/identitynetlify devnpx netlify deploynetlify devnpx netlify deployimport { login, getUser } from '@netlify/identity'
const user = await login('user@example.com', '<password>')
console.log(`Hello, ${user.name}`)
// Later, check auth state
const currentUser = await getUser()// netlify/functions/protected.mts
import { getUser } from '@netlify/identity'
import type { Context } from '@netlify/functions'
export default async (req: Request, context: Context) => {
const user = await getUser()
if (!user) return new Response('Unauthorized', { status: 401 })
return Response.json({ id: user.id, email: user.email })
}import { login, getUser } from '@netlify/identity'
const user = await login('user@example.com', '<password>')
console.log(`Hello, ${user.name}`)
// 后续校验登录状态
const currentUser = await getUser()// netlify/functions/protected.mts
import { getUser } from '@netlify/identity'
import type { Context } from '@netlify/functions'
export default async (req: Request, context: Context) => {
const user = await getUser()
if (!user) return new Response('Unauthorized', { status: 401 })
return Response.json({ id: user.id, email: user.email })
}import {
getUser,
handleAuthCallback,
login,
logout,
signup,
oauthLogin,
onAuthChange,
getSettings,
} from '@netlify/identity'import {
getUser,
handleAuthCallback,
login,
logout,
signup,
oauthLogin,
onAuthChange,
getSettings,
} from '@netlify/identity'import { login, AuthError } from '@netlify/identity'
async function handleLogin(email: string, password: string) {
try {
const user = await login(email, password)
showSuccess(`Welcome back, ${user.name ?? user.email}`)
} catch (error) {
if (error instanceof AuthError) {
showError(error.status === 401 ? 'Invalid email or password.' : error.message)
}
}
}import { login, AuthError } from '@netlify/identity'
async function handleLogin(email: string, password: string) {
try {
const user = await login(email, password)
showSuccess(`欢迎回来,${user.name ?? user.email}`)
} catch (error) {
if (error instanceof AuthError) {
showError(error.status === 401 ? '邮箱或密码错误' : error.message)
}
}
}user.emailVerifiedimport { signup, AuthError } from '@netlify/identity'
async function handleSignup(email: string, password: string, name: string) {
try {
const user = await signup(email, password, { full_name: name })
if (user.emailVerified) {
// Autoconfirm ON — user is logged in immediately
showSuccess('Account created. You are now logged in.')
} else {
// Autoconfirm OFF — confirmation email sent
showSuccess('Check your email to confirm your account.')
}
} catch (error) {
if (error instanceof AuthError) {
showError(error.status === 403 ? 'Signups are not allowed.' : error.message)
}
}
}user.emailVerifiedimport { signup, AuthError } from '@netlify/identity'
async function handleSignup(email: string, password: string, name: string) {
try {
const user = await signup(email, password, { full_name: name })
if (user.emailVerified) {
// 自动确认已开启:用户直接登录成功
showSuccess('账号创建成功,你已自动登录')
} else {
// 自动确认已关闭:验证邮件已发送
showSuccess('请查收邮件完成账号验证')
}
} catch (error) {
if (error instanceof AuthError) {
showError(error.status === 403 ? '当前暂不开放注册' : error.message)
}
}
}import { logout } from '@netlify/identity'
await logout()import { logout } from '@netlify/identity'
await logout()oauthLogin(provider)handleAuthCallback()import { oauthLogin } from '@netlify/identity'
// Step 1: Redirect to provider (navigates away — never returns)
function handleOAuthClick(provider: 'google' | 'github' | 'gitlab' | 'bitbucket') {
oauthLogin(provider)
}oauthLogin(provider)handleAuthCallback()import { oauthLogin } from '@netlify/identity'
// 第一步:跳转到第三方授权页(会离开当前站点,无返回值)
function handleOAuthClick(provider: 'google' | 'github' | 'gitlab' | 'bitbucket') {
oauthLogin(provider)
}handleAuthCallback()import { handleAuthCallback, AuthError } from '@netlify/identity'
async function processCallback() {
try {
const result = await handleAuthCallback()
if (!result) return // No callback hash — normal page load
switch (result.type) {
case 'oauth':
showSuccess(`Logged in as ${result.user?.email}`)
break
case 'confirmation':
showSuccess('Email confirmed. You are now logged in.')
break
case 'recovery':
// User is authenticated but must set a new password
showPasswordResetForm(result.user)
break
case 'invite':
// User must set a password to accept the invite
showInviteAcceptForm(result.token)
break
case 'email_change':
showSuccess('Email address updated.')
break
}
} catch (error) {
if (error instanceof AuthError) showError(error.message)
}
}handleAuthCallback()import { handleAuthCallback, AuthError } from '@netlify/identity'
async function processCallback() {
try {
const result = await handleAuthCallback()
if (!result) return // 无回调 hash,为普通页面加载
switch (result.type) {
case 'oauth':
showSuccess(`登录成功,账号为 ${result.user?.email}`)
break
case 'confirmation':
showSuccess('邮箱验证成功,你已自动登录')
break
case 'recovery':
// 用户已通过验证,需要设置新密码
showPasswordResetForm(result.user)
break
case 'invite':
// 用户需要设置密码来接受邀请
showInviteAcceptForm(result.token)
break
case 'email_change':
showSuccess('邮箱地址已更新')
break
}
} catch (error) {
if (error instanceof AuthError) showError(error.message)
}
}import { getUser, onAuthChange, AUTH_EVENTS } from '@netlify/identity'
// Check current user (never throws — returns null if not authenticated)
const user = await getUser()
// Subscribe to auth state changes (returns unsubscribe function)
const unsubscribe = onAuthChange((event, user) => {
switch (event) {
case AUTH_EVENTS.LOGIN:
console.log('Logged in:', user?.email)
break
case AUTH_EVENTS.LOGOUT:
console.log('Logged out')
break
case AUTH_EVENTS.TOKEN_REFRESH:
break
case AUTH_EVENTS.USER_UPDATED:
console.log('Profile updated:', user?.email)
break
case AUTH_EVENTS.RECOVERY:
console.log('Password recovery initiated')
break
}
})import { getUser, onAuthChange, AUTH_EVENTS } from '@netlify/identity'
// 校验当前登录用户(不会抛出异常,未登录时返回 null)
const user = await getUser()
// 订阅认证状态变化(返回取消订阅的函数)
const unsubscribe = onAuthChange((event, user) => {
switch (event) {
case AUTH_EVENTS.LOGIN:
console.log('用户登录:', user?.email)
break
case AUTH_EVENTS.LOGOUT:
console.log('用户登出')
break
case AUTH_EVENTS.TOKEN_REFRESH:
break
case AUTH_EVENTS.USER_UPDATED:
console.log('用户资料更新:', user?.email)
break
case AUTH_EVENTS.RECOVERY:
console.log('已发起密码找回请求')
break
}
})import { getSettings } from '@netlify/identity'
const settings = await getSettings()
// settings.autoconfirm — boolean
// settings.disableSignup — boolean
// settings.providers — Record<AuthProvider, boolean>
if (!settings.disableSignup) showSignupForm()
for (const [provider, enabled] of Object.entries(settings.providers)) {
if (enabled) showOAuthButton(provider)
}import { getSettings } from '@netlify/identity'
const settings = await getSettings()
// settings.autoconfirm — 布尔值,是否开启自动确认
// settings.disableSignup — 布尔值,是否关闭注册
// settings.providers — 记录各个 OAuth 提供商是否开启的对象
if (!settings.disableSignup) showSignupForm()
for (const [provider, enabled] of Object.entries(settings.providers)) {
if (enabled) showOAuthButton(provider)
}import { useEffect, useState } from 'react'
import {
getUser,
handleAuthCallback,
login,
logout,
oauthLogin,
onAuthChange,
} from '@netlify/identity'
function App() {
const [user, setUser] = useState(null)
const [loading, setLoading] = useState(true)
useEffect(() => {
;(async () => {
await handleAuthCallback()
setUser(await getUser())
setLoading(false)
})()
return onAuthChange((_event, currentUser) => setUser(currentUser))
}, [])
const handleLogin = async (email, password) => {
const currentUser = await login(email, password)
setUser(currentUser)
}
const handleGoogleLogin = () => oauthLogin('google')
const handleSignOut = async () => {
await logout()
setUser(null)
}
if (loading) return <p>Loading...</p>
// Render login form or user details based on `user` state
}import { useEffect, useState } from 'react'
import {
getUser,
handleAuthCallback,
login,
logout,
oauthLogin,
onAuthChange,
} from '@netlify/identity'
function App() {
const [user, setUser] = useState(null)
const [loading, setLoading] = useState(true)
useEffect(() => {
;(async () => {
await handleAuthCallback()
setUser(await getUser())
setLoading(false)
})()
return onAuthChange((_event, currentUser) => setUser(currentUser))
}, [])
const handleLogin = async (email, password) => {
const currentUser = await login(email, password)
setUser(currentUser)
}
const handleGoogleLogin = () => oauthLogin('google')
const handleSignOut = async () => {
await logout()
setUser(null)
}
if (loading) return <p>加载中...</p>
// 根据 `user` 状态渲染登录表单或用户信息
}@netlify/identityAuthErrormessagestatuscauseMissingIdentityErrorgetUser()isAuthenticated()nullfalse| Status | Meaning |
|---|---|
| 401 | Invalid credentials or expired token |
| 403 | Action not allowed (e.g., signups disabled) |
| 422 | Validation error (e.g., weak password, malformed email) |
| 404 | User or resource not found |
@netlify/identityAuthErrormessagestatuscauseMissingIdentityErrorgetUser()isAuthenticated()nullfalse| 状态码 | 含义 |
|---|---|
| 401 | 凭证无效或 token 已过期 |
| 403 | 无操作权限(例如注册功能已关闭) |
| 422 | 参数校验失败(例如密码强度不足、邮箱格式错误) |
| 404 | 用户或资源不存在 |
handleridentity-validateidentity-signupidentity-login// netlify/functions/identity-signup.mts
import type { Handler, HandlerEvent, HandlerContext } from '@netlify/functions'
const handler: Handler = async (event: HandlerEvent, context: HandlerContext) => {
const { user } = JSON.parse(event.body || '{}')
return {
statusCode: 200,
body: JSON.stringify({
app_metadata: {
...user.app_metadata,
roles: ['member'],
},
}),
}
}
export { handler }app_metadatauser_metadatahandleridentity-validateidentity-signupidentity-login// netlify/functions/identity-signup.mts
import type { Handler, HandlerEvent, HandlerContext } from '@netlify/functions'
const handler: Handler = async (event: HandlerEvent, context: HandlerContext) => {
const { user } = JSON.parse(event.body || '{}')
return {
statusCode: 200,
body: JSON.stringify({
app_metadata: {
...user.app_metadata,
roles: ['member'],
},
}),
}
}
export { handler }app_metadatauser_metadataapp_metadata.rolesuser_metadataupdateUser({ data: { ... } })app_metadata.rolesuser_metadataupdateUser({ data: { ... } })undefinedundefined
Rules are evaluated top-to-bottom. The `nf_jwt` cookie is read by the CDN to evaluate role conditions.
重定向规则从上到下依次匹配,CDN 会读取 `nf_jwt` cookie 来校验角色条件。