0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MSAL検証

Posted at
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();



0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?