Azure AD B2CでReact(SPA)ログインの方法まとめ:3パターン

Azure AD B2Cでログインする処理に関してまとめ:React
◆ Live配信スケジュール ◆
サイオステクノロジーでは、Microsoft MVPの武井による「わかりみの深いシリーズ」など、定期的なLive配信を行っています。
⇒ 詳細スケジュールはこちらから
⇒ 見逃してしまった方はYoutubeチャンネルをご覧ください
【5/21開催】Azure OpenAI ServiceによるRAG実装ガイドを公開しました
生成AIを活用したユースケースで最も一番熱いと言われているRAGの実装ガイドを公開しました。そのガイドの紹介をおこなうイベントです!!
https://tech-lab.connpass.com/event/315703/

Azure AD B2CをReact(SPA)でログインする方法についてまとめました。初期では1パターンしか知らなかったため、紆余曲折ありましたが使い分けができる程度には成長しました。使ったことがある人はさっくりと、知らなかった人はこっそりと勉強していってください。新米フロントエンドエンジニアの技術ログ

ご挨拶

どもども!燃え尽き症候群は深刻な問題だなと痛感している龍ちゃんです。ここ数日で一気に涼しくなりましたね。これぐらいの気温で固定してもらえると電気代も抑えられて、我が家の財政にも優しいのですが…..在宅ワークだと電気代が高騰するのが悩みです。

さて、今回は、React(SPA)を用いた「Azure AD B2C」でのログインの方法についてまとめる回になります。お手軽?に認証基盤を導入することができるという点とAzureのサービスの親和性を考えて、「Azure AD B2C」という選択肢を取ることが良くあります。ログインを実装する方法に関しては、3パターンあるのでその方法について解説していきます。

ブログで取り扱う内容としては以下になります。

  • React(SPA)でAzure AD B2Cでのログインに関する共通部分
  • useMsalを用いた自力実装
  • useMsalAuthenticationを用いた半自動実装
  • MsalAuthenticationTemplateを用いた自動実装

3パターンもあると、どれを使うべきか悩ましいところです。すべての実装をリダイレクト形式で処理をするように作成しています。

それでは実装の解説に入っていきます。

実装

まず、どの実装パターンでも必要な共通実装部分について作成していきます。その後、各実装について解説をしていきます。

React(SPA)でAzure AD B2Cを扱うための共通実装

【Msal.js】を利用するにあたって、絶対作成しなければならないコードが以下になります。接続先を示すファイルを設定ファイルとして切り出しています。ここの設定ファイルに関しては、以下のブログで解説しています。公式のガイドもわかりやすいのでおいておきます。

PublicClientApplicationを構築するため以外の設定ファイルが含まれています。

import { Configuration } from '@azure/msal-browser';

const AzureClientId: string = import.meta.env.VITE_AZURE_CLIENT_ID || '';
const AzureScopes: string[] = [import.meta.env.VITE_AZURE_SCOPE || ''];
const AzureAuthority: string = import.meta.env.VITE_AZURE_AUTHORITY || '';
const AzureKnownAuthorities: string[] = [import.meta.env.VITE_AZURE_KNOWN_AUTHORITY || ''];

export const msalConfig: Configuration = {
  auth: {
    clientId: AzureClientId,
    authority: AzureAuthority,
    knownAuthorities: AzureKnownAuthorities,
    redirectUri: window.location.origin,
  },
  cache: {
    cacheLocation: 'sessionStorage',
    storeAuthStateInCookie: false,
  },
};

以下のコードが【Msal.js】をReactで使用するためには必要なコンポーネントになります。

import { PublicClientApplication } from '@azure/msal-browser';
import { MsalProvider } from '@azure/msal-react';

import { msalConfig } from '@/constants/authAzure';

export const AzureConfigComponent = (props: { children: React.ReactNode }) => {
  const { children } = props;

  const pca = new PublicClientApplication(msalConfig);
  return (
    <MsalProvider instance={pca}>
      {children}
    </MsalProvider>
  );
};

