arctic 是一个现代、轻量级且类型安全的 JavaScript/TypeScript OAuth 2.0 客户端库(由 Lucia Auth 的作者开发)。它不绑定任何特定的框架(如 Next.js 或 SvelteKit),也不绑定特定的数据库,只专注于处理 OAuth 的协议流程。
下面以 Google 账号登录 为例,详细介绍如何使用 arctic 实现完整的 OAuth 2.0 登录流程。
1. 准备工作:在 Google Cloud 获取凭证
在开始写代码前,你需要在 Google Cloud Console 中配置:
- 创建一个项目并启用 OAuth 同意屏幕 (OAuth consent screen)。
- 进去 凭据 (Credentials) 页面,创建一个 OAuth 2.0 客户端 ID (OAuth 2.0 Client ID)。
- 设置 已启用的重定向 URI (Authorized redirect URIs)。例如本地开发可以设置为:
http://localhost:3000/login/google/callback - 保存后,你将获得:
- Client ID (客户端 ID)
- Client Secret (客户端密钥)
2. 安装 arctic
在你的项目中安装 arctic:
npm install arctic
3. 初始化 Google 客户端
在项目中创建一个 OAuth 配置文件(例如 src/lib/oauth.ts),初始化 Google 实例:
import { Google } from "arctic";
// 建议将敏感信息放在环境变量中
const clientId = process.env.GOOGLE_CLIENT_ID!;
const clientSecret = process.env.GOOGLE_CLIENT_SECRET!;
const redirectURI = "http://localhost:3000/login/google/callback";
export const google = new Google(clientId, clientSecret, redirectURI);
4. 步骤一:引导用户跳转至 Google 登录页
当用户点击“使用 Google 登录”按钮时,你需要生成一个授权 URL,并重定向用户。 为了防止 CSRF 攻击,Google 登录强制要求使用 State(状态码)和 Code Verifier(PKCE 代码验证器)。
以下是服务端的处理逻辑(以标准 Web API 规范为例,适用于 Next.js, SvelteKit, Astro 等):
import { generateState, generateCodeVerifier } from "arctic";
import { google } from "./oauth";
export async function GET(request: Request) {
// 1. 生成安全的随机字符
const state = generateState();
const codeVerifier = generateCodeVerifier();
// 2. 生成 Google 授权 URL
const scopes = ["openid", "profile", "email"];
const url = await google.createAuthorizationURL(state, codeVerifier, scopes);
// 3. 将 state 和 codeVerifier 存入 Cookie 中,供回调阶段校验
// 注意:生产环境务必开启 Secure, HttpOnly 并设置合适的 SameSite 属性
const response = new Response(null, {
status: 302,
headers: {
Location: url.toString(),
},
});
// 存入 cookie (通常需要库如 serialize 或框架自带的 cookie 挂载)
// 示例伪代码:
// setCookie("google_oauth_state", state, { secure: true, httpOnly: true, maxAge: 600 });
// setCookie("google_code_verifier", codeVerifier, { secure: true, httpOnly: true, maxAge: 600 });
return response;
}
5. 步骤二:处理 Google 回调 (Callback)
用户在 Google 页面同意授权后,浏览器会被重定向回你设置的 redirectURI(例如 /login/google/callback),并携带 code 和 state 参数。
你需要在这个路由中接收参数,校验它们,并向 Google 换取用户信息。
import { google } from "./oauth";
export async function GET(request: Request) {
const url = new URL(request.url);
const code = url.searchParams.get("code");
const state = url.searchParams.get("state");
// 1. 从之前保存的 Cookie 中取出 state 和 codeVerifier
const storedState = getCookie(request, "google_oauth_state");
const storedCodeVerifier = getCookie(request, "google_code_verifier");
// 2. 安全校验:确保 state 匹配以防止 CSRF 攻击
if (!code || !state || !storedState || state !== storedState || !storedCodeVerifier) {
return new Response("参数校验失败,请重新登录", { status: 400 });
}
try {
// 3. 使用授权码和 codeVerifier 向 Google 换取 Token
const tokens = await google.validateAuthorizationCode(code, storedCodeVerifier);
// tokens 对象中包含:accessToken, idToken, accessTokenExpiresAt 等
const accessToken = tokens.accessToken();
// 4. 使用 accessToken 调用 Google Userinfo API 获取用户信息
const response = await fetch("https://openidconnect.googleapis.com/v1/userinfo", {
headers: {
Authorization: `Bearer ${accessToken}`
}
});
const googleUser = await response.json() as GoogleUser;
// googleUser 数据格式示例:
// {
// sub: "1234567890", // 用户在 Google 的唯一标识
// name: "张三",
// picture: "https://...",
// email: "zhangsan@gmail.com",
// email_verified: true
// }
// 5. 业务逻辑处理:
// - 检查数据库中是否存在该 googleUser.sub 对应的用户
// - 如果没有,创建新用户
// - 在你的系统里创建会话(Session)并写入 Session Cookie
// - 清理 google_oauth_state 和 google_code_verifier Cookie
return new Response(null, {
status: 302,
headers: {
Location: "/dashboard", // 登录成功,跳转到后台
}
});
} catch (error) {
console.error("OAuth 验证失败:", error);
return new Response("登录验证出错", { status: 500 });
}
}
interface GoogleUser {
sub: string;
name: string;
given_name: string;
family_name: string;
picture: string;
email: string;
email_verified: boolean;
}
6. 日常使用小结与安全建议
- 为什么需要 PKCE (Code Verifier)?
Google 登录现在强制推荐或要求使用 PKCE。
arctic的google.createAuthorizationURL和validateAuthorizationCode默认就设计了传入codeVerifier的参数,这能有效防止授权码被拦截攻击。 - Cookie 的安全性:
保存
state和code_verifier的 Cookie 必须设置为HttpOnly、Secure(生产环境),并且SameSite建议设置为Lax。否则,第三方网站可能会利用你的回调接口发起跨站攻击。 - 过期处理:
保存
state和code_verifier的 Cookie 有效期不宜过长,通常设置为 10 分钟(600秒)即可,超时则让用户重新发起登录。