OAuth 提供者
規則
- 使用授權碼流程搭配 PKCE 處理公開客戶端(SPA、行動應用)—— 絕不使用隱含流程
- 網頁應用程式應在伺服器端進行程式碼交換 —— 客戶端密鑰絕不能離開伺服器
state 參數:產生隨機 state,儲存在 Session/Cookie 中,於回呼時驗證 —— 防止 CSRF 攻擊
- Google OAuth:範圍
openid email profile,使用 id_token 取得使用者資訊
- GitHub OAuth:範圍
read:user user:email,在 https://github.com/login/oauth/access_token 交換程式碼
- Discord OAuth:範圍
identify email,Token 端點位於 https://discord.com/api/oauth2/token
- Token 刷新:在伺服器端儲存
refresh_token,在 access_token 過期前重新整理
- Session 管理:在成功 OAuth 回呼後建立應用程式 Session,不要將 OAuth Token 儲存在 Cookie 中
- 帳號連結:允許使用者透過
accounts 資料表將多個提供者連接到同一個帳號
模式
export async function GET(req: Request) {
const { searchParams } = new URL(req.url);
const code = searchParams.get("code");
const state = searchParams.get("state");
if (state !== cookies().get("oauth_state")?.value) {
return new Response("Invalid state", { status: 400 });
}
const tokens = await exchangeCodeForTokens(code);
const userInfo = await fetchUserInfo(tokens.access_token);
const user = await upsertUser(userInfo);
await createSession(user.id);
return redirect("/dashboard");
}
避免
- 在前端程式碼中儲存客戶端密鑰 —— 務必在伺服器端交換 Token
- 略過
state 參數 —— CSRF 攻擊是真實存在的威脅
- 將原始 OAuth Token 儲存在 Cookie 中 —— 請使用伺服器端 Session
- 在連結提供者時,忘記處理「該電子郵件已有使用者」的情況