構成イメージ
React SPA
↓
↓ 認可コードフロー(PKCE)
↓
Microsoft Entra ID
↓
↓ Access Token
↓
Microsoft Graph
作成手順
1.Entra ID 側設定
アプリの登録
名前 : spa-demo
Supported account types : Accounts in this organizational directory only
Redirect URI :
プラットフォーム : Single-page application (SPA)
URI : http://localhost:5173
※CRAの場合 URI : http://localhost:3000
API Permissions 委任(ユーザー同意)
Microsoft Graph – User.Read
2.プロジェクト作成
npm create vite@latest spa-demo — –template react
cd spa-demo
npm install
npm install @azure/msal-browser @azure/msal-react
※CRAの場合
npx create-react-app spa-demo
cd spa-demo
npm install @azure/msal-browser @azure/msal-react
3.ディレクトリ構成
src/
├─ main.jsx
├─ App.jsx
└─ authConfig.js
4.authConfig.js
export const msalConfig = {
auth: {
clientId: import.meta.env.VITE_CLIENT_ID,
authority: `https://login.microsoftonline.com/${import.meta.env.VITE_TENANT_ID}`,
redirectUri: "http://localhost:5173"
}
};
export const loginRequest = {
scopes: ["User.Read"]
};
5.main.jsx
import React from "react";
import ReactDOM from "react-dom/client";
import { PublicClientApplication } from "@azure/msal-browser";
import { MsalProvider } from "@azure/msal-react";
import App from "./App";
import { msalConfig } from "./authConfig";
const msalInstance =
new PublicClientApplication(msalConfig);
ReactDOM.createRoot(document.getElementById("root")).render(
<React.StrictMode>
<MsalProvider instance={msalInstance}>
<App />
</MsalProvider>
</React.StrictMode>
);
6.App.js
import React, { useState } from "react";
import { useMsal } from "@azure/msal-react";
import { loginRequest } from "./authConfig";
function App() {
const { instance, accounts } = useMsal();
const [userInfo, setUserInfo] = useState(null);
const signIn = async () => {
try {
await instance.loginPopup(loginRequest);
} catch (error) {
console.error(error);
}
};
const getProfile = async () => {
try {
const response =
await instance.acquireTokenSilent({
...loginRequest,
account: accounts[0]
});
const graphResponse = await fetch(
"https://graph.microsoft.com/v1.0/me",
{
headers: {
Authorization: `Bearer ${response.accessToken}`
}
}
);
const data = await graphResponse.json();
setUserInfo(data);
} catch (error) {
console.error(error);
}
};
return (
<div style={{ padding: "20px" }}>
<h1>MSAL React Demo</h1>
<button onClick={signIn}>
Sign In
</button>
<button onClick={getProfile}>
Get Profile
</button>
{userInfo && (
<div>
<h3>User Info</h3>
<p>Name: {userInfo.displayName}</p>
<p>Mail: {userInfo.mail}</p>
<p>UPN: {userInfo.userPrincipalName}</p>
</div>
)}
</div>
);
}
export default App;
7.実行
viteの場合
npm run dev
アクセス: http://localhost:5173
CRAの場合
npm start
アクセス: http://localhost:3000
8.実際の認可コードフロー
認可要求
GET
/oauth2/v2.0/authorize
↓
code取得
?code=xxxxxxxxxxxxx
↓
トークン取得
{
”access_token”: “…”,
”id_token”: “…”,
”refresh_token”: “…”
}
※SPAでは内部的にPKCE付き認可コードフローが使用されます。