簡體   English   中英

如何解決我的 MERN 應用程序中的 Access-Control-Allow-Origin CORS 錯誤以進行 MSAL 身份驗證?

[英]How can I solve the Access-Control-Allow-Origin CORS error in my MERN app for MSAL auth?

我正在嘗試通過單擊按鈕在我的 MERN 應用程序中通過 MSAL 進行身份驗證。

但是我收到此錯誤:

從 origin 訪問“https://login.microsoftonline.com/common/oauth2/v2.0/a...”處的 XMLHttpRequest(重定向自“http://<SERVER_URL>/api/auth/signin”) http://<CLIENT_URL>' 已被 CORS 策略阻止:請求的資源上不存在“Access-Control-Allow-Origin”header。

這是我的 NodeJS 服務器的代碼:

const express = require("express");
const session = require('express-session');
const authRoutes = require("./routes/auth.routes");
const msal = require('@azure/msal-node');
const cors = require("cors");
require("dotenv").config();

const app = express();
const corsOptions = {
    origin : process.env.CLIENT_URL,
    credentials: true,
    "allowedHeaders": ["sessionId", "Content-Type"],
    "exposedHeaders": ["sessionId"],
    "methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
    "preflightContinue": false
}
app.use(cors(corsOptions));


// Demo only
app.locals.users = {};

// MSAL Config
const msalConfig = {
    auth: {
        clientId: process.env.OAUTH_APP_ID,
        authority: process.env.OAUTH_AUTHORITY,
        clientSecret: process.env.OAUTH_APP_SECRET
    },
    system: {
        loggerOptions: {
            loggerCallback(loglevel, message, containsPii) {
                console.log(message);
            },
            piiLoggingEnabled: false,
            logLevel: msal.LogLevel.Verbose,
        }
    }
};

app.locals.msalClient = new msal.ConfidentialClientApplication(msalConfig);

// Session middleware
app.use(session({
secret: 'your_secret_value_here',
resave: false,
saveUninitialized: false,
unset: 'destroy'
}));

app.use("/api/auth", authRoutes);

app.get("/", (req, res) => {
    res.send("Hello World!");
});

app.listen(process.env.PORT, () => {
    console.log(`Server is running on port ${process.env.PORT}`);
});

module.exports = app;

這是我的 auth.controller 方法:

module.exports = {
    signIn: async (req, res) => {
        const urlParameters = {
            scopes: process.env.OAUTH_SCOPES.split(','),
            redirectUri: process.env.OAUTH_REDIRECT_URI
        };
    
        try {
            const authUrl = await req.app.locals.msalClient.getAuthCodeUrl(urlParameters);
            res.redirect(authUrl);
        } catch (error) {
            console.log(`Error: ${error}`);
            res.redirect("/");
        }
    },

    callback: async (req, res) => {
        const tokenRequest = {
            code: req.query.code,
            scopes: process.env.OAUTH_SCOPES.split(","),
            redirectUri: process.env.OAUTH_REDIRECT_URI
        };
    
        try {
            const response = await req.app.locals.msalClient.acquireTokenByCode(tokenRequest);
            req.session.userId = response.account.homeAccountId;
    
            const user = await graph.getUserDetails(response.accessToken);
            req.app.locals.users[req.session.userId] = {
                displayName: user.displayName,
                email: user.mail || user.userPrincipalName,
                timeZone: user.mailboxSettings.timeZone
            };
        } catch (error) {
            console.log(`Error: ${error}`);
        }
        
        res.redirect("/");
    },

    signOut: async (req, res) => {
        if (req.session.userId) {
            const accounts = await req.app.locals.msalClient.getTokenCache().getAllAccounts();
            const userAccount = accounts.find(a => a.homeAccountId === req.session.userId);
    
            if (userAccount) {
                req.app.locals.msalClient.getTokenCache().removeAccount(userAccount);
            }
        }
    
        req.session.destroy(err => res.redirect("/"));
    }
};

這是 React 部分:

import React from 'react';
import axios from "axios";

const App = () => {
    const handleConnect = () => {
        axios({
            method: "get",
            url: `${process.env.SERVER_URL}/api/auth/signin`,
            withCredentials: true
        })
        .then(res => console.log(res.data))
        .catch(err => console.log(err));
    };

    return (
        <button onClick={handleConnect}>Connect</button>
    );
};

export default App;

在我的 Azure Active Directory 管理中心中,我的重定向 URI 是:

  • “<CLIENT_URL>”作為“SPA”
  • “<SERVER_URL>/api/auth/signin”為“Web”

devtools 中的 Network 選項卡有助於解決此類問題。

您可能需要處理CORS 預檢請求,方法是在您的快速應用程序中放置類似的內容來處理 OPTIONS 請求。

app.options('*',cors())

將此行放在任何路由的app.use()之前。

這一點我在生產中。 哎喲!

Access-Control-Allow-Origin設置為*非常危險,不推薦。 這意味着您允許任何來源從您的服務器接收響應。

刪除 CORS 意味着將執行同源策略,因此它將不起作用。

要解決客戶端和服務器之間的問題,您可以在 React 應用程序的package.json文件中設置一個代理,該代理將指向您的服務器: "proxy": "YourServerURI"

關於 MSAL 錯誤的最初問題,我建議仔細檢查您的應用程序是否已正確注冊並有權訪問您的服務器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM