概述
Auth Api 提供了一套完整的认证相关功能,支持多种登录方式、用户管理和会话管理。Auth Api 按照功能用途分为 7 个类别。每个类别包含相关的 API 方法,方便开发者根据具体需求快速找到合适的接口。
- 认证登录:用户注册和登录相关的 API 方法,支持多种登录方式。
- 会话管理:管理用户会话状态和令牌的 API 方法。
- 用户管理:获取、更新和管理用户信息的 API 方法。
- 身份源管理:管理第三方身份源绑定和解绑的 API 方法。
- 密码管理:密码重置和修改相关的 API 方法。
- 验证管理:验证码发送、验证和重发相关的 API 方法。
- 其他工具:其他辅助功能的 API 方法。
基础使用示例
Publishable Key 可前往 云开发平台/API Key 配置 中生成
auth.detectSessionInUrl 为初始化可选参数,设置后可以自动检测 URL 中的 OAuth 参数(code、state),适用于signInWithOAuth、linkIdentity等使用场景
import cloudbase from "@cloudbase/js-sdk";
// 初始化
const app = cloudbase.init({
env: "your-env-id", // 替换为您的环境ID
region: "ap-shanghai", // 地域,默认为上海
accessKey: "", // 填入生成的 Publishable Key,
auth: {
detectSessionInUrl: true, // 可选:自动检测 URL 中的 OAuth 参数,适用于signInWithOAuth、linkIdentity
},
});
const auth = app.auth;
// 检查登录状态
async function checkAuthStatus() {
const { data, error } = await auth.getSession();
if (error) {
console.error("检查登录状态失败:", error.message);
return false;
}
if (data.session) {
console.log("用户已登录:", data.session.user);
return true;
} else {
console.log("用户未登录");
return false;
}
}
// 用户注册示例(四步验证流程)
async function registerUser(email, password, verificationCode) {
// 第一步:发送验证码
const { data, error } = await auth.signUp({
email: email,
password: password,
});
if (error) {
console.error("发送验证码失败:", error.message);
return false;
} else {
console.log("验证码已发送,等待验证...");
// 第二步:验证验证码并完成注册
const { data: loginData, error: loginError } = await data.verifyOtp({
token: verificationCode,
});
if (loginError) {
console.error("验证失败:", loginError.message);
return false;
} else {
console.log("注册成功:", loginData.user?.email);
return true;
}
}
}
// 用户登出示例
async function logoutUser() {
const { data, error } = await auth.signOut();
if (error) {
console.error("登出失败:", error.message);
return false;
} else {
console.log("登出成功,会话已清除");
return true;
}
}
// 密码登录示例
async function loginWithPassword(email, password) {
const { data, error } = await auth.signInWithPassword({
email: email,
password: password,
});
if (error) {
console.error("登录失败:", error.message);
return false;
} else {
console.log("登录成功:", data.user?.email);
return true;
}
}
// 监听认证状态变化
auth.onAuthStateChange((event, session, info) => {
console.log("认证状态变化:", event);
switch (event) {
case "INITIAL_SESSION":
console.log("初始会话已建立");
if (session) {
console.log("用户已登录:", session.user);
} else {
console.log("用户未登录");
}
break;
case "SIGNED_IN":
console.log("用户登录成功:", session.user);
break;
case "SIGNED_OUT":
console.log("用户已登出");
break;
case "PASSWORD_RECOVERY":
console.log("密码已重置");
break;
case "TOKEN_REFRESHED":
console.log("令牌已刷新");
break;
case "USER_UPDATED":
console.log("用户信息已更新");
break;
case "BIND_IDENTITY":
console.log("身份源绑定结果");
break;
}
});
// 完整的手机验证码登录页面实现
class PhoneLoginPage {
constructor() {
this.setupEventListeners();
}
// 设置事件监听
setupEventListeners() {
document.getElementById("sendCodeBtn").addEventListener("click", (e) => {
e.preventDefault();
this.sendVerificationCode();
});
document.getElementById("verifyCodeBtn").addEventListener("click", (e) => {
e.preventDefault();
this.verifyCodeAndLogin();
});
}
// 发送验证码
async sendVerificationCode() {
const phone = document.getElementById("phone").value;
if (!phone) {
alert("请输入手机号码");
return;
}
// 验证手机号格式
if (!this.validatePhone(phone)) {
alert("请输入正确的手机号码格式");
return;
}
// 显示加载状态
this.showLoading(true);
this.hideError();
try {
const { data, error } = await auth.signInWithOtp({
phone: phone,
});
if (error) {
this.handleSendCodeError(error);
} else {
this.handleSendCodeSuccess(data);
}
} catch (error) {
this.handleNetworkError(error);
} finally {
this.showLoading(false);
}
}
// 验证验证码并登录
async verifyCodeAndLogin() {
const code = document.getElementById("code").value;
if (!code) {
alert("请输入验证码");
return;
}
if (!this.verifyFunction) {
alert("请先发送验证码");
return;
}
this.showLoading(true);
this.hideError();
try {
const { data, error } = await this.verifyFunction({ token: code });
if (error) {
this.handleVerifyError(error);
} else {
this.handleLoginSuccess(data);
}
} catch (error) {
this.handleNetworkError(error);
} finally {
this.showLoading(false);
}
}
// 手机号格式验证
validatePhone(phone) {
const phoneRegex = /^1[3-9]\d{9}$/;
return phoneRegex.test(phone);
}
// 处理发送验证码成功
handleSendCodeSuccess(data) {
this.verifyFunction = data.verifyOtp;
// 显示验证码输入区域
document.getElementById("verificationSection").style.display = "block";
document.getElementById("phoneSection").style.display = "none";
// 开始倒计时
this.startCountdown(60);
document.getElementById("success").innerText =
"验证码已发送到您的手机,请注意查收";
document.getElementById("success").style.display = "block";
}
// 处理发送验证码错误
handleSendCodeError(error) {
switch (error.code) {
case "invalid_phone":
document.getElementById("error").innerText =
"手机号格式错误,请检查后重试";
break;
case "user_not_found":
document.getElementById("error").innerText =
"该手机号未注册,请先注册或使用其他手机号";
break;
case "resource_exhausted":
document.getElementById("error").innerText = "发送频率过高,请稍后再试";
break;
case "unreachable":
document.getElementById("error").innerText =
"网络连接失败,请检查网络设置";
break;
default:
document.getElementById("error").innerText =
"发送验证码失败: " + error.message;
}
document.getElementById("error").style.display = "block";
}
// 处理验证错误
handleVerifyError(error) {
switch (error.code) {
case "invalid_code":
document.getElementById("error").innerText = "验证码错误,请重新输入";
break;
case "code_expired":
document.getElementById("error").innerText = "验证码已过期,请重新获取";
// 显示重新发送按钮
document.getElementById("resendBtn").style.display = "block";
break;
case "max_attempts_exceeded":
document.getElementById("error").innerText = "验证次数过多,请稍后重试";
break;
default:
document.getElementById("error").innerText =
"验证失败: " + error.message;
}
document.getElementById("error").style.display = "block";
}
// 处理登录成功
handleLoginSuccess(data) {
document.getElementById("success").innerText = "登录成功!欢迎回来";
document.getElementById("success").style.display = "block";
console.log("用户信息:", data.user);
console.log("会话信息:", data.session);
// 延迟跳转到首页
setTimeout(() => {
window.location.href = "/dashboard";
}, 2000);
}
// 处理网络错误
handleNetworkError(error) {
document.getElementById("error").innerText =
"网络错误,请检查网络连接后重试";
document.getElementById("error").style.display = "block";
console.error("网络错误:", error);
}
// 显示/隐藏加载状态
showLoading(show) {
document.getElementById("loading").style.display = show ? "block" : "none";
document.getElementById("sendCodeBtn").disabled = show;
document.getElementById("verifyCodeBtn").disabled = show;
}
// 隐藏错误信息
hideError() {
document.getElementById("error").style.display = "none";
}
// 开始倒计时
startCountdown(seconds) {
let countdown = seconds;
const btn = document.getElementById("resendBtn");
const originalText = btn.innerText;
btn.disabled = true;
const timer = setInterval(() => {
countdown--;
btn.innerText = `${countdown}秒后可重发`;
if (countdown <= 0) {
clearInterval(timer);
btn.disabled = false;
btn.innerText = originalText;
}
}, 1000);
}
}
// 页面加载完成后初始化
window.addEventListener("DOMContentLoaded", () => {
new PhoneLoginPage();
});
认证登录
signUp
async signUp(params: SignUpReq): Promise<SignUpRes>
注册新用户账户,采用智能注册并登录流程。
手机号验证码注册 仅支持 上海 地域
- 创建一个新的用户账户
- 采用智能注册并登录流程:发送验证码 → 等待用户输入 → 智能判断用户存在性 → 自动登录或注册并登录
- 如果用户已存在则直接登录,如果用户不存在则注册新用户并自动登录
参数
返回
示例
// 第一步:发送邮箱验证码并存储 verificationInfo
const { data, error } = await auth.signUp({
email: "newuser@example.com",
password: "securePassword123",
username: "newuser",
});
if (error) {
console.error("发送验证码失败:", error.message);
} else {
console.log("验证码已发送到邮箱,等待用户输入...");
// 第二步:等待用户输入验证码(通过 Promise 包装用户输入事件)
const verificationCode = "123456"; // 用户输入的验证码
// 第三步:智能验证流程(自动判断用户存在性)
const { data: loginData, error: loginError } = await data.verifyOtp({
token: verificationCode,
});
if (loginError) {
console.error("验证失败:", loginError.message);
} else {
// 第四步:自动完成注册或登录
console.log("操作成功,用户信息:", loginData.user);
console.log("会话信息:", loginData.session);
console.log(
"系统已自动判断:",
loginData.user?.email ? "新用户注册并登录" : "现有用户直接登录"
);
}
}
// 第一步:发送手机验证码
const { data, error } = await auth.signUp({
phone: "13800138000",
password: "mypassword",
});
if (error) {
console.error("发送验证码失败:", error.message);
} else {
console.log("验证码已发送到手机,等待用户输入...");
// 第二步:等待用户输入验证码
const verificationCode = "123456"; // 用户输入的验证码
// 第三步:智能验证流程(自动判断用户存在性)
const { data: loginData, error: loginError } = await data.verifyOtp({
token: verificationCode,
});
if (loginError) {
console.error("操作失败:", loginError.message);
} else {
// 系统自动判断:如果用户已存在则直接登录,如果不存在则注册新用户
if (loginData.user?.phone) {
console.log("现有用户直接登录成功,用户信息:", loginData.user);
} else {
console.log("新用户注册并登录成功,用户ID:", loginData.user?.id);
}
console.log("会话状态:", loginData.session ? "已登录" : "未登录");
}
}
let signUpVerify = null;
async function startRegistration(email, password) {
const { data, error } = await auth.signUp({
email: email,
password: password,
});
if (error) {
console.error("发送验证码失败:", error.message);
document.getElementById("error").innerText =
"发送验证码失败: " + error.message;
return false;
} else {
console.log("验证码已发送");
signUpVerify = data.verifyOtp;
// 显示验证码输入框
document.getElementById("verificationSection").style.display = "block";
document.getElementById("registrationSection").style.display = "none";
// 更新提示信息,说明智能判断逻辑
document.getElementById("verificationHint").innerText =
"请输入验证码,系统将自动判断您是注册新用户还是登录现有账户";
return true;
}
}
async function completeRegistration(verificationCode) {
if (!signUpVerify) {
console.error("注册流程未开始");
return false;
}
const { data, error } = await signUpVerify({ token: verificationCode });
if (error) {
console.error("验证失败:", error.message);
document.getElementById("error").innerText = "验证失败: " + error.message;
return false;
} else {
// 智能判断结果反馈
if (data.user?.email) {
console.log("智能注册并登录成功");
document.getElementById("success").innerText = data.user?.created_at
? "新用户注册成功,欢迎加入!"
: "登录成功,欢迎回来!";
}
// 自动跳转到首页
setTimeout(() => {
window.location.href = "/dashboard";
}, 2000);
return true;
}
}
// 注册表单提交
document
.getElementById("registerForm")
.addEventListener("submit", async (e) => {
e.preventDefault();
const email = document.getElementById("email").value;
const password = document.getElementById("password").value;
const nickname = document.getElementById("nickname").value;
await startRegistration(email, password, nickname);
});
// 验证码表单提交
document
.getElementById("verificationForm")
.addEventListener("submit", async (e) => {
e.preventDefault();
const code = document.getElementById("verificationCode").value;
await completeRegistration(code);
});
try {
const { data, error } = await auth.signUp({
email: "existing@example.com",
password: "password123",
});
if (error) {
switch (error.code) {
case "email_already_exists":
console.error("邮箱已被注册,请使用其他邮箱或直接登录");
document.getElementById("error").innerText = "该邮箱已被注册";
break;
case "phone_already_exists":
console.error("手机号已被注册,请使用其他手机号");
document.getElementById("error").innerText = "该手机号已被注册";
break;
case "password_too_weak":
console.error("密码强度不足,请使用更复杂的密码");
document.getElementById("error").innerText = "密码强度不足";
break;
case "invalid_email":
console.error("邮箱格式错误,请检查邮箱格式");
document.getElementById("error").innerText = "邮箱格式错误";
break;
case "invalid_phone":
console.error("手机号格式错误,请检查手机号格式");
document.getElementById("error").innerText = "手机号格式错误";
break;
case "username_already_exists":
console.error("用户名已被使用,请选择其他用户名");
document.getElementById("error").innerText = "用户名已被使用";
break;
case "resource_exhausted":
console.error("注册频率过高,请稍后重试");
document.getElementById("error").innerText = "注册频率过高,请稍后重试";
break;
case "unreachable":
console.error("网络连接失败,请检查网络设置后重试");
document.getElementById("error").innerText = "网络连接失败";
break;
default:
console.error("注册失败:", error.message);
document.getElementById("error").innerText =
"注册失败: " + error.message;
}
} else {
console.log("验证码发送成功");
}
} catch (error) {
console.error("网络错误:", error);
document.getElementById("error").innerText = "网络错误,请重试";
}
async function verifyRegistrationCode(code) {
try {
const { data, error } = await signUpCallback(code);
if (error) {
switch (error.code) {
case "invalid_code":
console.error("验证码不正确,请重新输入");
document.getElementById("error").innerText = "验证码不正确";
break;
case "code_expired":
console.error("验证码已过期,请重新获取");
document.getElementById("error").innerText = "验证码已过期";
// 显示重新发送按钮
document.getElementById("resendBtn").style.display = "block";
break;
case "max_attempts_exceeded":
console.error("验证次数过多,请稍后重试");
document.getElementById("error").innerText = "验证次数过多";
break;
case "verification_not_found":
console.error("验证信息不存在,请重新开始注册流程");
document.getElementById("error").innerText = "验证信息不存在";
break;
case "unreachable":
console.error("网络连接失败,请检查网络设置后重试");
document.getElementById("error").innerText = "网络连接失败";
break;
default:
console.error("验证失败:", error.message);
document.getElementById("error").innerText =
"验证失败: " + error.message;
}
return false;
} else {
console.log("注册成功");
return true;
}
} catch (error) {
console.error("网络错误:", error);
document.getElementById("error").innerText = "网络错误,请重试";
return false;
}
}
signInAnonymously
async signInAnonymously(params?: SignInAnonymouslyReq): Promise<SignInRes>
匿名登录,创建一个临时匿名用户账户。
- 创建一个临时匿名用户账户
- 无需提供任何身份验证信息
- 适合需要临时访问权限的场景
- 使用前,请确认已在云开发平台/身份认证/注册配置中开启允许匿名登录(默认开启)
参数
返回
示例
// 创建匿名用户
const { data, error } = await auth.signInAnonymously();
if (error) {
console.error("匿名登录失败:", error.message);
console.error("错误代码:", error.code);
} else {
console.log("匿名登录成功");
console.log("匿名用户ID:", data.user?.id);
console.log("会话信息:", data.session);
console.log("是否为匿名用户:", data.user?.is_anonymous);
}
async function safeAnonymousLogin() {
try {
const { data, error } = await auth.signInAnonymously();
if (error) {
switch (error.code) {
case "rate_limit_exceeded":
console.error("请求频率过高,请稍后重试");
break;
case "invalid_provider_token":
console.error("第三方平台令牌无效,请检查令牌格式");
break;
case "provider_not_supported":
console.error("不支持的第三方平台,请检查平台标识");
break;
case "unreachable":
console.error("网络连接失败,请检查网络设置后重试");
break;
case "permission_denied":
console.error("权限不足,请检查安全域名配置");
break;
default:
console.error("匿名登录失败:", error.message);
}
return null;
} else {
console.log("匿名登录成功");
return data;
}
} catch (error) {
console.error("网络错误:", error);
return null;
}
}
// 使用安全登录函数
const result = await safeAnonymousLogin();
if (result) {
console.log("登录成功,用户信息:", result.user);
}
// 第一步:匿名登录
const { data: anonymousData, error: anonymousError } =
await auth.signInAnonymously();
if (anonymousError) {
console.error("匿名登录失败:", anonymousError.message);
} else {
console.log("匿名登录成功,准备升级为正式用户");
// 第二步:绑定邮箱或手机号(示例:绑定邮箱)
const { data: upgradeData, error: upgradeError } = await auth.signUp({
email: "user@example.com",
password: "securePassword123",
anonymous_token: anonymousData.session?.access_token,
});
if (upgradeError) {
console.error("升级失败:", upgradeError.message);
} else {
console.log("升级成功,请输入验证码完成身份验证");
// 第三步:验证验证码
const verificationCode = "123456";
const { data: finalData, error: finalError } = await upgradeData.verifyOtp({
token: verificationCode,
});
if (finalError) {
console.error("验证失败:", finalError.message);
} else {
console.log("匿名用户成功升级为正式用户");
console.log("新用户信息:", finalData.user);
console.log("是否为匿名用户:", finalData.user?.is_anonymous);
}
}
}
signInWithPassword
async signInWithPassword(params: SignInWithPasswordReq): Promise<SignInRes>
使用用户名、邮箱或手机号和密码登录。
- 支持用户名、邮箱、手机号配合密码三种登录方式(三选一)
- 使用前,请确认已在云开发平台/身份认证/常规登录中开启用户名密码登录(默认开启)
参数
返回
示例
const { data, error } = await auth.signInWithPassword({
username: "testuser",
password: "password123",
});
if (error) {
console.error("登录失败:", error.message);
} else {
console.log("登录成功,用户信息:", data.user);
console.log("会话信息:", data.session);
}
const { data, error } = await auth.signInWithPassword({
email: "user@example.com",
password: "mypassword",
});
if (error) {
console.error("登录失败:", error.message);
} else {
console.log("登录成功,用户ID:", data.user?.id);
}
const { data, error } = await auth.signInWithPassword({
phone: "13800138000",
password: "securepassword",
});
if (error) {
console.error("登录失败:", error.code, error.message);
} else {
console.log("登录成功,用户ID:", data.user?.id);
}
try {
const { data, error } = await auth.signInWithPassword({
username: "wronguser",
password: "wrongpassword",
});
if (error) {
// 根据常见错误代码进行完整错误处理
switch (error.code) {
case "not_found":
console.error("用户不存在,请检查用户名/邮箱/手机号是否正确");
break;
case "password_not_set":
console.error("当前用户未设置密码,请使用验证码登录或第三方登录方式");
break;
case "invalid_password":
console.error("密码不正确,请重新输入");
break;
case "user_pending":
console.error("该用户未激活,请联系管理员激活账户");
break;
case "user_blocked":
console.error("该用户被停用,请联系管理员");
break;
case "invalid_status":
console.error("您已经超过了密码最大重试次数,请稍后重试");
break;
case "invalid_two_factor":
console.error("二次验证码不匹配或已过时,请重新获取");
break;
case "unreachable":
console.error("网络连接失败,请检查网络设置后重试");
break;
default:
console.error("登录失败:", error.message);
}
} else {
console.log("登录成功");
}
} catch (error) {
console.error("网络错误:", error);
}
signInWithOtp
async signInWithOtp(params: SignInWithOtpReq): Promise<SignInWithOtpRes>
使用一次性密码(OTP)进行登录验证,支持邮箱和手机号验证。
短信验证码 仅支持 上海 地域
- 通过邮箱或手机号发送一次性验证码进行登录验证
- 支持完整的验证流程:发送验证码 → 等待用户输入 → 验证并登录
- 适用于无密码登录场景,提供更高的安全性
- 使用前,请确认已在云开发平台/身份认证/登录方式/常规登录中开启邮箱/短信验证码登录
参数
返回
示例
const { data, error } = await auth.signInWithOtp({
phone: "13800138000",
});
if (error) {
console.error("发送验证码失败:", error.message);
} else {
console.log("验证码已发送,等待用户输入...");
// 用户输入验证码后验证
const { data: loginData, error: loginError } = await data.verifyOtp({
token: "123456",
});
if (loginError) {
console.error("验证失败:", loginError.message);
} else {
console.log("登录成功:", loginData.user);
console.log("会话信息:", loginData.session);
}
}
// 发送邮箱验证码
const { data, error } = await auth.signInWithOtp({
email: "user@example.com",
});
if (error) {
console.error("发送验证码失败:", error.message);
} else {
console.log("邮箱验证码已发送,请查收邮件...");
// 用户从邮箱获取验证码后验证
const { data: loginData, error: loginError } = await data.verifyOtp({
token: "654321",
});
if (loginError) {
console.error("验证失败:", loginError.message);
} else {
console.log("邮箱登录成功:", loginData.user?.email);
}
}
try {
const { data, error } = await auth.signInWithOtp({
phone: "13800138000",
});
if (error) {
switch (error.code) {
case "resource_exhausted":
console.error("发送频率过高,请稍后再试");
break;
case "invalid_argument":
console.error("手机号或邮箱格式错误,请检查后重试");
break;
case "failed_precondition":
console.error("从第三方获取用户信息失败,请重试");
break;
case "aborted":
console.error("尝试次数过多,请返回首页,稍后重试");
break;
case "permission_denied":
console.error("您当前的会话已过期,请返回重试");
break;
case "captcha_required":
console.error("需要输入验证码,请根据反机器人服务接入");
break;
case "captcha_invalid":
console.error("验证码不正确,请根据反机器人服务接入");
break;
case "unreachable":
console.error("网络连接失败,请检查网络设置后重试");
break;
default:
console.error("发送验证码失败:", error.message);
}
return;
}
// 验证验证码
const { data: loginData, error: loginError } = await data.verifyOtp({
token: "123456",
});
if (loginError) {
console.error("验证失败:", loginError.message);
} else {
console.log("登录成功");
}
} catch (error) {
console.error("网络错误:", error);
}
signInWithOAuth
async signInWithOAuth(params: SignInWithOAuthReq): Promise<SignInOAuthRes>
生成第三方平台授权链接,支持微信、Google 等主流平台。
- 生成第三方平台(如微信、Google 等)的授权页面 URL
- 将状态信息保存到浏览器会话中,以便后续验证
- 支持自定义回调地址和状态参数
- 使用前,请确认已在云开发平台/身份认证/登录方式中开启对应的 OAuth 身份源
注意事项
- 调用此方法后,状态信息会自动保存到浏览器会话中,在 cloudbase.init 时设置
auth.detectSessionInUrl为true时,从第三方回调回来后会自动调用 verifyOAuth 进行验证,否则后续需要手动通过 verifyOAuth 方法进行验证 - 如果未提供 state 参数,系统会自动生成格式为
prd-{provider}-{随机字符串}的状态参数 - 回调地址需要配置在云开发平台的安全域名中,否则会返回权限错误
参数
返回
示例
// 初始化
const app = cloudbase.init({
env: "your-env-id", // 替换为您的环境ID
region: "ap-shanghai", // 地域,默认为上海
accessKey: "", // 填入生成的 Publishable Key,
auth: {
detectSessionInUrl: true, // 可选:自动检测 URL 中的 OAuth 参数
},
});
const { data, error } = await auth.signInWithOAuth({
provider: "wechat",
options: {
redirectTo: "https://example.com/callback",
state: "wx_auth_123456",
},
});
if (error) {
console.error("获取微信授权链接失败:", error.message);
} else {
console.log("微信授权链接:", data.url);
console.log("第三方平台:", data.provider);
// 跳转到微信授权页面
window.location.href = data.url;
}
const app = cloudbase.init({
env: "your-env-id", // 替换为您的环境ID
region: "ap-shanghai", // 地域,默认为上海
accessKey: "", // 填入生成的 Publishable Key,
auth: {
detectSessionInUrl: true, // 可选:自动检测 URL 中的 OAuth 参数
},
});
const auth = app.auth;
const { data, error } = await auth.signInWithOAuth({
provider: "google",
});
if (error) {
console.error("获取Google授权链接失败:", error.message);
} else {
console.log("Google授权链接已生成,准备跳转...");
console.log("授权URL:", data.url);
// 在新窗口打开授权页面
window.open(data.url, "_blank");
}
// OAuth登录最佳实践 - 完整的UI交互流程
// 初始化
const app = cloudbase.init({
env: "your-env-id", // 替换为您的环境ID
region: "ap-shanghai", // 地域,默认为上海
accessKey: "", // 填入生成的 Publishable Key,
auth: {
detectSessionInUrl: true, // 可选:自动检测 URL 中的 OAuth 参数,适用于signInWithOAuth、linkIdentity
},
});
// 修改认证状态变化监听器,添加浮窗显示
async function setupAuthStateChangeListener() {
try {
if (!app.auth) return;
// 订阅认证状态变化事件
const { data } = await app.auth.onAuthStateChange(
(event, session, info) => {
console.log("认证状态变化:", { event, session, info });
switch (event) {
case "SIGNED_IN":
if (session && session.user) {
console.log("登录成功!");
}
break;
default:
console.log("未知认证事件:", event);
}
}
);
console.log("认证状态变化监听器已设置");
} catch (error) {
console.error("设置认证状态变化监听器失败:", error);
}
}
class OAuthManager {
constructor() {
this.initEventListeners();
this.provider = "oauth";
}
// 初始化事件监听器
initEventListeners() {
// OAuth登录按钮点击事件
document.getElementById("oauth-login-btn").addEventListener("click", () => {
this.startOAuth();
});
}
// 开始OAuth授权流程
async startOAuth() {
try {
this.showLoading(true);
this.hideError();
const { data, error } = await auth.signInWithOAuth({
provider: this.provider,
});
if (error) {
this.handleOAuthError(error);
} else {
console.log("OAuth授权链接生成成功,正在跳转...");
// 最佳实践:使用当前窗口跳转,保持用户体验
window.location.href = data.url;
}
} catch (error) {
this.handleOAuthError(error);
} finally {
this.showLoading(false);
}
}
showLoading(show) {
document.getElementById("loading").style.display = show ? "block" : "none";
}
}
setupAuthStateChangeListener();
// 初始化OAuth登录管理器
const oAuthManager = new OAuthManager();
// 初始化
const app = cloudbase.init({
env: "your-env-id", // 替换为您的环境ID
region: "ap-shanghai", // 地域,默认为上海
accessKey: "", // 填入生成的 Publishable Key,
});
class OAuthManager {
constructor() {
this.initEventListeners();
this.provider = "oauth";
}
// 初始化事件监听器
initEventListeners() {
// OAuth登录按钮点击事件
document.getElementById("oauth-login-btn").addEventListener("click", () => {
this.startOAuth();
});
// 页面加载时检查是否有OAuth授权回调
document.addEventListener("DOMContentLoaded", () => {
this.checkOAuthCallback();
});
}
// 开始OAuth授权流程
async startOAuth() {
try {
this.showLoading(true);
this.hideError();
const { data, error } = await auth.signInWithOAuth({
provider: this.provider,
});
if (error) {
this.handleOAuthError(error);
} else {
console.log("OAuth授权链接生成成功,正在跳转...");
// 最佳实践:使用当前窗口跳转,保持用户体验
window.location.href = data.url;
}
} catch (error) {
this.handleOAuthError(error);
} finally {
this.showLoading(false);
}
}
// 检查OAuth授权回调
async checkOAuthCallback() {
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get("code");
const state = urlParams.get("state");
if (code && state) {
console.log("检测到OAuth授权回调,正在验证...");
await this.verifyOAuth(code, state);
}
}
// 验证OAuth授权
async verifyOAuth(code, state) {
try {
this.showLoading(true);
const result = await auth.verifyOAuth({
code: code,
state: state,
provider: this.provider,
});
if (result.error) {
this.handleOAuthError(result.error);
} else {
console.log("OAuth登录成功!");
this.showSuccess("OAuth登录成功!");
}
} catch (error) {
this.handleOAuthError(error);
} finally {
this.showLoading(false);
}
}
// 错误处理
handleOAuthError(error) {
console.error("OAuth登录错误:", error);
switch (error.code) {
case "provider_not_supported":
this.showError("不支持的第三方平台,请检查平台标识是否正确");
break;
case "invalid_redirect_uri":
this.showError("回调地址格式错误,请检查URL格式");
break;
case "failed_precondition":
this.showError("从OAuth获取用户信息失败,请检查平台配置");
break;
case "permission_denied":
this.showError("权限不足,请检查安全域名配置");
break;
case "resource_exhausted":
this.showError("请求频率过高,请稍后重试");
break;
case "unreachable":
this.showError("网络连接失败,请检查网络设置后重试");
break;
case "invalid_code":
this.showError("授权码无效或已过期,请重新授权");
break;
case "state_mismatch":
this.showError("状态参数不匹配,可能存在安全风险,请重新授权");
break;
default:
this.showError("OAuth登录失败:" + (error.message || "未知错误"));
}
}
showLoading(show) {
document.getElementById("loading").style.display = show ? "block" : "none";
}
showError(message) {
const errorElement = document.getElementById("error-message");
errorElement.textContent = message;
errorElement.style.display = "block";
}
hideError() {
document.getElementById("error-message").style.display = "none";
}
showSuccess(message) {
const successElement = document.getElementById("success-message");
successElement.textContent = message;
successElement.style.display = "block";
}
}
signInWithIdToken
async signInWithIdToken(params: SignInWithIdTokenReq): Promise<SignInRes>
使用第三方平台的身份令牌登录,支持微信、Google 等主流平台。
- 使用第三方平台(如微信、Google 等)的身份令牌进行登录
- 支持指定第三方平台标识,第三方平台需在云开发平台/身份认证/登录方式中先进行配置配置
- 令牌为必填参数
参数
返回
示例
const { data, error } = await auth.signInWithIdToken({
provider: "wechat",
token: "wx_token_1234567890",
});
if (error) {
console.error("微信登录失败:", error.message);
} else {
console.log("微信登录成功,用户信息:", data.user);
console.log("会话信息:", data.session);
}
const { data, error } = await auth.signInWithIdToken({
provider: "google",
token: "google_token_abcdefg",
});
if (error) {
console.error("Google登录失败:", error.message);
} else {
console.log("Google登录成功,用户昵称:", data.user?.user_metadata?.nickName);
}
const { data, error } = await auth.signInWithIdToken({
token: "generic_token_xyz",
});
if (error) {
console.error("令牌登录失败:", error.message);
} else {
console.log("令牌登录成功,用户ID:", data.user?.id);
}
try {
const { data, error } = await auth.signInWithIdToken({
provider: "wechat",
token: "invalid_token",
});
if (error) {
switch (error.code) {
case "invalid_token":
console.error("令牌无效或已过期,请重新获取");
break;
case "provider_not_supported":
console.error("不支持的第三方平台,请使用其他登录方式");
break;
case "failed_precondition":
console.error("从第三方获取用户信息失败,请重试");
break;
case "resource_exhausted":
console.error("尝试过于频繁,请稍后重试");
break;
case "permission_denied":
console.error("权限不足,请检查令牌权限范围");
break;
case "unreachable":
console.error("网络连接失败,请检查网络设置后重试");
break;
default:
console.error("登录失败:", error.message);
}
} else {
console.log("登录成功");
}
} catch (error) {
console.error("网络错误:", error);
}
signInWithCustomTicket
async signInWithCustomTicket(getTickFn: GetCustomSignTicketFn): Promise<SignInRes>
使用自定义登录票据进行登录,支持完全自定义的登录流程。
- 使用自定义的登录票据进行身份验证
- 支持传入获取自定义登录票据的函数
- 适用于需要完全自定义登录流程的场景
- 签发 Ticket 详细流程可参考自定义登录
参数
获取自定义登录票据的函数,返回 Promise<string>
返回
示例
// 获取自定义登录票据的函数
const getTickFn = () => Promise.resolve("custom_ticket_123456");
const { data, error } = await auth.signInWithCustomTicket(getTickFn);
if (error) {
console.error("自定义登录失败:", error.message);
} else {
console.log("自定义登录成功,用户信息:", data.user);
console.log("会话信息:", data.session);
}
// 异步获取自定义登录票据
const getTickFn = async () => {
// 模拟从后端API获取票据
const response = await fetch("/api/get-custom-ticket");
const data = await response.json();
return data.ticket;
};
const { data, error } = await auth.signInWithCustomTicket(getTickFn);
if (error) {
console.error("自定义登录失败:", error.message);
} else {
console.log("自定义登录成功");
}
try {
const getTickFn = () => Promise.resolve("custom_ticket_123456");
const { data, error } = await auth.signInWithCustomTicket(getTickFn);
if (error) {
switch (error.code) {
case "invalid_ticket":
console.error("票据无效或已过期,请重新获取");
break;
case "ticket_required":
console.error("需要提供自定义登录票据");
break;
case "network_error":
console.error("网络连接失败,请检查网络设置后重试");
break;
default:
console.error("登录失败:", error.message);
}
} else {
console.log("登录成功");
}
} catch (error) {
console.error("网络错误:", error);
}
signInWithOpenId
async signInWithOpenId(params?: SignInWithOpenIdReq): Promise<SignInRes>
微信小程序 OpenID 静默登录。如果用户不存在,会根据云开发平台/登录方式中对应身份源的登录模式配置,判断是否自动注册。
仅支持在 微信小程序 中使用
参数
登录参数
返回
示例
const { data, error } = await auth.signInWithOpenId();
const { data, error } = await auth.signInWithOpenId({ useWxCloud: false });
signInWithPhoneAuth
async signInWithPhoneAuth(params: SignInWithPhoneAuthReq): Promise<SignInRes>
微信小程序手机号授权登录。如果用户不存在,会根据云开发平台/登录方式中对应身份源的登录模式配置,判断是否自动注册。
仅支持在 微信小程序 中使用
参数
登录参数
返回
示例
const { data, error } = await auth.signInWithPhoneAuth({ phoneCode: "xxx" });
会话管理
getSession
async getSession(): Promise<SignInRes>
获取当前会话信息,检查用户登录状态。
- 获取当前用户的会话信息,包括访问令牌、用户信息等
- 检查用户是否已登录,未登录时返回空会话
参数
无参数
返回
示例
const { data, error } = await auth.getSession();
if (error) {
console.error("获取会话失败:", error.message);
} else if (data.session) {
console.log("用户已登录:", data.session.user);
console.log("访问令牌:", data.session.access_token);
console.log("过期时间:", data.session.expires_in, "秒");
} else {
console.log("用户未登录,请先登录");
// 显示登录按钮
document.getElementById("loginBtn").style.display = "block";
}
document.addEventListener("DOMContentLoaded", async () => {
const { data, error } = await auth.getSession();
if (error) {
console.error("检查登录状态失败:", error.message);
return;
}
if (data.session) {
// 用户已登录,显示用户信息
document.getElementById("userInfo").innerHTML = `
<p>欢迎,${data.session.user?.name || data.session.user?.username}</p>
`;
document.getElementById("loginBtn").style.display = "none";
document.getElementById("logoutBtn").style.display = "block";
} else {
// 用户未登录,显示登录界面
document.getElementById("loginForm").style.display = "block";
}
});
// 定时检查会话状态,自动刷新令牌
function setupSessionMonitor() {
setInterval(async () => {
const { data, error } = await auth.getSession();
if (error) {
console.error("会话检查失败:", error.message);
} else if (data.session) {
const expiresIn = data.session.expires_in;
// 如果令牌将在5分钟内过期,则自动刷新
if (expiresIn < 300) {
console.log("令牌即将过期,自动刷新...");
await auth.refreshSession();
}
}
}, 60000); // 每分钟检查一次
}
// 启动会话监控
setupSessionMonitor();
try {
const { data, error } = await auth.getSession();
if (error) {
switch (error.code) {
case "unreachable":
console.error("网络连接失败,请检查网络设置后重试");
break;
case "token_expired":
console.error("访问令牌已过期,请重新登录");
// 自动刷新令牌
await auth.refreshSession();
break;
case "invalid_refresh_token":
console.error("刷新令牌无效,请重新登录");
break;
case "refresh_token_expired":
console.error("刷新令牌已过期,请重新登录");
break;
case "user_not_found":
console.error("用户不存在,请重新登录");
break;
case "permission_denied":
console.error("权限不足,请检查安全域名配置");
break;
default:
console.error("获取会话失败:", error.message);
}
} else {
console.log("会话获取成功");
}
} catch (error) {
console.error("未知错误:", error);
}
refreshSession
async refreshSession(refresh_token?: string): Promise<SignInRes>
刷新会话令牌,延长用户登录状态,支持自动续期和错误恢复。
- 使用刷新令牌获取新的访问令牌
- 延长用户会话的有效期
- 支持使用指定的刷新令牌或默认令牌
参数
返回
示例
const { data, error } = await auth.refreshSession();
if (error) {
console.error("刷新会话失败:", error.message);
// 刷新失败,可能需要重新登录
window.location.href = "/login";
} else {
console.log("会话刷新成功,新令牌:", data.session?.access_token);
console.log("新过期时间:", data.session?.expires_in, "秒");
}
const savedRefreshToken = "refresh_token";
if (savedRefreshToken) {
const { data, error } = await auth.refreshSession(savedRefreshToken);
if (error) {
console.error("使用保存的令牌刷新失败:", error.message);
} else {
console.log("使用保存的令牌刷新成功");
}
} else {
console.log("没有保存的刷新令牌,使用默认方式刷新");
const { data, error } = await auth.refreshSession();
if (error) {
console.error("刷新失败:", error.message);
}
}
// 设置定时器,在令牌过期前自动刷新
function setupTokenRefresh() {
setInterval(async () => {
const { data, error } = await auth.getSession();
if (data.session) {
const expiresIn = data.session.expires_in;
// 如果令牌将在5分钟内过期,则刷新
if (expiresIn < 300) {
console.log("令牌即将过期,自动刷新...");
const { data: refreshData, error: refreshError } =
await auth.refreshSession();
if (refreshError) {
console.error("自动刷新失败:", refreshError.message);
} else {
console.log("自动刷新成功");
}
}
}
}, 60000); // 每分钟检查一次
}
// 启动定时刷新
setupTokenRefresh();
try {
const { data, error } = await auth.refreshSession();
if (error) {
switch (error.code) {
case "invalid_refresh_token":
console.error("刷新令牌无效,请重新登录");
// 需要重新登录
window.location.href = "/login";
break;
case "refresh_token_expired":
console.error("刷新令牌已过期,请重新登录");
// 需要重新登录
window.location.href = "/login";
break;
case "user_not_found":
console.error("用户不存在,请重新注册");
// 清除本地会话
localStorage.removeItem("refresh_token");
break;
case "unreachable":
console.error("网络连接失败,请检查网络设置后重试");
break;
case "permission_denied":
console.error("权限不足,请检查安全域名配置");
break;
case "resource_exhausted":
console.error("刷新频率过高,请稍后重试");
break;
default:
console.error("刷新失败:", error.message);
}
} else {
console.log("刷新成功");
}
} catch (error) {
console.error("网络错误:", error);
}
setSession
async setSession(params: SetSessionReq): Promise<SignInRes>
使用现有的访问令牌和刷新令牌来设置用户会话,支持外部系统集成和手动会话管理。
- 使用现有的 access_token 和 refresh_token 来设置用户会话
- 适用于从外部系统获取令牌后手动设置会话的场景
- 成功设置会话后会触发 SIGNED_IN 事件
参数
返回
示例
const { data, error } = await auth.setSession({
access_token: "your_access_token_here",
refresh_token: "your_refresh_token_here",
});
if (error) {
console.error("会话设置失败:", error.message);
} else {
console.log("会话设置成功");
console.log("用户信息:", data.user);
console.log("会话信息:", data.session);
}
signOut
async signOut(params?: SignOutReq): Promise<SignOutRes>
用户登出,清除当前会话和本地存储。
- 安全退出当前用户登录状态
- 清除服务器端会话和本地存储
- 支持重定向到指定页面
- 触发认证状态变化事件
参数
返回
示例
const { data, error } = await auth.signOut();
if (error) {
console.error("登出失败:", error.message);
} else {
console.log("登出成功");
// 登出后跳转到登录页
window.location.href = "/login";
}
const { data, error } = await auth.signOut({
options: {
redirectTo: "/login",
clearStorage: true,
},
});
if (error) {
console.error("登出失败:", error.message);
} else {
console.log("登出成功,正在跳转到登录页...");
// 自动重定向到登录页
window.location.href = "/login";
}
async function safeSignOut() {
// 显示确认对话框
if (!confirm("确定要退出登录吗?")) {
return;
}
// 显示加载状态
document.getElementById("logoutBtn").disabled = true;
document.getElementById("logoutBtn").innerText = "登出中...";
const { data, error } = await auth.signOut();
if (error) {
console.error("登出失败:", error.message);
alert("登出失败: " + error.message);
// 恢复按钮状态
document.getElementById("logoutBtn").disabled = false;
document.getElementById("logoutBtn").innerText = "退出登录";
} else {
console.log("登出成功");
// 清除本地存储
localStorage.removeItem("user_session");
sessionStorage.clear();
// 显示成功消息
alert("已安全退出登录");
// 跳转到登录页
window.location.href = "/login";
}
}
// 登出按钮点击事件
document.getElementById("logoutBtn").addEventListener("click", safeSignOut);
try {
const { data, error } = await auth.signOut();
if (error) {
switch (error.code) {
case "network_error":
console.error("网络连接失败,请检查网络设置后重试");
alert("网络连接失败,请稍后重试");
break;
case "session_not_found":
console.error("会话不存在,可能已经登出");
// 清除本地存储并跳转
localStorage.clear();
window.location.href = "/login";
break;
case "token_invalid":
console.error("令牌无效,请重新登录");
// 强制清除并跳转
localStorage.clear();
window.location.href = "/login";
break;
case "permission_denied":
console.error("权限不足,无法执行登出操作");
alert("权限不足,无法登出");
break;
case "unreachable":
console.error("服务器连接失败,请检查网络设置");
alert("服务器连接失败,请检查网络");
break;
default:
console.error("登出失败:", error.message);
alert("登出失败: " + error.message);
}
} else {
console.log("登出成功");
// 显示成功消息
alert("已安全退出登录");
// 跳转到登录页
window.location.href = "/login";
}
} catch (error) {
console.error("未知错误:", error);
alert("发生未知错误,请重试");
}
用户管理
getUser
async getUser(): Promise<GetUserRes>
获取当前登录用户的详细信息,包括身份信息、元数据和权限状态,支持用户资料展示和权限验证。
- 获取当前登录用户的完整信息
- 包括用户基本信息、元数据、身份信息等 需要用户已登录状态才能获取完整信息
- 支持检查用户权限和验证状态
参数
无参数
返回
示例
const { data, error } = await auth.getUser();
if (error) {
console.error("获取用户信息失败:", error.message);
} else if (data.user) {
const user = data.user;
console.log("用户ID:", user.id);
console.log("邮箱:", user.email);
console.log("手机号:", user.phone);
console.log("用户名:", user.user_metadata?.username);
console.log("昵称:", user.user_metadata?.nickName);
console.log("头像:", user.user_metadata?.avatarUrl);
console.log("注册时间:", user.created_at);
} else {
console.log("用户未登录");
}
// 在用户资料页面显示详细信息
async function loadUserProfile() {
const { data, error } = await auth.getUser();
if (error) {
document.getElementById("error").innerText =
"获取用户信息失败: " + error.message;
return;
}
if (data.user) {
const user = data.user;
// 更新页面显示
document.getElementById("userEmail").innerText = user.email || "未设置";
document.getElementById("userPhone").innerText = user.phone || "未设置";
document.getElementById("userName").innerText =
user.user_metadata?.name || "未设置";
document.getElementById("userNickname").innerText =
user.user_metadata?.nickName || "未设置";
document.getElementById("userAvatar").src =
user.user_metadata?.avatarUrl || "/default-avatar.png";
document.getElementById("regTime").innerText = new Date(
user.created_at
).toLocaleString();
} else {
document.getElementById("error").innerText = "用户未登录";
}
}
// 页面加载时调用
loadUserProfile();
async function checkUserPermissions() {
const { data, error } = await auth.getUser();
if (error) {
console.error("获取用户信息失败:", error.message);
return false;
}
if (data.user) {
const user = data.user;
// 检查邮箱是否已验证
if (!user.email_confirmed_at) {
console.log("邮箱未验证,需要验证邮箱");
return false;
}
// 检查用户角色
if (user.role?.includes("administrator")) {
console.log("管理员用户,拥有全部权限");
return true;
} else if (!!user.role?.length) {
console.log("普通用户,拥有基本权限");
return true;
} else {
console.log("未知用户角色");
return false;
}
} else {
console.log("用户未登录,无权限");
return false;
}
}
// 检查权限并执行操作
if (await checkUserPermissions()) {
// 有权限,执行操作
console.log("有权限,继续执行...");
} else {
// 无权限,显示错误
console.log("无权限,操作被拒绝");
}
try {
const { data, error } = await auth.getUser();
if (error) {
switch (error.code) {
case "user_not_found":
console.error("用户不存在,请重新登录");
// 可能是会话已过期,需要重新登录
window.location.href = "/login";
break;
case "token_expired":
console.error("访问令牌已过期,尝试刷新令牌");
// 尝试刷新令牌
await auth.refreshSession();
// 重新获取用户信息
await auth.getUser();
break;
case "unreachable":
console.error("网络连接失败,请检查网络设置后重试");
break;
case "permission_denied":
console.error("权限不足,请检查安全域名配置");
break;
case "invalid_refresh_token":
console.error("刷新令牌无效,请重新登录");
window.location.href = "/login";
break;
case "refresh_token_expired":
console.error("刷新令牌已过期,请重新登录");
window.location.href = "/login";
break;
default:
console.error("获取用户信息失败:", error.message);
}
} else {
console.log("用户信息获取成功");
}
} catch (error) {
console.error("未知错误:", error);
}
refreshUser
async refreshUser(): Promise<CommonRes>
刷新当前登录用户的信息。
- 刷新当前登录用户的完整信息
- 从服务器重新获取最新的用户数据
- 适用于用户信息可能已更新但本地缓存未同步的场景 需要用户已登录状态才能刷新信息
参数
无参数
返回
示例
const { data, error } = await auth.refreshUser();
if (error) {
console.error("刷新用户信息失败:", error.message);
} else {
console.log("用户信息已刷新");
console.log("最新用户信息:", data.user);
console.log("最新会话信息:", data.session);
}
// 当用户修改资料后,刷新页面显示
async function refreshUserProfile() {
const { data, error } = await auth.refreshUser();
if (error) {
console.error("刷新失败:", error.message);
return false;
}
if (data.user) {
const user = data.user;
// 更新页面显示
document.getElementById("userEmail").innerText = user.email || "未设置";
document.getElementById("userPhone").innerText = user.phone || "未设置";
document.getElementById("name").innerText =
user.user_metadata?.name || "未设置";
document.getElementById("userNickname").innerText =
user.user_metadata?.nickName || "未设置";
document.getElementById("userAvatar").src =
user.user_metadata?.avatarUrl || "/default-avatar.png";
console.log("用户信息已刷新并更新显示");
return true;
}
return false;
}
// 在用户修改资料后调用
await refreshUserProfile();
async function safeRefreshUser() {
try {
const { data, error } = await auth.refreshUser();
if (error) {
switch (error.code) {
case "user_not_found":
console.error("用户不存在,请重新登录");
break;
case "token_expired":
console.error("访问令牌已过期,尝试刷新会话");
await auth.refreshSession();
// 重新刷新用户信息
return await auth.refreshUser();
case "unreachable":
console.error("网络连接失败,请检查网络设置后重试");
break;
default:
console.error("刷新用户信息失败:", error.message);
}
return null;
}
return data;
} catch (error) {
console.error("刷新过程中发生未知错误:", error);
return null;
}
}
// 安全地刷新用户信息
const refreshedData = await safeRefreshUser();
if (refreshedData) {
console.log("用户信息刷新成功");
}
updateUser
async updateUser(params: UpdateUserReq): Promise<GetUserRes>
更新当前登录用户的信息。
- 不支持更新密码,更新密码请使用 resetPasswordForEmail 或 resetPasswordForOld 或 reauthenticate
- 更新当前登录用户的基本信息和元数据
- 支持更新邮箱、手机号、用户名、昵称、头像等
- 需要用户已登录状态才能更新信息 更新成功后返回更新后的用户信息
参数
返回
示例
const { data, error } = await auth.updateUser({
nickname: "新昵称",
gender: "MALE",
});
if (error) {
console.error("更新用户信息失败:", error.message);
} else {
console.log("用户信息已更新:", data.user);
console.log("新邮箱:", data.user?.email);
console.log("新昵称:", data.user?.user_metadata?.nickName);
}
// 更新 email 或 phone(需要验证)
const { data } = await app.auth.updateUser({
email: "new@example.com",
});
// 调用 verifyOtp 回调验证
await data.verifyOtp({ email: "new@example.com", token: "123456" });
async function saveUserProfile(formData) {
const { data, error } = await auth.updateUser({
username: formData.username,
nickname: formData.nickname,
gender: formData.gender,
description: formData.description,
avatar_url: formData.avatarUrl,
});
if (error) {
document.getElementById("error").innerText = "保存失败: " + error.message;
return false;
} else {
document.getElementById("success").innerText = "资料保存成功";
return true;
}
}
// 表单提交事件
document.getElementById("profileForm").addEventListener("submit", async (e) => {
e.preventDefault();
const formData = {
username: document.getElementById("username").value,
nickname: document.getElementById("nickname").value,
gender: document.getElementById("gender").value,
description: document.getElementById("description").value,
avatarUrl: document.getElementById("avatar").value,
};
await saveUserProfile(formData);
});
try {
const { data, error } = await auth.updateUser({
email: "invalid-email",
phone: "123456",
});
if (error) {
switch (error.code) {
case "failed_precondition":
console.error("邮箱或手机号已被其他用户使用,请使用其他号码");
break;
case "invalid_email":
console.error("邮箱格式错误,请检查邮箱格式");
break;
case "invalid_phone":
console.error("手机号格式错误,请检查手机号格式");
break;
case "password_too_weak":
console.error("密码强度不足,请使用更复杂的密码");
break;
case "unreachable":
console.error("网络连接失败,请检查网络设置后重试");
break;
case "permission_denied":
console.error("权限不足,请检查安全域名配置");
break;
case "resource_exhausted":
console.error("更新频率过高,请稍后重试");
break;
case "user_not_found":
console.error("用户不存在,请重新登录");
break;
default:
console.error("更新失败:", error.message);
}
} else {
console.log("更新成功");
}
} catch (error) {
console.error("网络错误:", error);
}
deleteUser
async deleteUser(params: DeleteMeReq): Promise<CommonRes>
删除当前登录用户的账户。
- 永久删除当前登录用户的账户
- 需要验证用户密码进行身份确认
- 删除后所有用户数据将被永久移除
- 操作不可逆,请谨慎使用
参数
返回
示例
const { data, error } = await auth.deleteUser({
password: "userPassword123",
});
if (error) {
console.error("账户删除失败:", error.message);
} else {
console.log("账户删除成功");
// 用户已登出,重定向到首页
window.location.href = "/";
}
async function deleteAccount(password) {
if (!confirm("确定要删除账户吗?此操作不可逆,所有数据将被永久删除!")) {
return false;
}
const { data, error } = await auth.deleteUser({ password });
if (error) {
switch (error.code) {
case "invalid_password":
alert("密码错误,请重新输入");
break;
case "user_not_found":
alert("用户不存在");
break;
default:
alert("删除失败: " + error.message);
}
return false;
} else {
alert("账户删除成功");
return true;
}
}
// 删除账户表单提交
document
.getElementById("deleteAccountForm")
.addEventListener("submit", async (e) => {
e.preventDefault();
const password = document.getElementById("password").value;
const success = await deleteAccount(password);
if (success) {
// 重定向到首页
window.location.href = "/";
}
});
async function deleteAccountWithVerification(password, verificationCode) {
// 第一步:验证密码
const { data: verifyData, error: verifyError } = await auth.reauthenticate();
if (verifyError) {
alert("身份验证失败: " + verifyError.message);
return false;
}
// 第二步:等待验证码输入
const { data: updateData, error: updateError } = await verifyData.updateUser({
nonce: verificationCode,
password,
});
if (updateError) {
alert("验证码错误: " + updateError.message);
return false;
}
// 第三步:删除账户
const { data, error } = await auth.deleteUser({ password });
if (error) {
alert("删除失败: " + error.message);
return false;
} else {
alert("账户删除成功");
return true;
}
}
class AccountDeletionManager {
constructor() {
this.deletionAttempts = 0;
this.maxAttempts = 3;
}
async deleteAccount(password) {
if (this.deletionAttempts >= this.maxAttempts) {
alert("删除尝试次数过多,请稍后再试");
return false;
}
this.deletionAttempts++;
const { data, error } = await auth.deleteUser({ password });
if (error) {
if (error.code === "invalid_password") {
const remainingAttempts = this.maxAttempts - this.deletionAttempts;
alert(`密码错误,剩余尝试次数: ${remainingAttempts}`);
} else {
alert("删除失败: " + error.message);
}
return false;
} else {
alert("账户删除成功");
this.deletionAttempts = 0;
return true;
}
}
resetAttempts() {
this.deletionAttempts = 0;
}
}
// 使用账户删除管理器
const deletionManager = new AccountDeletionManager();
// 删除账户
document.getElementById("deleteBtn").addEventListener("click", async () => {
const password = prompt("请输入密码确认删除账户:");
if (password) {
await deletionManager.deleteAccount(password);
}
});
身份源管理
getUserIdentities
async getUserIdentities(): Promise<GetUserIdentitiesRes>
获取当前用户绑定的所有身份源信息。
- 获取所有第三方身份源,相关身份源可在云开发平台/身份认证/登录方式中进行配置配置
- 返回身份源的详细信息,包括平台标识、身份源 ID、绑定时间等
- 需要用户已登录状态才能获取身份源信息
参数
无参数
返回
示例
const { data, error } = await auth.getUserIdentities();
if (error) {
console.error("获取身份源失败:", error.message);
} else if (data.identities) {
console.log("用户绑定的身份源:", data.identities);
data.identities.forEach((identity) => {
console.log(
`- ${identity.name} (${identity.provider}): ${identity.provider_user_id}`
);
console.log(
` 绑定时间: ${new Date(identity.created_at).toLocaleString()}`
);
});
} else {
console.log("用户未绑定任何身份源");
}
async function loadUserIdentities() {
const { data, error } = await auth.getUserIdentities();
if (error) {
document.getElementById("error").innerText =
"获取身份源失败: " + error.message;
return;
}
const container = document.getElementById("identitiesContainer");
container.innerHTML = "";
if (data.identities && data.identities.length > 0) {
data.identities.forEach((identity) => {
const identityElement = document.createElement("div");
identityElement.className = "identity-item";
identityElement.innerHTML = `
<h3>${identity.name}</h3>
<p>平台: ${identity.provider}</p>
<p>绑定时间: ${new Date(identity.created_at).toLocaleString()}</p>
<button onclick="unbindIdentity('${identity.id}')">解绑</button>
`;
container.appendChild(identityElement);
});
} else {
container.innerHTML = "<p>您还没有绑定任何第三方账号</p>";
}
}
// 页面加载时调用
loadUserIdentities();
async function isProviderBound(provider) {
const { data, error } = await auth.getUserIdentities();
if (error) {
console.error("检查身份源失败:", error.message);
return false;
}
if (data.identities) {
return data.identities.some((identity) => identity.provider === provider);
}
return false;
}
// 检查是否绑定了微信
const isWechatBound = await isProviderBound("wechat");
if (isWechatBound) {
console.log("已绑定微信账号");
document.getElementById("bindWechatBtn").style.display = "none";
} else {
console.log("未绑定微信账号");
document.getElementById("bindWechatBtn").style.display = "block";
}
linkIdentity
async linkIdentity(params: LinkIdentityReq): Promise<LinkIdentityRes>
绑定新的身份源到当前用户,会自动跳转第三方 OAuth 授权页面。
- 将新的第三方身份源绑定到当前登录用户,支持绑定微信、Google、GitHub 等第三方平台,身份源需先在云开发平台/身份认证/登录方式中进行配置配置
- 绑定成功后,用户可以使用该身份源进行登录
- 需要用户已登录状态才能绑定身份源
- 在 cloudbase.init 时设置
auth.detectSessionInUrl为true时,从第三方回调回来后会自动调用 verifyOAuth 进行验证,否则后续需要手动通过 verifyOAuth 方法进行验证
参数
返回
示例
const app = cloudbase.init({
env: "your-env-id", // 替换为您的环境ID
region: "ap-shanghai", // 地域,默认为上海
accessKey: "", // 填入生成的 Publishable Key,
auth: {
detectSessionInUrl: true, // 可选:自动检测 URL 中的 OAuth 参数
},
});
// 监听身份源绑定事件
auth.onAuthStateChange((event, session, info) => {
console.log("认证状态变化:", { event, session, info });
switch (event) {
case "BIND_IDENTITY":
if (!!info.error) {
console.error("身份源绑定失败:", info.error);
// 可以在这里添加UI错误提示
} else {
console.log("身份源已绑定");
// 重新加载身份源列表
await auth.getUserIdentities();
}
break;
default:
return;
}
});
try {
const { data, error } = await auth.linkIdentity({
provider: "google",
});
if (error) {
console.error("绑定身份源失败:", error.message);
// 处理绑定失败逻辑
return;
}
console.log("身份源绑定请求已发送,等待用户授权...");
// 绑定请求成功,等待用户完成OAuth授权流程
} catch (error) {
console.error("调用linkIdentity方法时发生错误:", error);
// 处理网络错误或其他异常
}
const app = cloudbase.init({
env: "your-env-id", // 替换为您的环境ID
region: "ap-shanghai", // 地域,默认为上海
accessKey: "", // 填入生成的 Publishable Key,
auth: {
detectSessionInUrl: true, // 可选:自动检测 URL 中的 OAuth 参数
},
});
const auth = app.auth;
async function bindProvider(provider) {
try {
// 显示加载状态
document.getElementById("bindBtn").disabled = true;
document.getElementById("status").innerText = "绑定中...";
const { data, error } = await auth.linkIdentity({ provider });
if (error) {
console.error("身份源绑定失败:", error);
document.getElementById("status").innerText =
"绑定失败: " + error.message;
document.getElementById("bindBtn").disabled = false;
// 根据错误类型提供更具体的提示
if (error.message.includes("already bound")) {
document.getElementById("status").innerText =
"该身份源已绑定,无需重复绑定";
} else if (error.message.includes("not logged in")) {
document.getElementById("status").innerText = "请先登录后再绑定身份源";
} else if (error.message.includes("provider not found")) {
document.getElementById("status").innerText = "不支持的身份源类型";
}
} else {
console.log("身份源绑定请求已发送,等待用户授权...");
document.getElementById("status").innerText = "正在跳转授权页面...";
// 绑定请求成功,等待用户完成OAuth授权流程
// 实际绑定结果将通过onAuthStateChange事件通知
}
} catch (error) {
console.error("绑定身份源时发生异常:", error);
document.getElementById("status").innerText = "绑定过程发生异常,请重试";
document.getElementById("bindBtn").disabled = false;
}
}
// 监听身份源绑定结果
auth.onAuthStateChange((event, session, info) => {
if (event === "BIND_IDENTITY") {
if (info.error) {
console.error("身份源绑定失败:", info.error);
document.getElementById("status").innerText =
"授权失败: " + info.error.message;
document.getElementById("bindBtn").disabled = false;
} else {
console.log("身份源绑定成功");
document.getElementById("status").innerText = "绑定成功";
document.getElementById("bindBtn").style.display = "none";
// 更新身份源列表
loadUserIdentities();
}
}
});
// 绑定按钮点击事件
document.getElementById("bindWechatBtn").addEventListener("click", () => {
bindProvider("wechat");
});
unlinkIdentity
async unlinkIdentity(params: UnlinkIdentityReq): Promise<CommonRes>
解绑当前用户绑定的身份源。
- 解绑当前登录用户绑定的第三方身份源,相关身份源可在云开发平台/身份认证/登录方式中进行配置配置
- 解绑成功后需要重新加载身份源列表
- 使用身份源标识(provider)而非身份源 ID(identity_id)进行解绑
参数
返回
示例
const { data, error } = await auth.unlinkIdentity({
provider: "wechat",
});
if (error) {
console.error("解绑身份源失败:", error.message);
} else {
console.log("身份源解绑成功");
// 重新加载身份源列表
await auth.getUserIdentities();
}
async function unbindIdentity(provider) {
if (!confirm("确定要解绑这个账号吗?")) {
return;
}
const { data, error } = await auth.unlinkIdentity({ provider });
if (error) {
alert("解绑失败: " + error.message);
} else {
alert("解绑成功");
// 重新加载身份源列表
await loadUserIdentities();
}
}
// 解绑按钮点击事件
document.querySelectorAll(".unbind-btn").forEach((btn) => {
btn.addEventListener("click", (e) => {
const provider = e.target.dataset.provider;
unbindIdentity(provider);
});
});
async function unbindMultipleProviders(providers) {
const results = [];
for (const provider of providers) {
const result = await auth.unlinkIdentity({ provider });
results.push({ provider, result });
if (result.error) {
console.error(`解绑${provider}失败:`, result.error.message);
} else {
console.log(`解绑${provider}成功`);
}
}
return results;
}
// 解绑多个身份源
const providers = ["wechat", "google", "github"];
const unbindResults = await unbindMultipleProviders(providers);
// 统计解绑结果
const successCount = unbindResults.filter((r) => !r.result.error).length;
console.log(
`成功解绑 ${successCount} 个身份源,失败 ${
providers.length - successCount
} 个`
);
try {
const { data, error } = await auth.unlinkIdentity({
provider: "invalid_provider",
});
if (error) {
switch (error.code) {
case "provider_not_found":
console.error("身份源不存在,请检查身份源标识是否正确");
break;
case "last_identity_cannot_unlink":
console.error("不能解绑最后一个身份源,请至少保留一个登录方式");
break;
case "permission_denied":
console.error("没有权限解绑此身份源,请检查权限设置");
break;
case "unreachable":
console.error("网络连接失败,请检查网络设置后重试");
break;
case "resource_exhausted":
console.error("解绑频率过高,请稍后重试");
break;
case "user_not_found":
console.error("用户不存在,请重新登录");
break;
case "token_expired":
console.error("会话已过期,请重新登录");
break;
default:
console.error("解绑失败:", error.message);
}
} else {
console.log("解绑成功");
}
} catch (error) {
console.error("网络错误:", error);
}
密码管理
resetPasswordForEmail
async resetPasswordForEmail(email: string): Promise<ResetPasswordForEmailRes>
通过邮箱重置用户密码,采用四步验证流程。
- 通过邮箱发送验证码来重置用户密码
- 采用四步验证流程:发送验证码 → 等待用户输入 → 验证验证码 → 设置新密码
- 需要用户邮箱已注册且已验证
参数
用户注册的邮箱地址
返回
示例
// 第一步:发送验证码到邮箱
const { data, error } = await auth.resetPasswordForEmail("user@example.com");
if (error) {
console.error("发送验证码失败:", error.message);
} else {
console.log("验证码已发送到邮箱,等待用户输入...");
// 第二步:等待用户输入验证码和新密码
const verificationCode = "123456"; // 用户输入的验证码
const newPassword = "newSecurePassword123"; // 用户输入的新密码
// 第三步:验证验证码并设置新密码
const { data: loginData, error: loginError } = await data.updateUser({
nonce: verificationCode,
password: newPassword,
});
if (loginError) {
console.error("重置密码失败:", loginError.message);
} else {
console.log("密码重置成功,用户已自动登录");
console.log("用户信息:", loginData.user);
}
}
let resetPasswordVerify = null;
async function startPasswordReset(email) {
const { data, error } = await auth.resetPasswordForEmail(email);
if (error) {
document.getElementById("error").innerText =
"发送验证码失败: " + error.message;
return false;
} else {
resetPasswordVerify = data.updateUser;
// 显示验证码输入框
document.getElementById("verificationSection").style.display = "block";
document.getElementById("emailSection").style.display = "none";
document.getElementById("status").innerText =
"验证码已发送到您的邮箱,请查收";
return true;
}
}
async function completePasswordReset(code, newPassword) {
if (!resetPasswordVerify) {
alert("请先发送验证码");
return false;
}
const { data, error } = await resetPasswordVerify({
nonce: code,
password: newPassword,
});
if (error) {
document.getElementById("error").innerText =
"重置密码失败: " + error.message;
return false;
} else {
document.getElementById("success").innerText = "密码重置成功,已自动登录";
// 跳转到首页
setTimeout(() => {
window.location.href = "/dashboard";
}, 2000);
return true;
}
}
// 表单提交事件
document.getElementById("resetForm").addEventListener("submit", async (e) => {
e.preventDefault();
const email = document.getElementById("email").value;
const code = document.getElementById("code").value;
const newPassword = document.getElementById("newPassword").value;
if (!resetPasswordVerify) {
await startPasswordReset(email);
} else {
await completePasswordReset(code, newPassword);
}
});
try {
const { data, error } = await auth.resetPasswordForEmail("invalid-email");
if (error) {
switch (error.code) {
case "invalid_email":
console.error("邮箱格式错误,请检查邮箱格式");
break;
case "user_not_found":
console.error("用户不存在,请检查邮箱是否正确");
break;
case "email_not_verified":
console.error("邮箱未验证,请先验证邮箱");
break;
case "rate_limit_exceeded":
console.error("发送频率过高,请稍后再试");
break;
default:
console.error("发送验证码失败:", error.message);
}
}
} catch (error) {
console.error("网络错误:", error);
}
resetPasswordForOld
async resetPasswordForOld(params: ResetPasswordForOldReq): Promise<SignInRes>
通过旧密码重置当前登录用户的密码。
- 通过验证旧密码来重置当前登录用户的密码
- 需要用户已登录状态
- 适用于用户记得旧密码的场景
参数
返回
示例
const { data, error } = await auth.resetPasswordForOld({
new_password: "newSecurePassword123",
old_password: "oldPassword123",
});
if (error) {
console.error("密码重置失败:", error.message);
} else {
console.log("密码重置成功");
console.log("用户信息:", data.user);
console.log("会话信息:", data.session);
}
async function changePassword(oldPassword, newPassword) {
const { data, error } = await auth.resetPasswordForOld({
new_password: newPassword,
old_password: oldPassword,
});
if (error) {
switch (error.code) {
case "invalid_password":
alert("旧密码不正确");
break;
case "password_too_weak":
alert("新密码强度不够,请使用更复杂的密码");
break;
default:
alert("密码重置失败: " + error.message);
}
return false;
} else {
alert("密码重置成功");
return true;
}
}
// 表单提交事件
document
.getElementById("passwordForm")
.addEventListener("submit", async (e) => {
e.preventDefault();
const oldPassword = document.getElementById("oldPassword").value;
const newPassword = document.getElementById("newPassword").value;
const confirmPassword = document.getElementById("confirmPassword").value;
if (newPassword !== confirmPassword) {
alert("新密码和确认密码不一致");
return;
}
const success = await changePassword(oldPassword, newPassword);
if (success) {
// 跳转到首页或用户中心
window.location.href = "/dashboard";
}
});
function validatePassword(password) {
const minLength = 8;
const hasUpperCase = /[A-Z]/.test(password);
const hasLowerCase = /[a-z]/.test(password);
const hasNumbers = /\d/.test(password);
const hasSpecialChar = /[!@#$%^&*(),.?":{}|<>]/.test(password);
return (
password.length >= minLength &&
hasUpperCase &&
hasLowerCase &&
hasNumbers &&
hasSpecialChar
);
}
async function resetPasswordWithValidation(oldPassword, newPassword) {
if (!validatePassword(newPassword)) {
alert("密码必须包含大小写字母、数字和特殊字符,且长度不少于8位");
return false;
}
const { data, error } = await auth.resetPasswordForOld({
new_password: newPassword,
old_password: oldPassword,
});
if (error) {
alert("密码重置失败: " + error.message);
return false;
}
alert("密码重置成功");
return true;
}
try {
const { data, error } = await auth.resetPasswordForOld({
new_password: "newPassword123",
old_password: "wrongOldPassword",
});
if (error) {
switch (error.code) {
case "invalid_password":
console.error("旧密码不正确,请重新输入");
document.getElementById("oldPassword").classList.add("error");
break;
case "password_too_weak":
console.error("新密码强度不足,请使用更复杂的密码");
document.getElementById("newPassword").classList.add("error");
break;
case "user_not_found":
console.error("用户不存在,请重新登录");
window.location.href = "/login";
break;
case "token_expired":
console.error("会话已过期,请重新登录");
window.location.href = "/login";
break;
case "permission_denied":
console.error("权限不足,无法修改密码");
break;
case "unreachable":
console.error("网络连接失败,请检查网络设置后重试");
break;
case "resource_exhausted":
console.error("重置频率过高,请稍后重试");
break;
default:
console.error("密码重置失败:", error.message);
}
} else {
console.log("密码重置成功");
}
} catch (error) {
console.error("网络错误:", error);
}
reauthenticate
async reauthenticate(): Promise<ReauthenticateRes>
重新认证当前登录用户身份,通过验证码验证并允许修改密码。
短信验证码 仅支持 上海 地域
- 重新认证当前已登录用户的身份,支持更新密码
- 通过发送验证码到用户注册的邮箱或手机号进行验证,优先选用邮箱,如果用户未设置邮箱则使用手机号
- 适用于安全敏感操作前的身份验证
参数
无参数
返回
示例
// 第一步:发送验证码(使用当前用户信息)
const { data, error } = await auth.reauthenticate();
if (error) {
console.error("发送验证码失败:", error.message);
} else {
console.log("验证码已发送,等待用户输入...");
// 第二步:等待用户输入验证码和新密码
const verificationCode = "123456"; // 用户输入的验证码
const newPassword = "newSecurePassword123"; // 用户输入的新密码
// 第三步:验证验证码并设置新密码
const { data: loginData, error: loginError } = await data.updateUser({
nonce: verificationCode,
password: newPassword,
});
if (loginError) {
console.error("重新认证失败:", loginError.message);
} else {
console.log("重新认证成功,密码已更新");
console.log("用户信息:", loginData.user);
}
}
async function verifyIdentityBeforeSensitiveOperation() {
// 在执行敏感操作前重新认证用户
const { data, error } = await auth.reauthenticate();
if (error) {
console.error("身份验证失败:", error.message);
return false;
}
console.log("验证码已发送到您的邮箱/手机,请输入验证码继续");
// 显示验证码输入界面
document.getElementById("verificationModal").style.display = "block";
return new Promise((resolve) => {
// 等待用户输入验证码
document.getElementById("verifyBtn").addEventListener("click", async () => {
const code = document.getElementById("code").value;
const newPassword = document.getElementById("newPassword").value;
const { data: verifyData, error: verifyError } = await data.updateUser({
nonce: code,
password: newPassword,
});
if (verifyError) {
console.error("验证失败:", verifyError.message);
resolve(false);
} else {
console.log("身份验证成功,继续执行敏感操作");
document.getElementById("verificationModal").style.display = "none";
resolve(true);
}
});
});
}
// 执行敏感操作前验证身份
if (await verifyIdentityBeforeSensitiveOperation()) {
// 执行敏感操作
performSensitiveOperation();
}
try {
const { data, error } = await auth.reauthenticate();
if (error) {
switch (error.code) {
case "user_not_found":
console.error("用户未登录,请先登录");
window.location.href = "/login";
break;
case "email_not_set":
console.error("用户未设置邮箱,无法发送验证码");
document.getElementById("error").innerText = "请先设置邮箱地址";
break;
case "phone_not_set":
console.error("用户未设置手机号,无法发送验证码");
document.getElementById("error").innerText = "请先设置手机号码";
break;
case "rate_limit_exceeded":
console.error("发送频率过高,请稍后再试");
document.getElementById("resendBtn").disabled = true;
setTimeout(() => {
document.getElementById("resendBtn").disabled = false;
}, 60000);
break;
case "unreachable":
console.error("网络连接失败,请检查网络设置后重试");
break;
case "permission_denied":
console.error("权限不足,请检查安全域名配置");
break;
default:
console.error("发送验证码失败:", error.message);
document.getElementById("error").innerText =
"发送失败: " + error.message;
}
}
} catch (error) {
console.error("网络错误:", error);
document.getElementById("error").innerText = "网络错误,请重试";
}
async function verifyReauthenticationCode(code, newPassword) {
try {
const { data, error } = await auth.reauthenticate();
if (error) {
console.error("发送验证码失败:", error.message);
return false;
}
const { data: verifyData, error: verifyError } = await data.updateUser({
nonce: code,
password: newPassword,
});
if (verifyError) {
switch (verifyError.code) {
case "invalid_code":
console.error("验证码不正确,请重新输入");
document.getElementById("code").classList.add("error");
break;
case "code_expired":
console.error("验证码已过期,请重新获取");
document.getElementById("resendBtn").style.display = "block";
break;
case "max_attempts_exceeded":
console.error("验证次数过多,请稍后重试");
document.getElementById("verifyBtn").disabled = true;
break;
case "password_too_weak":
console.error("新密码强度不足,请使用更复杂的密码");
document.getElementById("newPassword").classList.add("error");
break;
default:
console.error("验证失败:", verifyError.message);
}
return false;
} else {
console.log("重新认证成功");
return true;
}
} catch (error) {
console.error("网络错误:", error);
return false;
}
}
验证管理
verifyOAuth
async verifyOAuth(params?: VerifyOAuthReq): Promise<SignInRes>
验证第三方平台授权回调,完成 OAuth 登录流程。
- 验证第三方平台授权回调,获取用户信息并完成登录,可以配合signInWithOAuth使用
- 支持自动从 URL 参数获取授权码和状态参数
- 提供完整的安全验证机制,防止 CSRF 攻击
参数
返回
示例
// 在授权回调页面调用,自动获取URL参数
const { data, error } = await auth.verifyOAuth();
if (error) {
console.error("授权验证失败:", error.message);
} else {
console.log("授权成功,用户信息:", data.user);
console.log("会话信息:", data.session);
// 验证成功后跳转到首页
window.location.href = "/home";
}
// 手动获取URL参数并验证
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get("code");
const state = urlParams.get("state");
const { data, error } = await auth.verifyOAuth({
code: code,
state: state,
provider: "wechat",
});
if (error) {
console.error("微信授权验证失败:", error.message);
} else {
console.log("微信授权成功,用户昵称:", data.user?.user_metadata?.nickName);
}
// 第一步:生成授权链接
const { data, error } = await auth.signInWithOAuth({
provider: "wechat",
options: {
redirectTo: "https://example.com/oauth-callback",
state: "wx_oauth_20241204",
},
});
if (error) {
console.error("获取授权链接失败:", error.message);
return;
}
// 第二步:跳转到授权页面
window.location.href = data.url;
// 在回调页面(oauth-callback)中:
// 第三步:验证授权结果
const { data: verifyData, error: verifyError } = await auth.verifyOAuth();
if (verifyError) {
console.error("授权验证失败:", verifyError.message);
document.getElementById("error").innerText = verifyError.message;
} else {
console.log("授权成功,用户已登录");
window.location.href = "/dashboard";
}
try {
const { data, error } = await auth.verifyOAuth();
if (error) {
switch (error.code) {
case "invalid_code":
console.error("授权码无效或已过期,请重新授权");
break;
case "state_mismatch":
console.error("状态参数不匹配,可能存在安全风险,请重新授权");
break;
case "provider_mismatch":
console.error("第三方平台标识不匹配,请检查平台配置");
break;
case "failed_precondition":
console.error("从第三方获取用户信息失败,请检查平台配置");
break;
case "resource_exhausted":
console.error("请求频率过高,请稍后重试");
break;
case "permission_denied":
console.error("权限不足,请检查安全域名配置");
break;
case "unreachable":
console.error("网络连接失败,请检查网络设置后重试");
break;
case "invalid_code":
console.error("授权码无效或已过期,请重新授权");
break;
case "state_mismatch":
console.error("状态参数不匹配,可能存在安全风险,请重新授权");
break;
default:
console.error("授权验证失败:", error.message);
}
document.getElementById("error").innerText = "授权失败,请重新尝试";
} else {
console.log("授权验证成功");
}
} catch (error) {
console.error("网络错误:", error);
}
verifyOtp
async verifyOtp(params: VerifyOtpReq): Promise<SignInRes>
验证一次性密码(OTP),完成登录或注册流程。
短信验证码 仅支持 上海 地域
- 验证通过邮箱或手机号发送的一次性密码(OTP)
- 支持邮箱和手机号两种验证方式(二选一)
- 验证成功后自动登录用户并返回会话信息
- 适用于注册、登录、密码重置等场景
参数
返回
示例
const phone = "13800138000";
// 1.获取验证码
const { data } = await auth.resend({ phone });
// 2.验证验证码
const { data: verifyData, error } = await auth.verifyOtp({
phone: "13800138000",
token: "123456",
messageId: data.messageId,
});
if (error) {
console.error("验证失败:", error.message);
} else {
console.log("验证成功,用户信息:", data: verifyData.user);
console.log("会话信息:", data: verifyData.session);
}
const email = "user@example.com";
// 1.获取验证码
const verificationInfo = await auth.getVerification({
email,
});
// 2.验证验证码
const { data, error } = await auth.verifyOtp({
email,
token: "654321",
verificationInfo,
});
if (error) {
console.error("邮箱验证失败:", error.message);
} else {
console.log("邮箱验证成功,用户邮箱:", data.user?.email);
}
async function completeRegistration(email, verificationCode) {
const { data, error } = await auth.verifyOtp({
email: email,
token: verificationCode,
});
if (error) {
document.getElementById("error").innerText = "验证失败: " + error.message;
return false;
} else {
document.getElementById("success").innerText = "注册成功,欢迎加入!";
// 自动登录用户
window.location.href = "/dashboard";
return true;
}
}
// 注册表单提交
document
.getElementById("registerForm")
.addEventListener("submit", async (e) => {
e.preventDefault();
const email = document.getElementById("email").value;
const code = document.getElementById("code").value;
await completeRegistration(email, code);
});
try {
const { data, error } = await auth.verifyOtp({
phone: "13800138000",
token: "wrong_code",
});
if (error) {
switch (error.code) {
case "invalid_code":
console.error("验证码错误,请重新输入");
document.getElementById("code").classList.add("error");
break;
case "code_expired":
console.error("验证码已过期,请重新获取");
document.getElementById("resendBtn").style.display = "block";
break;
case "max_attempts_exceeded":
console.error("验证次数过多,请稍后再试");
document.getElementById("verifyBtn").disabled = true;
break;
default:
console.error("验证失败:", error.message);
}
} else {
console.log("验证成功");
}
} catch (error) {
console.error("网络错误:", error);
}
resend
async resend(params: ResendReq): Promise<ResendRes>
重新发送验证码到邮箱或手机号。
短信验证码 仅支持 上海 地域
- 向用户重新发送邮箱或手机号的验证码
- 支持注册、邮箱变更、手机号变更等场景
- 重新发送后获取新的消息 ID,用于后续验证流程
- 提供频率限制保护,防止恶意重发
参数
返回
示例
// 第一次发送验证码
const { data, error } = await auth.signInWithOtp({ phone: "13800138000" });
// 验证码校验回调
let signUpVerify = data.verifyOtp;
// 重新发送验证码,获取新的messageId
const { data: resendData, error: resendError } = await auth.resend({
phone: "13800138000",
type: "signup",
});
if (resendError) {
console.error("重发验证码失败:", resendError.message);
console.error("错误代码:", resendError.code);
} else {
console.log("验证码已重发,消息ID:", resendData.messageId);
// 将新的messageId传入signInWithOtp()或signUp()的callback参数
const verificationCode = "123456"; // 用户输入的验证码
const messageId = resendData.messageId; // 新的messageId
// 使用新的messageId进行验证
const { data: loginData, error: loginError } = await signUpVerify({
token: verificationCode,
messageId,
});
if (loginError) {
console.error("验证失败:", loginError.message);
} else {
console.log("验证成功");
}
// 开始倒计时
startCountdown(60);
}
const { data, error } = await auth.resend({
email: "user@example.com",
type: "email_change",
});
if (error) {
console.error("重发邮箱验证码失败:", error.message);
} else {
console.log("邮箱验证码已重发");
// 显示提示信息
document.getElementById("resendStatus").innerText =
"验证码已重新发送到您的邮箱";
}
let countdown = 0;
let countdownInterval;
function startCountdown(seconds) {
countdown = seconds;
const resendBtn = document.getElementById("resendBtn");
resendBtn.disabled = true;
resendBtn.innerText = `${countdown}秒后可重发`;
countdownInterval = setInterval(() => {
countdown--;
resendBtn.innerText = `${countdown}秒后可重发`;
if (countdown <= 0) {
clearInterval(countdownInterval);
resendBtn.disabled = false;
resendBtn.innerText = "重新发送验证码";
}
}, 1000);
}
async function resendVerificationCode() {
const email = document.getElementById("email").value;
if (!email) {
alert("请输入邮箱地址");
return;
}
const { data, error } = await auth.resend({
email: email,
type: "signup",
});
if (error) {
alert("重发失败: " + error.message);
} else {
alert("验证码已重新发送到您的邮箱");
startCountdown(60); // 60秒倒计时
}
}
// 重发按钮点击事件
document
.getElementById("resendBtn")
.addEventListener("click", resendVerificationCode);
try {
const { data, error } = await auth.resend({
phone: "13800138000",
type: "signup",
});
if (error) {
switch (error.code) {
case "rate_limit_exceeded":
console.error("发送频率过高,请稍后再试");
document.getElementById("resendBtn").disabled = true;
setTimeout(() => {
document.getElementById("resendBtn").disabled = false;
}, 60000); // 1分钟后重试
break;
case "invalid_phone":
console.error("手机号格式错误");
break;
case "invalid_email":
console.error("邮箱格式错误");
break;
default:
console.error("重发失败:", error.message);
}
} else {
console.log("重发成功");
}
} catch (error) {
console.error("网络错误:", error);
}
其他工具
onAuthStateChange
onAuthStateChange(callback: OnAuthStateChangeCallback): OnAuthStateChangeResult
监听认证状态变化,实时响应登录、登出、令牌刷新等事件。
- 监听用户认证状态的变化事件
- 支持多种事件类型:登录、登出、令牌刷新、用户信息更新、身份源绑定等
- 返回订阅对象,用于取消监听
- 适用于构建响应式 UI 和状态管理
参数
状态变化回调函数
返回
示例
const { data } = auth.onAuthStateChange((event, session, info) => {
console.log("认证状态变化:", event, session, info);
switch (event) {
case "INITIAL_SESSION":
console.log("初始会话已建立");
if (session) {
console.log("用户已登录:", session.user?.email);
} else {
console.log("用户未登录");
}
break;
case "SIGNED_IN":
console.log("用户登录成功:", session.user?.email);
// 更新UI显示
document.getElementById("loginBtn").style.display = "none";
document.getElementById("userInfo").style.display = "block";
document.getElementById("userEmail").innerText =
session.user?.email || "";
break;
case "SIGNED_OUT":
console.log("用户已登出");
// 更新UI显示
document.getElementById("loginBtn").style.display = "block";
document.getElementById("userInfo").style.display = "none";
break;
case "PASSWORD_RECOVERY":
console.log("密码已重置");
// 显示密码重置界面
document.getElementById("passwordResetForm").style.display = "block";
break;
case "TOKEN_REFRESHED":
console.log("令牌已刷新");
break;
case "USER_UPDATED":
console.log("用户信息已更新");
// 更新用户信息显示
if (session) {
document.getElementById("userEmail").innerText =
session.user?.email || "";
document.getElementById("userAvatar").src =
session.user?.user_metadata?.avatarUrl || "";
}
break;
case "BIND_IDENTITY":
console.log("身份源绑定结果");
if (!!info.error) {
console.log("身份源绑定失败");
} else {
console.log("身份源已绑定");
}
break;
}
});
// 取消监听(在组件卸载时调用)
// data.subscription.unsubscribe();
import { useEffect, useState } from "react";
function AuthStatus() {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const { data } = auth.onAuthStateChange((event, session, info) => {
setLoading(false);
if (event === "SIGNED_IN" || event === "INITIAL_SESSION") {
setUser(session?.user || null);
} else if (event === "SIGNED_OUT") {
setUser(null);
}
});
// 清理函数
return () => {
data.subscription.unsubscribe();
};
}, []);
if (loading) {
return <div>加载中...</div>;
}
return (
<div>
{user ? (
<div>
<p>欢迎,{user.email}</p>
<button onClick={() => auth.signOut()}>退出登录</button>
</div>
) : (
<div>
<p>请先登录</p>
<button
onClick={() =>
auth.signInWithPassword({
/* 登录参数 */
})
}
>
登录
</button>
</div>
)}
</div>
);
}
// 路由守卫组件
function RouteGuard({ children }) {
const [authenticated, setAuthenticated] = useState(false);
const [loading, setLoading] = useState(true);
useEffect(() => {
const { data } = auth.onAuthStateChange((event, session, info) => {
setLoading(false);
if (event === "SIGNED_IN" || event === "INITIAL_SESSION") {
if (session) {
setAuthenticated(true);
} else {
setAuthenticated(false);
}
} else if (event === "SIGNED_OUT") {
setAuthenticated(false);
}
});
return () => {
data.subscription.unsubscribe();
};
}, []);
if (loading) {
return <div>检查登录状态...</div>;
}
if (!authenticated) {
// 未登录,重定向到登录页
window.location.href = "/login";
return <div>重定向到登录页...</div>;
}
return children;
}
// 使用路由守卫
function App() {
return (
<div>
<RouteGuard>
<Dashboard />
</RouteGuard>
</div>
);
}
// 全局认证状态管理
class AuthManager {
constructor() {
this.currentUser = null;
this.listeners = [];
this.setupAuthListener();
}
setupAuthListener() {
const { data } = auth.onAuthStateChange((event, session, info) => {
switch (event) {
case "SIGNED_IN":
case "INITIAL_SESSION":
this.currentUser = session?.user || null;
this.notifyListeners();
break;
case "SIGNED_OUT":
this.currentUser = null;
this.notifyListeners();
break;
}
});
this.unsubscribe = data.subscription.unsubscribe;
}
addListener(listener) {
this.listeners.push(listener);
}
removeListener(listener) {
this.listeners = this.listeners.filter((l) => l !== listener);
}
notifyListeners() {
this.listeners.forEach((listener) => listener(this.currentUser));
}
destroy() {
if (this.unsubscribe) {
this.unsubscribe();
}
}
}
// 创建全局认证管理器
const authManager = new AuthManager();
// 在不同页面中使用
function PageA() {
const [user, setUser] = useState(null);
useEffect(() => {
authManager.addListener(setUser);
return () => authManager.removeListener(setUser);
}, []);
return <div>{user ? `欢迎,${user.email}` : "请登录"}</div>;
}
getClaims
async getClaims(): Promise<GetClaimsRes>
获取当前访问令牌中的声明信息,用于调试和权限检查。
- 解析当前访问令牌的 JWT 声明信息
- 返回令牌的头部、声明和签名部分
- 用于调试令牌信息、检查权限和验证令牌状态
- 需要用户已登录状态才能获取令牌信息
参数
无参数
返回
示例
const { data, error } = await auth.getClaims();
if (error) {
console.error("获取声明失败:", error.message);
} else {
console.log("令牌声明信息:", data.claims);
console.log("令牌头部信息:", data.header);
console.log("令牌签名:", data.signature);
// 解析用户信息
if (data.claims) {
console.log("用户ID:", data.claims.sub);
console.log("过期时间:", new Date(data.claims.exp * 1000).toLocaleString());
console.log("签发时间:", new Date(data.claims.iat * 1000).toLocaleString());
console.log("用户角色:", data.claims.role);
}
}
async function checkTokenPermissions() {
const { data, error } = await auth.getClaims();
if (error) {
console.error("获取令牌信息失败:", error.message);
return false;
}
if (data.claims) {
const claims = data.claims;
// 检查令牌是否过期
const now = Math.floor(Date.now() / 1000);
if (claims.exp && claims.exp < now) {
console.error("令牌已过期");
return false;
}
// 检查用户角色
if (claims.role === "admin") {
console.log("管理员权限");
return true;
} else if (claims.role === "user") {
console.log("普通用户权限");
return true;
} else {
console.error("未知用户角色");
return false;
}
}
return false;
}
// 检查权限并执行操作
if (await checkTokenPermissions()) {
console.log("有权限,继续执行...");
} else {
console.log("无权限,操作被拒绝");
}
async function checkTokenExpiration() {
const { data, error } = await auth.getClaims();
if (error) {
console.error("检查令牌失败:", error.message);
return false;
}
if (data.claims) {
const claims = data.claims;
const now = Math.floor(Date.now() / 1000);
const expiresAt = claims.exp;
if (expiresAt) {
const timeLeft = expiresAt - now;
const minutesLeft = Math.floor(timeLeft / 60);
const secondsLeft = timeLeft % 60;
if (timeLeft <= 0) {
console.error("令牌已过期,请重新登录");
return false;
} else if (timeLeft < 300) {
console.warn(
`令牌将在 ${minutesLeft}分${secondsLeft}秒后过期,建议刷新令牌`
);
return true;
} else {
console.log(`令牌有效,剩余时间: ${minutesLeft}分${secondsLeft}秒`);
return true;
}
}
}
return false;
}
// 定期检查令牌状态
setInterval(async () => {
const isValid = await checkTokenExpiration();
if (!isValid) {
console.log("令牌已过期,自动刷新...");
await auth.refreshSession();
}
}, 60000); // 每分钟检查一次
toDefaultLoginPage
async toDefaultLoginPage(params: authModels.ToDefaultLoginPage): Promise<void>
跳转系统默认登录页,兼容 web 和微信小程序端。
- 支持跳转到系统默认登录页面
- 兼容 Web 端和微信小程序端
- 可配置登录页面的版本和重定向地址
- 支持携带自定义参数跳转
本地调试
如果开发 Web 端应用,由于 __auth 登录页面静态资源存放于静态网站托管中,所以在本地调试时需要配置代理才能成功跳转 __auth 登录页面。
推荐使用 Whistle 工具进行代理配置。 __auth 登录页面的访问域名可在静态网站托管-配置信息-默认域名中查看。
假设本地启动应用的访问地址为 http://localhost:3000,__auth 登录页面的访问域名为lowcode-xxx-xxx.tcloudbaseapp.com,则 Whistle 代理的 Rules 配置如下:
https://lowcode-xxx-xxx.tcloudbaseapp.com http://localhost:3000
# 应用其他路径代理配置
运行应用后,通过 https://lowcode-xxx-xxx.tcloudbaseapp.com 即可访问应用
参数
返回
示例
const app = cloudbase.init({
env: "xxxx-yyy",
region: "ap-shanghai", // 不传默认为上海地域
});
const auth = app.auth();
await auth.toDefaultLoginPage({
config_version: "env",
app_id: "app-xxx",
redirect_uri: "xxx",
});
错误码
登录错误
| 错误码 | 说明 |
|---|---|
| not_found | 用户不存在 |
| password_not_set | 当前用户未设置密码,请使用验证码登录或第三方登录方式 |
| invalid_password | 密码不正确 |
| user_pending | 该用户未激活 |
| user_blocked | 该用户被停用 |
| invalid_status | 您已经超过了密码最大重试次数, 请稍后重试 |
| invalid_two_factor | 二次验证码不匹配或已过时 |
注册错误
| 错误码 | 说明 |
|---|---|
| failed_precondition | 你输入的手机号或邮箱已被注册,请使用其他号码 |
验证码相关错误
| 错误码 | 说明 |
|---|---|
| failed_precondition | 从第三方获取用户信息失败 |
| resource_exhausted | 你尝试过于频繁,请稍后重试 |
| invalid_argument | 您输入的验证码不正确或已过期 |
| aborted | 你尝试的次数过多,请返回首页,稍后重试 |
| permission_denied | 您当前的会话已过期,请返回重试 |
| captcha_required | 需要输入验证码, 需根据反机器人服务接入 |
| captcha_invalid | 验证码不正确, 需根据反机器人服务接入 |
其他错误
| 错误码 | 说明 |
|---|---|
| unreachable | 网络错误,请检查您的网络连接,稍后重试 |
错误描述
| 错误码 | 错误描述 | 说明 |
|---|---|---|
| permission_denied | cors permission denied,please check if {url} in your client {env} domains | 请在“云开发平台/环境配置/安全来源/安全域名”中检查对应{env}环境下是否已经配置了安全域名{url},配置后 10 分钟生效 |
完整类型定义
SignInAnonymouslyReq
// 匿名登录参数
interface SignInAnonymouslyReq {
provider_token?: string; // 提供令牌(可选)
}
User
interface User {
id: any; // 用户ID
aud: string; // 受众
role: string[]; // 用户角色
email: any; // 邮箱
email_confirmed_at: string; // 邮箱确认时间
phone: any; // 手机号
phone_confirmed_at: string; // 手机号确认时间
confirmed_at: string; // 确认时间
last_sign_in_at: string; // 最后登录时间
app_metadata: {
// 应用元数据
provider: any; // 提供商
providers: any[]; // 提供商列表
};
user_metadata: {
// 用户元数据
name: any; // 姓名
picture: any; // 头像
username: any; // 用户名
gender: any; // 性别
locale: any; // 地区
uid: any; // 用户ID
nickName: any; // 昵称
avatarUrl: any; // 头像URL
location: any; // 位置
hasPassword: any; // 是否有密码
};
identities: any; // 身份信息
created_at: string; // 创建时间
updated_at: string; // 更新时间
is_anonymous: boolean; // 是否匿名用户
// 新增字段
recovery_sent_at?: string; // 密码重置发送时间
email_change_sent_at?: string; // 邮箱变更发送时间
phone_change_sent_at?: string; // 手机号变更发送时间
new_email?: string; // 新邮箱地址
new_phone?: string; // 新手机号
}
Session
interface Session {
access_token: string; // 访问令牌
refresh_token: string; // 刷新令牌
expires_in: number; // 过期时间(秒)
token_type: string; // 令牌类型
user: User; // 用户信息
// 新增字段
provider_token?: string; // 第三方平台令牌
provider_refresh_token?: string; // 第三方平台刷新令牌
expires_at?: number; // 过期时间戳
issued_at?: number; // 签发时间戳
scope?: string; // 授权范围
token_id?: string; // 令牌ID
}
AuthError
// 认证错误类型
interface AuthError extends Error {
code: (string & {}) | undefined; // 错误代码
status: number | undefined; // HTTP状态码
// 常见错误代码
// 400: 客户端错误
// - invalid_email: 邮箱格式错误
// - invalid_phone: 手机号格式错误
// - invalid_password: 密码格式错误
// - user_not_found: 用户不存在
// - email_already_exists: 邮箱已存在
// - phone_already_exists: 手机号已存在
// - username_already_exists: 用户名已存在
// - invalid_code: 验证码错误
// - code_expired: 验证码已过期
// - max_attempts_exceeded: 验证次数过多
// - password_too_weak: 密码强度不足
// - invalid_token: 令牌无效
// - token_expired: 令牌已过期
// - state_mismatch: 状态参数不匹配
// - provider_not_supported: 不支持的第三方平台
// - provider_mismatch: 第三方平台标识不匹配
// - failed_precondition: 前置条件失败
// - permission_denied: 权限不足
// - resource_exhausted: 资源耗尽
// - unreachable: 网络连接失败
// 500: 服务器错误
// - internal_error: 内部服务器错误
// - service_unavailable: 服务不可用
}
CommonRes
// 通用响应参数
interface CommonRes {
data: {}; // 成功时为空对象
error: AuthError | null; // 错误信息,成功时为null
}
SignUpReq
// 用户注册参数(四步验证流程)
interface SignUpReq {
email?: string; // 邮箱(可选,与手机号二选一)
phone?: string; // 手机号(可选,与邮箱二选一)
password: string; // 密码(必填)
username?: string; // 用户名称(可选),长度 5-24 位,支持字符中英文、数字、特殊字符(仅支持_-),不支持中文
nickname?: string; // 昵称(可选)
avatar_url?: string; // 头像URL(可选)
gender?: "MALE" | "FEMALE"; // 性别(可选)
}
SignOutReq
// 用户登出参数
interface SignOutReq {
options?: {
// 配置选项(可选)
redirectTo?: string; // 登出后的重定向地址
clearStorage?: boolean; // 是否清除本地存储(默认true)
};
}
SignInWithPasswordReq
// 密码登录参数
interface SignInWithPasswordReq {
username?: string; // 用户名称(可选,与邮箱、手机号三选一),长度 5-24 位,支持字符中英文、数字、特殊字符(仅支持_-),不支持中文
email?: string; // 邮箱(可选,与用户名、手机号三选一)
phone?: string; // 手机号(可选,与用户名、邮箱三选一)
password: string; // 密码(必填)
is_encrypt?: boolean; // 是否加密,默认为false
}
SignInWithIdTokenReq
// ID令牌登录参数
interface SignInWithIdTokenReq {
provider?: string; // 第三方平台标识(可选)
token: string; // 第三方平台的身份令牌(必填)
// 新增字段
provider?: string; // 第三方平台标识(可选,与provider参数重复,保留兼容性)
}
SignInWithOtpReq
// OTP登录参数
interface SignInWithOtpReq {
email?: string; // 邮箱(可选,与手机号二选一)
phone?: string; // 手机号(可选,与邮箱二选一)
}
SignInWithOAuthReq
// OAuth授权参数
interface SignInWithOAuthReq {
provider: string; // 第三方平台标识(必填)
options?: {
// 配置选项(可选)
redirectTo?: string; // 回调地址,默认为当前页面
skipBrowserRedirect?: boolean; // 是否跳转至授权页面,默认为false
state?: string; // 状态参数,用于安全验证,默认为随机字符串(格式:prd-{provider}-{随机字符串})
queryParams?: Record<string, string>; // 额外的查询参数,将合并到授权 URI 中
type?: "sign_in" | "bind_identity"; // 类型(可选),默认为'sign_in', sign_in: 登录,bind_identity: 绑定身份
};
}
SetSessionReq
// 会话设置参数
interface SetSessionReq {
access_token: string; // 访问令牌(必填)
refresh_token: string; // 刷新令牌(必填)
}
VerifyOAuthReq
// OAuth验证参数
interface VerifyOAuthReq {
code?: string; // 授权码(可选,默认从URL参数获取)
state?: string; // 状态参数(可选,默认从URL参数获取)
provider?: string; // 第三方平台标识(可选,默认从session获取)
}
VerifyOtpReq
// OTP验证参数
interface VerifyOtpReq {
type?:
| "sms"
| "phone_change"
| "signup"
| "invite"
| "magiclink"
| "recovery"
| "email_change"
| "email"; // 验证类型(可选)
email?: string; // 邮箱(可选,与手机号二选一)
phone?: string; // 手机号(可选,与邮箱二选一)
token: string; // 验证码(必填)
messageId: string; // 验证码对应ID(必填)
}
UpdateUserReq
// 用户信息更新参数
interface UpdateUserReq {
email?: string; // 邮箱地址
phone?: string; // 手机号
username?: string; // 用户名称(可选),长度 5-24 位,支持中英文、数字、特殊字符(仅支持_-),不支持中文
description?: string; // 描述(可选)
avatar_url?: string; // 头像URL(可选)
nickname?: string; // 昵称(可选)
gender?: "MALE" | "FEMALE"; // 性别(可选)
}
LinkIdentityReq
// 身份源绑定参数
interface LinkIdentityReq {
provider: string; // 身份源标识(必填)
}
UnlinkIdentityReq
// 身份源解绑参数
interface UnlinkIdentityReq {
provider: string; // 身份源标识(必填)
}
ReauthenticateReq
// 重新认证参数
interface ReauthenticateReq {
// 无入参,使用当前登录用户的信息
}
ResendReq
// 重发验证码参数
interface ResendReq {
email?: string; // 邮箱(可选,与手机号二选一)
phone?: string; // 手机号(可选,与邮箱二选一)
type?: "signup" | "email_change" | "phone_change" | "sms"; // 类型(可选)
}
ResendRes
// 重发验证码响应参数
interface ResendRes {
data: {
messageId?: string; // 消息ID(验证码ID)
};
error: AuthError | null; // 错误信息,成功时为null
}
SignInWithOtpRes
// OTP登录响应参数
interface SignInWithOtpRes {
data: {
verifyOtp?: (params: {
token: string;
messageId?: string;
}) => Promise<SignInRes>; // 验证码回调函数,支持messageId参数
};
error: AuthError | null; // 错误信息,成功时为null
}
SignUpRes
// 用户注册响应参数
interface SignUpRes {
data: {
verifyOtp?: (params: {
token: string;
messageId?: string;
}) => Promise<SignInRes>; // 验证码回调函数,支持messageId参数
};
error: AuthError | null;
}
SignInOAuthRes
// OAuth授权响应参数
interface SignInOAuthRes {
data: {
url?: string; // 授权页面URL
provider?: string; // 第三方平台标识
scopes?: string; // 授权范围
};
error: AuthError | null; // 错误信息,成功时为null
}
LinkIdentityRes
// 身份源绑定响应参数
interface LinkIdentityRes {
data: {
provider?: string; // 绑定的身份源标识
type?: "sign_in" | "bind_identity" | ""; // 类型(可选),默认为'sign_in', sign_in: 登录,bind_identity: 绑定身份
};
error: AuthError | null; // 错误信息,成功时为null
}
Identity
interface Identity {
id: string; // 身份源标识
name: string; // 身份源名称
picture: string; // 头像URL
}
GetUserIdentitiesRes
// 用户身份源获取响应参数
interface GetUserIdentitiesRes {
data: {
identities?: Array<{
id: string; // 身份源标识
name: string; // 身份源名称
picture: string; // 头像URL
}>;
};
error: AuthError | null; // 错误信息,成功时为null
}
GetClaimsRes
// 声明信息获取响应参数
interface GetClaimsRes {
data: {
// 令牌声明信息
claims?: {
iss: string; // issuer
sub: string; // subject
aud: string; // audience
exp: number; // expiration time
iat: number; // issued at
at_hash: string; // access token hash
name: string; // 名称
picture?: string; // 头像URL
email?: string; // 邮箱
phone_number?: string; // 手机号
scope: string; // 授权范围
project_id: string; // 项目ID
provider?: string; // 第三方平台标识
provider_type?: string; // 第三方平台类型
groups?: string[]; // 用户组
meta?: {
wxOpenId?: string;
wxUnionId?: string;
};
user_id: string; // 用户ID
roles: string[]; // 角色
user_type: string; // 用户类型
client_type: string; // 客户端类型
is_system_admin: boolean; // 是否系统管理员
};
// 令牌头部信息
header?: {
alg: string; // 加密算法
kid: string; // 令牌ID
};
signature?: string; // 令牌签名
};
error: AuthError | null; // 错误信息,成功时为null
}
ResetPasswordForOldReq
// 通过旧密码重置密码参数
interface ResetPasswordForOldReq {
new_password: string; // 新密码(必填)
old_password: string; // 旧密码(必填)
}
DeleteMeReq
// 删除当前用户参数
interface DeleteMeReq {
password: string; // 用户密码(必填)
}
SignInRes
// 登录响应参数
interface SignInRes {
data: {
user?: User; // 用户信息
session?: Session; // 会话信息
};
error: AuthError | null; // 错误信息,成功时为null
}
GetUserRes
// 用户信息获取响应参数
interface GetUserRes {
data: {
user?: User; // 用户详细信息
};
error: AuthError | null; // 错误信息,成功时为null
}
OnAuthStateChangeEvent
// 认证状态变化事件类型
type OnAuthStateChangeEvent =
| "SIGNED_OUT" // 用户已登出
| "SIGNED_IN" // 用户登录成功
| "INITIAL_SESSION" // 初始会话已建立
| "PASSWORD_RECOVERY" // 密码已重置
| "TOKEN_REFRESHED" // 令牌已刷新
| "USER_UPDATED" // 用户信息已更新
| "BIND_IDENTITY"; // 身份源绑定结果
OnAuthStateChangeCallback
// 认证状态变化回调函数类型
type OnAuthStateChangeCallback = (
event: OnAuthStateChangeEvent,
session: Session
) => void;
ResetPasswordForEmailRes
// 邮箱重置密码响应参数
interface ResetPasswordForEmailRes {
data: {
updateUser?: (attributes: UpdateUserAttributes) => Promise<SignInRes>; // 验证码回调函数,支持新密码参数
};
error: AuthError | null; // 错误信息,成功时为null
}
UpdateUserAttributes
// 用户属性更新参数
interface UpdateUserAttributes {
nonce: string; // 验证码
password: string; // 新密码
}
ReauthenticateRes
// 重新认证响应参数
interface ReauthenticateRes {
data: {
updateUser?: (attributes: UpdateUserAttributes) => Promise<SignInRes>; // 验证码回调函数,支持新密码参数
};
error: AuthError | null; // 错误信息,成功时为null
}