MsalProvider以下ではないと、【Msal.js】が提供している機能が動かないのでご注意ください。

useMsalを用いた自力実装

公式のGitの資料としては以下になります。こちらは、ログインの判定からログインの処理までをすべて自力で実装する内容になります。こちらの実装方法を採用する場面としては、トップページの一部が、ログイン状態によって変化するページに適しています。

import { useCallback } from 'react';

import { useMsal } from '@azure/msal-react';

export const useAzureAuth = () => {
  const { instance } = useMsal();

  const loginAzure = useCallback(async () => {
    instance.loginRedirect();
  }, [instance]);

  const logoutAzure = useCallback(async () => {
    instance.logout();
  }, [instance]);

  return {
    logoutAzure,
    loginAzure,
  };
};

上記のHooksに示した方法が、Redirect方式でログインをする場合の対応になります。ボタンコンポーネントと複合して使用することで、ログイン処理やログアウト処理を実装することができます。

以下使用方法のサンプルになります。

import { AuthenticatedTemplate, UnauthenticatedTemplate } from '@azure/msal-react';

import { useAzureAuth } from '@/hooks/useAzureAuth';

export const TestPage = () => {
  const { loginAzure, logoutAzure } = useAzureAuth();
  return (
    <>
      <UnauthenticatedTemplate>
        ログイン前に表示されるページ<button onClick={loginAzure}>ログイン</button>
      </UnauthenticatedTemplate>

      <AuthenticatedTemplate>
        ログイン後に表示されるページ <button onClick={logoutAzure}>ログアウト</button>
      </AuthenticatedTemplate>
    </>
  );
};

UnauthenticatedTemplateAuthenticatedTemplateは【msal-react】が提供しているコンポーネントになります。ログイン状態によって一部分のUIを変化させたい場合は、非常に活躍します。

useMsalAuthenticationを用いた半自動実装

公式のGitの資料としてはこちらになります。こちらは、呼び出したタイミングで自動でログイン処理が走ります。エラーが出た場合は、ReactのuseEffectと併用することでログインの処理を実装することができます。以下がコードになります。

import { useEffect } from 'react';

import { InteractionRequiredAuthError, InteractionType } from '@azure/msal-browser';
import { useMsalAuthentication } from '@azure/msal-react';

export const TestPage = () => {
  const { login, result, error } = useMsalAuthentication(InteractionType.Redirect);

  useEffect(() => {
    if (error instanceof InteractionRequiredAuthError) {
      login(InteractionType.Redirect);
    } else {
      console.log(result);
    }
  }, [error, login, result]);

  return <>ログイン完了</>;
};

 

useMsalAuthenticationでは、ログインの機能とログイン結果を取得することができます。resultはログインの結果が格納されているため、アクセストークンの取得を担保することができます。

こちらを使用する場合では、「アクセス~ログイン処理」を実行するまで、画面がちらつくため自前でローディングの機能を実装する必要があります。ちらつきの原因としては、【Msal.js】の起動時にReactのコンポーネント再レンダリングが発生することが考えられます。そのため、判定ロジック前に

こちらの解消方法としては、useMsalで取得することができるinProgressを使用します。inProgressは【Msal.js】の状態を返答してくれる変数になります。こちらの値は【InteractionStatus】で定義されており、この値がNoneになった時にログイン判定までが終了したことになります。

import { useEffect, useMemo } from 'react';

import { InteractionRequiredAuthError, InteractionStatus, InteractionType } from '@azure/msal-browser';
import { useMsal, useMsalAuthentication } from '@azure/msal-react';

import { LoadingComponent } from '@/pages/LoadingPage';

export const TestPage = () => {
  const { inProgress } = useMsal();
  const { login, result, error } = useMsalAuthentication(InteractionType.Redirect);

  useEffect(() => {
    if (error instanceof InteractionRequiredAuthError) {
      login(InteractionType.Redirect);
    }
  }, [error, login]);

  const userID = useMemo(() => {
    if (!result || !result.account.idTokenClaims?.oid) return '';
    return result.account.idTokenClaims.oid;
  }, [result]);

  if (inProgress != InteractionStatus.None) return <LoadingComponent />;

  return <>ログイン完了{userID}</>;
}

