You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

新手求教:基于Node.js、MongoDB和Express实现Passport OAuth2认证REST API

使用Passport OAuth2为Node.js + Express + MongoDB REST API实现认证的分步指南

嘿,作为Node.js新手,用Passport OAuth2给REST API做认证确实得一步步来,我给你整理了超详细的实操步骤,跟着做应该能顺利搞定!

1. 初始化项目并安装依赖

首先咱们搭好基础环境,打开终端创建项目文件夹,然后初始化:

mkdir oauth2-api-auth && cd oauth2-api-auth
npm init -y

接下来安装核心依赖,包括Express、MongoDB驱动、Passport和OAuth2策略,还有环境变量管理和跨域支持:

npm install express mongoose passport passport-oauth2 dotenv cors jsonwebtoken

再装个开发依赖方便热重载:

npm install -D nodemon

记得在package.json里加个启动脚本:

"scripts": {
  "start": "node server.js",
  "dev": "nodemon server.js"
}

2. 搭建项目结构

咱们把文件分模块放,结构清晰好维护:

oauth2-api-auth/
├── config/          # 配置文件
│   ├── db.js        # MongoDB连接配置
│   └── passport.js  # Passport OAuth2策略配置
├── models/          # 数据模型
│   └── User.js      # 用户模型
├── routes/          # 路由文件
│   ├── auth.js      # 认证相关路由
│   └── api.js       # 受保护的API路由
├── .env             # 环境变量
└── server.js        # 服务器入口文件

3. 配置MongoDB连接

在config/db.js里写MongoDB的连接逻辑,用Mongoose来操作数据库:

const mongoose = require('mongoose');
require('dotenv').config();

const connectDB = async () => {
  try {
    await mongoose.connect(process.env.MONGODB_URI);
    console.log('MongoDB连接成功!');
  } catch (err) {
    console.error('MongoDB连接失败:', err.message);
    process.exit(1);
  }
};

module.exports = connectDB;

4. 创建用户数据模型

在models/User.js里定义用户Schema,存储OAuth2提供商返回的用户信息:

const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
  oauthId: {
    type: String,
    required: true,
    unique: true
  },
  provider: {
    type: String,
    required: true,
    enum: ['github', 'google', 'custom'] // 根据你的提供商调整
  },
  email: {
    type: String,
    required: true,
    unique: true
  },
  displayName: {
    type: String,
    required: true
  }
}, { timestamps: true });

module.exports = mongoose.model('User', userSchema);

5. 配置Passport OAuth2策略

这是核心步骤,在config/passport.js里设置OAuth2的认证逻辑:

const passport = require('passport');
const OAuth2Strategy = require('passport-oauth2').Strategy;
const User = require('../models/User');
const jwt = require('jsonwebtoken');
require('dotenv').config();

// 配置OAuth2策略
passport.use(new OAuth2Strategy({
  authorizationURL: process.env.OAUTH2_AUTH_URL, // 提供商的授权地址(比如GitHub的https://github.com/login/oauth/authorize)
  tokenURL: process.env.OAUTH2_TOKEN_URL, // 提供商的令牌地址(比如GitHub的https://github.com/login/oauth/access_token)
  clientID: process.env.OAUTH2_CLIENT_ID, // 你的客户端ID(从提供商后台获取)
  clientSecret: process.env.OAUTH2_CLIENT_SECRET, // 你的客户端密钥
  callbackURL: process.env.OAUTH2_CALLBACK_URL // 回调地址(要和提供商后台配置的一致)
}, async (accessToken, refreshToken, profile, done) => {
  try {
    // 先查找是否已有该用户
    let user = await User.findOne({ oauthId: profile.id, provider: process.env.OAUTH2_PROVIDER });
    
    if (!user) {
      // 没有的话创建新用户
      user = await User.create({
        oauthId: profile.id,
        provider: process.env.OAUTH2_PROVIDER,
        email: profile.emails[0].value,
        displayName: profile.displayName
      });
    }
    
    // 生成JWT令牌(REST API常用无状态认证)
    const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET, { expiresIn: '7d' });
    
    // 把用户和token传给回调
    done(null, { user, token });
  } catch (err) {
    done(err, null);
  }
}));

// 序列化用户(REST API用JWT的话,这里可以简化)
passport.serializeUser((user, done) => {
  done(null, user.id);
});

