import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import {
PublicClientApplication,
type Configuration,
BrowserAuthError
} from '@azure/msal-browser'
import { MsalProvider } from '@azure/msal-react'
import './index.css'
import App from './App.tsx'
const msalConfig: Configuration = {
auth: {
clientId: "hoge",
authority: "https://hoge",
redirectUri: window.location.origin,
postLogoutRedirectUri: window.location.origin,
},
cache: {
cacheLocation: "sessionStorage",
storeAuthStateInCookie: false,
}
};
const msalInstance = new PublicClientApplication(msalConfig);
/**
* アプリケーションの初期化
* 認証とAPI疎通確認が完了するまでレンダリングを保留します
*/
async function initializeApp() {
try {
// 0. MSALの初期化 (v3以降で必須)
await msalInstance.initialize();
// 1. リダイレクトレスポンスの処理
await msalInstance.handleRedirectPromise();
// 2. アクティブアカウントの復元
let account = msalInstance.getActiveAccount();
if (!account && msalInstance.getAllAccounts().length > 0) {
account = msalInstance.getAllAccounts()[0];
msalInstance.setActiveAccount(account);
}
// 3. 未認証時のログイン処理 (Popup -> Redirect フォールバック)
if (!msalInstance.getActiveAccount()) {
const loginRequest = {
scopes: ["User.Read"],
prompt: "select_account",
// ログイン後に戻る場所として現在のURLを記憶
redirectStartPage: window.location.href
};
try {
console.log("Attempting login via popup...");
const loginResponse = await msalInstance.loginPopup(loginRequest);
msalInstance.setActiveAccount(loginResponse.account);
} catch (error) {
// ポップアップがブロックされた、またはキャンセルされた場合はリダイレクトにフォールバック
if (error instanceof BrowserAuthError &&
(error.errorCode === "popup_window_error" || error.errorCode === "user_cancelled")) {
console.warn("Popup failed, falling back to redirect...");
await msalInstance.loginRedirect(loginRequest);
return; // リダイレクトが発生するため、ここでの処理を終了
}
throw error;
}
}
// 4. API検証 (Yahooへの疎通確認)
console.log("Verifying API connectivity...");
try {
// no-corsモードでリクエストを投げ、成功(レスポンスが返ること)を確認
await fetch("https://www.yahoo.co.jp", { mode: 'no-cors' });
console.log("Connectivity verified.");
} catch (e) {
console.error("Connectivity check failed:", e);
// 必要に応じてここで処理を止めることも可能
}
// 5. すべてが準備できたらレンダリング
createRoot(document.getElementById('root')!).render(
<StrictMode>
<MsalProvider instance={msalInstance}>
<App />
</MsalProvider>
</StrictMode>,
);
} catch (error) {
console.error("Initialization failed:", error);
document.body.innerHTML = `
<div style="background:#0f172a; color:white; height:100vh; display:flex; align-items:center; justify-content:center; font-family:sans-serif;">
<div style="text-align:center;">
<h2 style="margin-bottom:1rem;">Authentication Failed</h2>
<p style="color:#94a3b8;">${error instanceof Error ? error.message : "Internal Error"}</p>
<button onclick="window.location.reload()" style="margin-top:2rem; padding:10px 20px; border-radius:8px; border:none; background:#8b5cf6; color:white; cursor:pointer;">
Retry
</button>
</div>
</div>`;
}
}
initializeApp();
Register as a new user and use Qiita more conveniently
- You get articles that match your needs
- You can efficiently read back useful information
- You can use dark theme