MsalAuthenticationTemplateを用いた自動実装

公式のGitの資料としてはこちらになります。こちらは、前述の方法と異なりコンポーネントとして提供されています。ログイン状態でなければ自動でログイン処理を行い、ログイン中や起動判定なども自動で行ってくれます。


import { InteractionType } from '@azure/msal-browser';
import { MsalAuthenticationResult, MsalAuthenticationTemplate } from '@azure/msal-react';

import { LoadingComponent } from '@/pages/LoadingPage';

export const TestPage = () => {
  const ErrorComponent = (result: MsalAuthenticationResult) => {
    const { error } = result;
    return <>{error}</>;
  };
  return (
    <>
      <MsalAuthenticationTemplate
        interactionType={InteractionType.Redirect}
        authenticationRequest={{}}
        errorComponent={ErrorComponent}
        loadingComponent={LoadingComponent}
      >
        ログイン完了
      </MsalAuthenticationTemplate>
    </>
  );
};

使用方法としては、上記になります。こちらは、コンポーネントにPropとしてerrorComponentloadingComponentを渡すことが求められます。名前の通り処理中とエラーが表示された際に、コンポーネントの差し替えを自動で行ってくれます。

単純にコンポーネントレベルで実現したい場合は、楽に実装することができるので非常に便利だと思います。

3パターンのログイン処理の比較

3パターンの実装について紹介したので、それぞれの比較を行ってい置きたいと思います。自動でログイン処理を行いたい場合は、useMsalAuthenticationMsalAuthenticationTemplateになるかと思います。

Azure AD B2CでSPAログインを行いたいときの方法まとめ

自動ログインを実装したい場合は、useMsalAuthenticationMsalAuthenticationTemplateを使用することがベターだと思います。ログイン後でページの一部分のみが変わる場合は、useMsalUnauthenticatedTemplateAuthenticatedTemplateを併用することが良い選択しただと思います。どの手法でもログイン情報を取得することができるので、要件によって構築方法が変化するかと思います。

個人的な好みとしては、MsalAuthenticationTemplateがコード量が少なくてよいかと思います。エラーハンドリングがブラックボックス化される部分は否めないですが、React側でキャッチすることで拾えることができるかと思います。一方で、useMsalAuthenticationでログイン処理のちらつきを抑制することができるのであれば、トークン取得もセットでできるのでお得です。

終わりに

お疲れ様です。Azure AD B2Cはお手軽にログイン機能を実装することができるので、非常に便利です。ログイン機能があるだけで、自主開発であればレベルがぐっと上がる気がします。商用のサービスであれば、認証・認可などはがっつり必要となる機能だと思います。

去年一年は、何もわからないからAzureのサービス「チョットツカエル」になったと思います。昔書いたブログのミスも見つけたので、反省しながら修正しておきます。

フロントエンドの記事をひと段落させたら、フロントとバック(+デザイン)の記事を書いていきたいと思っています。年内に出したいものですね。

ではまた~

 

 

アバター画像
About 龍:Ryu 107 Articles
2022年入社で主にフロントエンドの業務でTailwindと遊ぶ日々。お酒とうまいご飯が好きで、運動がちょっと嫌いなエンジニアです。しゃべれるエンジニアを目指しておしゃべりとブログ執筆に注力中(業務もね)//
ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。


ご覧いただきありがとうございます。
ブログの最新情報はSNSでも発信しております。
ぜひTwitterのフォロー&Facebookページにいいねをお願い致します!



>> 雑誌等の執筆依頼を受付しております。
   ご希望の方はお気軽にお問い合わせください!

Be the first to comment

Leave a Reply

Your email address will not be published.


*


質問はこちら 閉じる