// 反序列化用户
passport.deserializeUser(async (id, done) => {
  try {
    const user = await User.findById(id);
    done(null, user);
  } catch (err) {
    done(err, null);
  }
});

module.exports = passport;

6. 启动Express服务器并配置中间件

在server.js里整合所有配置,启动服务器:

const express = require('express');
const connectDB = require('./config/db');
const passport = require('./config/passport');
const cors = require('cors');
require('dotenv').config();

// 初始化Express
const app = express();

// 连接数据库
connectDB();

// 配置中间件
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// 初始化Passport
app.use(passport.initialize());
app.use(passport.session()); // 如果用session的话开启,REST API用JWT可以注释,但回调路由需要session暂存状态

// 挂载路由
app.use('/auth', require('./routes/auth'));
app.use('/api', require('./routes/api'));

// 启动服务器
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
  console.log(`服务器运行在端口${PORT}`);
});

7. 创建认证路由

在routes/auth.js里写OAuth2的授权、回调和退出路由:

const express = require('express');
const router = express.Router();
const passport = require('../config/passport');

// 跳转到OAuth2提供商的授权页面
router.get('/oauth2', passport.authenticate('oauth2'));

// 授权后的回调路由
router.get('/oauth2/callback', 
  passport.authenticate('oauth2', { failureRedirect: '/auth/failure' }),
  (req, res) => {
    // 授权成功,返回JWT令牌给客户端(可以重定向到前端页面,把token作为参数传递)
    res.json({ 
      success: true,
      token: req.user.token,
      user: {
        id: req.user.user._id,
        email: req.user.user.email,
        displayName: req.user.user.displayName
      }
    });
  }
);

// 授权失败的路由
router.get('/failure', (req, res) => {
  res.json({ success: false, message: '认证失败' });
});

// 退出登录
router.get('/logout', (req, res) => {
  req.logout((err) => {
    if (err) return res.status(500).json({ success: false, message: '退出失败' });
    res.json({ success: true, message: '已退出登录' });
  });
});

module.exports = router;

8. 创建受保护的API路由

在routes/api.js里写需要认证才能访问的接口,用Passport中间件保护:

const express = require('express');
const router = express.Router();
const passport = require('../config/passport');

// 受保护的用户信息接口
router.get('/profile', passport.authenticate('oauth2', { session: false }), (req, res) => {
  res.json({
    success: true,
    user: {
      id: req.user._id,
      email: req.user.email,
      displayName: req.user.displayName,
      provider: req.user.provider
    }
  });
});

module.exports = router;

9. 配置环境变量

在.env文件里填写你的配置信息,记得替换成自己的实际值:

PORT=5000
MONGODB_URI=mongodb://localhost:27017/oauth2-auth-db
# OAuth2提供商配置(以GitHub为例)
OAUTH2_PROVIDER=github
OAUTH2_AUTH_URL=https://github.com/login/oauth/authorize
OAUTH2_TOKEN_URL=https://github.com/login/oauth/access_token
OAUTH2_CLIENT_ID=你的GitHub客户端ID
OAUTH2_CLIENT_SECRET=你的GitHub客户端密钥
OAUTH2_CALLBACK_URL=http://localhost:5000/auth/oauth2/callback
JWT_SECRET=你的JWT密钥(随便写个长字符串)

10. 测试认证流程

  1. 启动开发服务器:npm run dev
  2. 打开浏览器访问http://localhost:5000/auth/oauth2,会跳转到OAuth2提供商的授权页面
  3. 授权成功后,会返回包含JWT令牌的JSON响应
  4. 用Postman或者curl访问http://localhost:5000/api/profile,在请求头里添加Authorization: Bearer <你的JWT令牌>,就能获取到用户信息了

一些重要提醒

  • 一定要在OAuth2提供商的后台(比如GitHub Developer Settings)配置好回调地址,必须和OAUTH2_CALLBACK_URL完全一致
  • 如果是生产环境,记得把NODE_ENV设为production,并且不要把.env文件提交到版本库
  • 如果不需要session,可以注释掉app.use(passport.session()),但回调路由可能需要调整状态存储方式
  • 可以根据需要扩展用户模型,添加更多字段比如头像地址等

内容的提问来源于stack exchange,提问作者Rajeev Varshney

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:20:16