JavaScript OAuth2.0认证授权流程

JavaScript OAuth2.0认证授权流程
最新回答
逼啵逼啵

2021-05-18 19:04:20

JavaScript 中 OAuth2.0 认证授权流程(授权码模式 + PKCE)的核心步骤如下

1. 生成 Code Verifier 和 Code Challenge
  • Code Verifier:前端生成一个高强度随机字符串(如 43-128 字符的 Base64 URL 安全编码字符串),用于后续验证。
  • Code Challenge:对 Code Verifier 进行 SHA-256 哈希计算,再将结果进行 Base64 URL 编码,生成 Code Challenge。示例代码:function generateCodeVerifier() { const array = new Uint8Array(32); window.crypto.getRandomValues(array); return btoa(String.fromCharCode.apply(null, array)) .replace(/+/g, '-') .replace(///g, '_') .replace(/=+$/, '');}function generateCodeChallenge(verifier) { const hashBuffer = await window.crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier)); const hashArray = Array.from(new Uint8Array(hashBuffer)); return btoa(String.fromCharCode.apply(null, hashArray)) .replace(/+/g, '-') .replace(///g, '_') .replace(/=+$/, '');}
2. 构造授权 URL 并跳转
  • 前端将用户重定向至第三方授权服务器,携带以下参数:

    response_type=code:指定使用授权码模式。

    client_id:应用注册时分配的客户端 ID。

    redirect_uri:授权完成后回调的地址(需与注册时一致)。

    scope:请求的权限范围(如 read profile)。

    state:随机字符串,用于防止 CSRF 攻击(回调时需校验一致性)。

    code_challenge 和 code_challenge_method=S256:PKCE 相关参数。示例 URL

    https://auth.example.com/authorize?
    response_type=code &client_id=your_client_id &redirect_uri=
    https://yourapp.com/callback
    &scope=read%20profile &state=random_string &code_challenge=generated_code_challenge &code_challenge_method=S256
3. 用户登录并授权
  • 用户在第三方平台输入账号密码并同意授权后,授权服务器将用户重定向回 redirect_uri,并附带 code(授权码)和 state。示例回调 URL
    https://yourapp.com/callback?code=auth_code&state=returned_state
  • 安全校验:前端需验证 state 是否与跳转前一致,防止中间人攻击。
4. 使用授权码换取 Access Token
  • 场景 1:有后端服务前端将 code 发送至自己的后端,由后端携带 client_secret 和 code_verifier 向授权服务器请求 Token(避免暴露敏感信息)。后端请求示例

    POST /token HTTP/1.1Content-Type: application/x-www-form-urlencodedgrant_type=authorization_code&client_id=your_client_id&client_secret=your_client_secret&redirect_uri=
    https://yourapp.com/callback&code=auth_code&code_verifier=original_code_verifier
  • 场景 2:无后端(公开客户端)某些平台(如 Auth0、Firebase)支持前端直接请求 Token,但需提供 code_verifier。前端请求示例

    fetch('
    https://auth.example.com/token'
    , { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ grant_type: 'authorization_code', client_id: 'your_client_id', redirect_uri: '
    https://yourapp.com/callback'
    , code: 'auth_code', code_verifier: 'original_code_verifier' })});
  • 响应结果:授权服务器验证 code_verifier 与 code_challenge 匹配后,返回 access_token 和可选的 refresh_token。

5. 使用 Access Token 调用 API
  • 前端在请求头中携带 Token 访问受保护资源:fetch('
    https://api.example.com/user'
    , { headers: { 'Authorization': 'Bearer ' + accessToken }});
安全注意事项
  • Token 存储

    避免在 URL、localStorage 或 sessionStorage 中存储 access_token(易受 XSS 攻击)。

    推荐存储在内存或由后端设置的 HttpOnly Cookie 中。

  • State 校验:始终验证回调中的 state 是否与跳转前一致。
  • Code Verifier 生命周期:code_verifier 必须一次性使用且生命周期短。
  • 日志安全:避免在日志中记录 access_token 或 code。
简化实现建议
  • 使用成熟库

    Auth0.js / @auth0/auth0-spa-js:专为 SPA 设计,内置 PKCE 支持。

    Okta Auth JS:支持多种身份提供商。

    simple-oauth2(Node.js):适合前后端协作场景。

  • 示例(Auth0):import createAuth0Client from '@auth0/auth0-spa-js';const auth0 = await createAuth0Client({ domain: 'your-domain.auth0.com', client_id: 'your_client_id', redirect_uri: window.location.origin});// 登录并获取 Tokenawait auth0.loginWithRedirect({ redirect_uri: window.location.origin });// 回调中处理 Tokenconst token = await auth0.getTokenSilently();

总结:JavaScript 中 OAuth2.0 的核心流程为 前端生成 PKCE 参数 → 跳转授权 → 校验 state → 后端(或可信服务)换取 Token → 前端使用 Token 访问 API。全程需严格遵循安全规范,推荐使用成熟库简化实现。