如何用Node.js实现OAuth2.0认证流程?

如何用Node.js实现OAuth2.0认证流程?
最新回答
拾柒

2022-05-25 21:36:19

使用Node.js实现OAuth2.0认证流程的核心是通过授权码模式(Authorization Code Flow)与第三方授权服务器交互,完成用户身份验证。以下是分步骤的详细实现方案:

1. 配置OAuth2.0应用信息

在目标平台(如Google、GitHub)注册应用,获取以下关键参数:

  • Client ID:客户端猛键唯一标识
  • Client Secret:客户端密钥(需保密)
  • Redirect URI:授权后回调地址(如
    http://localhost:3000/auth/callback

安全建议:将敏感信息存储在环境变量中,避免硬编码。

# .env 文件示例CLIENT_ID=your_client_idCLIENT_SECRET=your_client_secretREDIRECT_URI=
http://localhost:3000/auth/callback
2. 引导用户授权并获取授权码

用户点击“登录”按钮时,跳转到第三方授权页面。以Google为例:

  • 授权端点
    https://accounts.google.com/o/oauth2/v2/auth
  • 请求参数

    client_id:应用ID

    redirect_uri:回调地址

    response_type=code:表示授权码模式

    scope:请求的权限范围(如 openid email profile)

    state:随机字符串,防止CSRF攻击枝团巧

代码实现

const express = require('express');const app = express();app.get('/auth/google', (req, res) => { const url = new URL('
https://accounts.google.com/o/oauth2/v2/auth'
); url.searchParams.append('client_id', process.env.CLIENT_ID); url.searchParams.append('redirect_uri', process.env.REDIRECT_URI); url.searchParams.append('response_type', 'code'); url.searchParams.append('scope', 'openid email profile'); url.searchParams.append('state', 'random_string'); // 实际项目中应动态生成并校验 res.redirect(url.toString());});3. 接收回调并换取Access Token

用户授权或饥后,第三方服务器会重定向到Redirect URI,并附带code参数。用该code向令牌端点(Token Endpoint)请求access_token。

  • 令牌端点(Google示例):
    https://oauth2.googleapis.com/token
  • 请求方式:POST
  • 参数

    client_id、client_secret

    code:授权码

    grant_type=authorization_code

    redirect_uri:必须与授权时一致

代码实现(使用axios):

const axios = require('axios');app.get('/auth/callback', async (req, res) => { const { code, state } = req.query; if (!code) return res.status(400).send('授权失败'); try { const tokenResponse = await axios.post('
https://oauth2.googleapis.com/token'
, null, { params: { client_id: process.env.CLIENT_ID, client_secret: process.env.CLIENT_SECRET, code, grant_type: 'authorization_code', redirect_uri: process.env.REDIRECT_URI } }); const { access_token, id_token } = tokenResponse.data; // 可选:验证id_token(JWT)获取用户信息 res.send({ access_token, id_token }); // 或存入Session/Cookie } catch (err) { console.error('获取Token失败:', err); res.status(500).send('服务器错误'); }});4. 获取用户信息并完成登录

使用access_token调用资源服务器的API(如Google的userinfo端点)获取用户数据。

  • 用户信息端点(Google示例):
    https://www.googleapis.com/oauth2/v2/userinfo
  • 请求头:Authorization: Bearer ${access_token}

代码实现

app.get('/userinfo', async (req, res) => { const access_token = req.session.access_token; // 从Session中获取 if (!access_token) return res.status(401).send('未登录'); try { const userInfo = await axios.get('
https://www.googleapis.com/oauth2/v2/userinfo'
, { headers: { Authorization: `Bearer ${access_token}` } }); res.json(userInfo.data); // 返回用户信息(如email、name) } catch (err) { res.status(500).send('获取用户信息失败'); }});5. 关键安全注意事项
  1. State参数校验:生成随机state并存储在Session中,回调时校验以防止CSRF攻击。

    // 生成state并存储const state = crypto.randomBytes(16).toString('hex');req.session.state = state;// 回调时校验if (req.query.state !== req.session.state) { return res.status(403).send('状态不匹配');}
  2. Token存储:避免在前端直接存储access_token,建议使用HttpOnly Cookie或Session。

  3. HTTPS:生产环境必须启用HTTPS,防止中间人攻击。

  4. Scope管理:仅请求必要的权限(如email而非full_profile)。

6. 完整流程总结
  1. 用户访问 /auth/google,跳转到Google授权页面。
  2. 用户授权后,Google重定向到 /auth/callback 并附带code。
  3. 服务端用code换取access_token和id_token。
  4. 使用access_token获取用户信息,创建本地会话。
  5. 用户登录成功,可访问受保护资源。

通过以上步骤,Node.js可高效实现OAuth2.0授权码模式。实际项目中可结合框架(如Passport.js)简化流程,但理解底层原理是关键。