首先实现授权码流程,通过OAuth2orize处理授权请求与令牌发放,结合Passport进行用户认证;接着配置客户端认证与会话管理,最后提供登录及授权确认页面,完成标准OAuth2授权码流程。

实现一个支持 OAuth2 的授权服务器,核心是处理授权码流程、令牌发放、客户端认证和用户身份验证。Node.js 结合 OAuth2orize 和 Passport 是常见选择。下面是一个基础但完整的实现思路和代码示例。
1. 初始化项目并安装依赖
创建项目目录并安装必要模块:
npm init -y
npm install express oauth2orize passport passport-local bcrypt body-parser cookie-session
这些库的作用:
express:构建 Web 服务oauth2orize:实现 OAuth2 授权服务器逻辑passport + passport-local:处理用户登录认证body-parser:解析请求体cookie-session:管理会话(用于登录状态)bcrypt:密码加密
2. 配置 OAuth2orize 授权服务器
创建 server.js,初始化 Express 和 OAuth2orize:
const express = require('express');const oauth2orize = require('oauth2orize');const bodyParser = require('body-parser');const session = require('cookie-session');const passport = require('passport');const LocalStrategy = require('passport-local').Strategy;const bcrypt = require('bcrypt');const app = express();const server = oauth2orize.createServer();// 中间件app.use(bodyParser.urlencoded({ extended: true }));app.use(bodyParser.json());app.use(session({ secret: 'your-session-secret', maxAge: 3600000 }));app.use(passport.initialize());app.use(passport.session());// 模拟数据存储(生产环境应使用数据库)const clients = [ { id: 'client_id_123', secret: 'client_secret_456', redirectUri: 'http://localhost:3000/callback' }];const tokens = [];const codes = [];const users = [{ id: 1, username: 'user', password: '$2b$10$...' }]; // 密码哈希// Passport 用户本地认证passport.use(new LocalStrategy((username, password, done) => { const user = users.find(u => u.username === username); if (user && bcrypt.compareSync(password, user.password)) { return done(null, user); } return done(null, false);}));passport.serializeUser((user, done) => done(null, user.id));passport.deserializeUser((id, done) => { const user = users.find(u => u.id === id); done(null, user);});
3. 实现 OAuth2 授权端点
配置授权码(authorization code)流程:
// 生成授权码server.grant(oauth2orize.grant.code((client, redirectUri, user, ares, done) => { const code = Math.random().toString(36).substr(2, 8); codes.push({ value: code, clientId: client.id, redirectUri: redirectUri, userId: user.id }); done(null, code);}));// 交换令牌server.exchange(oauth2orize.exchange.code((client, code, redirectUri, done) => { const authCode = codes.find(c => c.value === code); if (!authCode) return done(null, false); if (client.id !== authCode.clientId) return done(null, false); if (redirectUri !== authCode.redirectUri) return done(null, false); const token = Math.random().toString(36).substr(2, 24); tokens.push({ value: token, userId: authCode.userId, clientId: client.id }); done(null, token);}));// 授权中间件:检查客户端合法性function authenticateClient(req, res, next) { const clientId = req.body.client_id || req.query.client_id; const clientSecret = req.body.client_secret; const client = clients.find(c => c.id === clientId && c.secret === clientSecret); if (!client) return res.status(401).json({ error: 'Invalid client' }); req.oauth2 = { client }; next();}// GET /authorize - 用户确认授权页面app.get('/authorize', server.authorize((clientId, redirectUri, done) => { const client = clients.find(c => c.id === clientId); if (!client) return done(new Error('Unknown client')); if (client.redirectUri !== redirectUri) return done(new Error('Invalid redirect URI')); return done(null, client, redirectUri);}), (req, res) => { res.render('dialog', { transactionID: req.oauth2.transactionID, user: req.user, client: req.oauth2.client });});// POST /authorize/decision - 处理用户同意/拒绝app.post('/authorize/decision', server.decision());// POST /token - 获取访问令牌app.post('/token', authenticateClient, server.token(), server.errorHandler());
4. 用户登录与授权确认页面
添加简单视图(可用模板引擎如 EJS 或直接返回 HTML):
app.get('/login', (req, res) => { res.send(`
`);});app.post('/login', passport.authenticate('local', { failureRedirect: '/login' }), (req, res) => { // 登录成功后重定向到授权确认页 res.redirect('/authorize?client_id=' + req.query.client_id + '&response_type=code&redirect_uri=' + encodeURIComponent(req.query.redirect_uri));});
5. 启动服务器
“`javascriptapp.listen(3000, () => { console.log(‘OAuth2 授权服务器运行在 http://localhost:3000’);});“`
基本上就这些。这个例子实现了标准的授权码流程:
客户端跳转到 /authorize 请求授权用户登录并确认授权服务器返回授权码客户端用授权码请求 /token 换取访问令牌
注意:这只是一个教学示例。生产环境需要加入更多安全措施,比如 HTTPS、CSRF 防护、刷新令牌、令牌过期、数据库持久化、PKCE 扩展等。
以上就是如何用Node.js实现一个支持OAuth2的授权服务器?的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1526514.html
微信扫一扫
支付宝扫一扫