概述
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)进行登录验证,支持邮箱和手机号验证。
短信验证码 仅支持 上海 地域
- 通过邮箱或手机号发送一次性验证码进行登录验证
- 支持完整的验证流程:发送验证码 → 等待用户输入 → 验证并登录
- 适用于无密码登录场景,提供更高的安全性
- 使用前,请确认已在云开发平台/身份认证/登录方式/常规登录中开启邮箱/短信验证码登录
- 如果用户不存在,会默认注册用户,可以通过
shouldCreateUser参数控制是否自动创建用户,默认为 true
参数
返回
示例
- 手机验证码登录
- 邮箱验证码登录
- 关闭自动注册
- 错误处理
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);
}
}
const { data, error } = await auth.signInWithOtp({
phone: "13800138000",
options: {
shouldCreateUser: false,
},
});
if (error) {
console.error("发送验证码失败:", error.message);
} else {
console.log("验证码已发送,等待用户输入...");
// 用户输入验证码后验证
const { data: loginData, error: loginError } = await data.verifyOtp({
token: "123456",
});
// 未注册用户会提示“user not exist”
}
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}-{随机字符串}的状态参数 - 回调地址需要配置在云开发平台的安全域名中,否则会返回权限错误
- 目前,使用“微信开放平台”登录时先要确保用户已关联对应的身份源,可以通过 linkIdentity 进行身份源关联
参数
返回
示例
- 微信授权登录
- Google授权登录
- OAuth 登录最佳实践
- 手动处理 OAuth回调(不推荐)
// 初始化
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 等)的身份令牌进行登录
- 支持指定第三方平台标识,第三方平台需在云开发平台/身份认证/登录方式中先进行配置配置
- 令牌为必填参数
参数
返回
示例
- 微信令牌登录
- 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 静默登录。如果用户不存在,会根据云开发平台/登录方式中对应身份源的登录模式配置,判断是否自动注册。
仅支持在 微信小程序 中使 用
参数
登录参数
返回
示例
- 微信云开发模式
- 普通 http 模式
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("