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

React应用调用Passport.js+Node.js+Azure AD OAuth2认证接口求助

问题说明

我已经基于Passport.js、Node.js和Azure AD OAuth2实现了后端认证服务,现在想在React应用中调用该认证端点,但不清楚具体的实现逻辑。以下是我尝试的代码,希望得到帮助:


后端代码(app.js)

import express from 'express';
import dotenv from 'dotenv';
import cors from 'cors';
import passport from 'passport';
import AzureAdOAuth2Strategy from 'passport-azure-ad-oauth2';
import jwt from 'jsonwebtoken'; // 补充缺失的JWT依赖导入
import User from './models/User'; // 补充User模型导入(需根据实际路径调整)

const app = express();

dotenv.config();

const Port = process.env.PORT || 3001;

passport.use(
  new AzureAdOAuth2Strategy(
    {
      clientID: process.env.CLIENT_ID,
      clientSecret: process.env.CLIENT_SECRET,
      callbackURL: 'https://www.example.net/auth/azureadoauth2/callback',
      resource: process.env.RESOURCE,
      tenant: 'contoso.onmicrosoft.com',
    },
    function (accessToken, refresh_token, params, profile, done) {
      var waadProfile = profile || jwt.decode(params.id_token, '', true);

      User.findOrCreate({ id: waadProfile.upn }, function (err, user) {
        done(err, user);
      });
    }
  )
);

// 修正CORS中间件配置:允许React应用域名并开启会话凭证
app.use(cors({
  origin: 'http://localhost:3000', // 替换为你的React应用实际域名
  credentials: true
}));

// 初始化Passport并启用会话支持
app.use(passport.initialize());
app.use(passport.session());

// 序列化用户到会话
passport.serializeUser((user, done) => {
  done(null, user.id);
});

// 从会话反序列化用户
passport.deserializeUser((id, done) => {
  User.findById(id, (err, user) => {
    done(err, user);
  });
});

// 认证路由
app.get('/auth/azureadoauth2', passport.authenticate('azure_ad_oauth2'));

app.get(
  '/auth/azureadoauth2/callback',
  passport.authenticate('azure_ad_oauth2', { failureRedirect: '/login' }),
  function (req, res) {
    // 认证成功后重定向到React应用页面
    res.redirect('http://localhost:3000/dashboard'); // 替换为你的React应用首页/仪表盘地址
  }
);

// 新增接口:供React获取当前登录用户信息
app.get('/api/user', (req, res) => {
  if (req.isAuthenticated()) {
    res.json(req.user);
  } else {
    res.status(401).json({ message: '未授权' });
  }
});

app.get('/', (req, res) => {
  res.send('App is running successfully');
});

app.listen(Port, () => {
  console.log(`Server is listening on ${Port}`);
});

前端代码(Login.js)

function Login() {
  const handleLogin = () => {
    // OAuth2授权码流程需通过浏览器重定向到后端认证端点,无需fetch
    window.location.href = 'http://localhost:4000/auth/azureadoauth2';
  };

  return <button onClick={handleLogin}>登录(Azure AD)</button>;
}

export default Login;

关键修正说明

  • 后端CORS配置:原代码app.use(express(cors))用法错误,需直接调用cors()并指定允许的React域名,同时开启credentials以保持会话。
  • Passport会话支持:必须添加passport.initialize()、passport.session()以及序列化/反序列化逻辑,否则认证成功后无法在后续请求中识别用户。
  • 缺失依赖补充:原代码使用了jwt和User模型但未导入,需补充对应语句。
  • 前端登录逻辑:用fetch调用认证端点不符合OAuth2流程,应直接通过window.location.href跳转到后端认证路由,触发Azure AD的授权页面。
  • 回调重定向调整:后端回调路由需将用户重定向回React应用,而不是后端自身的根路径。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 05:25:33