我正在尝试访问代码以将其发送到后端,以使用 Microsoft 图形 API 和 msal 浏览器获取 Microsoft 帐户的访问令牌和刷新令牌。这是我的代码
const authorizeEmail = async (idToken: string | undefined) => {
if (!idToken) {
return;
}
const token = await getIdTokenClaims();
await axios.post(
`${process.env.BASE_URL}/email/authorize/`,
{
code: idToken,
deal_id: 22,
},
{
headers: {
'Content-Type': 'application/json',
"Authorization": `Bearer ${token}`,
},
}
);
};
const loginAndGetAuthorizationCode = async () => {
const loginRequest = {
scopes: ["User.Read", "Mail.Read", "offline_access"]
};
try {
const loginResponse = await msalInstance.loginPopup(loginRequest);
await authorizeEmail(loginResponse.code); // this is coming undefined
return loginResponse.code;
} catch (error) {
console.error("Login failed: ", error);
}
};
问题在于,MSAL.js 中的
loginResponse
不会在 React 等客户端应用程序中返回授权代码。相反,它直接提供 idToken
和 accessToken
。
我注册了一个 Azure AD 应用程序并添加了相同的
API permissions
,如下所示:
在“身份验证”选项卡中,我在“单页应用程序”平台中添加了重定向 URI 作为 http://localhost:3000,并启用了公共客户端流程,如下所示:
就我而言,我使用以下代码文件并成功获取登录用户的令牌和电子邮件,如下所示:
authConfig.js:
// src/authConfig.js
export const msalConfig = {
auth: {
clientId: "appId", // Application (client) ID
authority: "https://login.microsoftonline.com/tenantId", // Directory (tenant) ID
redirectUri: "http://localhost:3000", // Your redirect URI
},
};
export const loginRequest = {
scopes: ["User.Read", "Mail.Read", "offline_access"], // Adjust scopes as needed
};
// src/App.js
import React, { useEffect, useState } from "react";
import { msalConfig, loginRequest } from "./authConfig";
import { PublicClientApplication } from "@azure/msal-browser";
import axios from "axios";
const msalInstance = new PublicClientApplication(msalConfig);
const App = () => {
const [accessToken, setAccessToken] = useState("");
const [idToken, setIdToken] = useState("");
const [messages, setMessages] = useState([]);
const [userName, setUserName] = useState("");
// Initialize MSAL on app load
useEffect(() => {
const initializeMSAL = async () => {
try {
await msalInstance.initialize();
console.log("MSAL initialized successfully");
} catch (error) {
console.error("MSAL initialization failed: ", error);
}
};
initializeMSAL();
}, []);
const loginAndGetToken = async () => {
try {
const loginResponse = await msalInstance.loginPopup(loginRequest);
console.log("Login successful!", loginResponse);
// Set the active account after successful login
msalInstance.setActiveAccount(loginResponse.account);
// Access tokens and ID token
const newAccessToken = loginResponse.accessToken;
const newIdToken = loginResponse.idToken; // Get the ID token
setAccessToken(newAccessToken);
setIdToken(newIdToken);
setUserName(loginResponse.account.name);
await callGraphAPI(newAccessToken);
} catch (error) {
console.error("Login failed: ", error);
alert(`Login failed: ${error.message}`);
}
};
const callGraphAPI = async (token) => {
try {
const response = await axios.get("https://graph.microsoft.com/v1.0/me/messages", {
headers: {
Authorization: `Bearer ${token}`,
},
});
console.log("Graph API Response:", response.data);
setMessages(response.data.value);
} catch (error) {
console.error("Graph API call failed:", error);
}
};
const logout = () => {
msalInstance.logoutPopup();
};
return (
<div>
<h1>MSAL Login</h1>
{!accessToken ? (
<button onClick={loginAndGetToken}>Login</button>
) : (
<div>
<h2>Logged in as: {userName}</h2> {/* Display user's name */}
<button onClick={logout}>Logout</button>
</div>
)}
{accessToken && (
<div>
<h2>Access Token:</h2>
<p>{accessToken}</p>
</div>
)}
{idToken && (
<div>
<h2>ID Token:</h2>
<p>{idToken}</p>
</div>
)}
{messages.length > 0 && (
<div>
<h2>Messages:</h2>
<ul>
{messages.map((message) => (
<li key={message.id}>
<strong>{message.subject}</strong> - {message.bodyPreview}
</li>
))}
</ul>
</div>
)}
</div>
);
};
export default App;