如何解决 Node.js 和 React App 中 Microsoft OAuth2 授权请求的 CORS 策略块

问题描述 投票:0回答:1

我有一个带有 NodeJS 后端和 React 前端的应用程序,我想为其实现 Azure SSO。由于前端是由后端提供服务的,因此想要登录应用程序的用户会被后端重定向到前端的登录页面。当用户单击登录页面上的相关按钮时,应打开 Azure 身份验证页面,登录后应将他们重定向回我的应用程序。但是,我在 API 端收到错误,如下所示。

访问 XMLHttpRequest 'https://login.microsoftonline.com/xxx/oauth2/v2.0/authorize?client_id={clientid}1&response_type=code&redirect_uri=http:%2F%2Flocalhost:3000%2Fauth%2Fcallback&response_mode=query&scope= https:%2F%2Fgraph.microsoft.com%2F.default+offline_access'(从'http://localhost:3000/api/auth/sso-login'重定向)来自原点'http://localhost:3000' 已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头

我的API代码是

const params = new URLSearchParams({
    client_id: CLIENT_ID,
    response_type: 'code',
    redirect_uri: REDIRECT_URI,
    response_mode: 'query',
    scope: 'https://graph.microsoft.com/.default offline_access'
  });

  res.redirect(`${authorizeUrl}?${params.toString()}`);

我创建了一个简单的nodejs应用程序,具有相同的逻辑,没有前端,它工作没有问题。

app.get('/login', (req, res) => {
  const params = new URLSearchParams({
    client_id: CLIENT_ID,
    response_type: 'code',
    redirect_uri: REDIRECT_URI,
    response_mode: 'query',
    scope: 'https://graph.microsoft.com/.default offline_access'
  });

  res.redirect(`${authorizeUrl}?${params.toString()}`);
});

app.get('/auth/callback', async (req, res) => {
  const { code } = req.query;

  if (!code) {
    return res.status(400).send('Authorization code not found.');
  }

  try {
    const response = await axios.post(tokenUrl, new URLSearchParams({
      client_id: CLIENT_ID,
      scope: 'https://graph.microsoft.com/.default',
      code,
      redirect_uri: REDIRECT_URI,
      grant_type: 'authorization_code',
      client_secret: CLIENT_SECRET
    }));

    const accessToken = response.data.access_token;
    res.send(`Access Token: ${accessToken}`);
  } catch (error) {
    res.status(500).send(`Error exchanging code: ${error.message}`);
  }
});```
 
azure single-sign-on azure-ad-msal msal.js
1个回答
0
投票

我通过将 CORS 添加到后端 (Node.js) 代码解决了该问题。现在,想要登录应用程序的用户已成功被后端重定向到前端的登录页面,并检索了访问令牌。

这是 GitHub 存储库中的完整代码。

后端/index.js :

const express = require('express');
const axios = require('axios');
const cors = require('cors');
const dotenv = require('dotenv');

dotenv.config();

const app = express();
app.use(cors());
app.use(express.json());
const tokenUrl = `https://login.microsoftonline.com/${process.env.TENANT_ID}/oauth2/v2.0/token`;

app.get('/api/auth/sso-login', (req, res) => {
  const params = new URLSearchParams({
    client_id: process.env.CLIENT_ID,
    response_type: 'code',
    redirect_uri: process.env.REDIRECT_URI,
    response_mode: 'query',
    scope: 'https://graph.microsoft.com/.default offline_access',
  });

  const loginUrl = `https://login.microsoftonline.com/${process.env.TENANT_ID}/oauth2/v2.0/authorize?${params.toString()}`;
  res.redirect(loginUrl);
});

app.post('/api/auth/exchange-token', async (req, res) => {
  const { code } = req.body;
  if (!code) {
    return res.status(400).json({ error: 'Authorization code not provided' });
  }
  try {
    const response = await axios.post(tokenUrl, new URLSearchParams({
      client_id: process.env.CLIENT_ID,
      scope: 'https://graph.microsoft.com/.default',
      code,
      redirect_uri: process.env.REDIRECT_URI,
      grant_type: 'authorization_code',
      client_secret: process.env.CLIENT_SECRET,
    }));
    const accessToken = response.data.access_token;
    res.json({ accessToken });
  } catch (error) {
    res.status(500).json({ error: `Error exchanging code: ${error.message}` });
  }
});

const PORT = 4000;
app.listen(PORT, () => {
  console.log(`Backend running on http://localhost:${PORT}`);
});

.env:

CLIENT_ID=<Client_ID>
CLIENT_SECRET=<Client_Secret>
TENANT_ID=<tenant_ID>
REDIRECT_URI=http://localhost:3000/auth/callback

前端/Login.js :

import React from 'react';

const Login = () => {
  const handleLogin = () => {
    window.location.href = `${process.env.REACT_APP_BACKEND_URL}/api/auth/sso-login`;
  };
  return (
    <div>
      <h2>Login Page</h2>
      <button onClick={handleLogin}>Login with Azure</button>
    </div>
  );
};
export default Login;

前端/.env:

REACT_APP_CLIENT_ID=<client_ID>
REACT_APP_TENANT_ID=<tenant_ID>
REACT_APP_REDIRECT_URI=http://localhost:3000/auth/callback
REACT_APP_BACKEND_URL=http://localhost:4000

我已在 Azure AD 应用程序的重定向 URI 中的 Web 下添加了以下 URL,如下所示。

http://localhost:3000/auth/callback

enter image description here

后端输出:

我成功运行了后端(Node.js)应用程序。当我在浏览器中打开下面的 URL 时,它会将我重定向到登录页面,然后我使用我的帐户登录,如下所示:

http://localhost:4000/api/auth/sso-login

enter image description here

登录后,我收到了授权码,如下图:

enter image description here

我复制了授权码并在POST请求中使用它,如下所示。

enter image description here

我使用 authorization_code 发送了 POST 请求并收到了 访问令牌,如下所示。

http://localhost:4000/api/auth/exchange-token
{
  "code": "<authorization_code>"
}

enter image description here

前端输出:

我成功运行了前端 (React.js) 应用程序并使用 Login with Azure 按钮登录。

enter image description here

enter image description here

登录后,我检索到了访问令牌,如下所示。

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.