クラス コンポーネントでの MSAL React の使用

MSAL React では、関数コンポーネントとクラス コンポーネントの両方がサポートされています。 この記事では、クラス コンポーネントで MSAL React を使用する方法について説明します。これにより、クラス コンポーネント内の MSAL React コンテキストを初期化、保護、アクセスできます。

クラス コンポーネント内で @azure/msal-react フックを使用できないことに注意することが重要です。 クラス コンポーネント内の認証状態にアクセスする必要がある場合は、 @azure/msal-browser を直接使用して同様の機能を取得する必要があります。

Prerequisites

初期化

MSAL React を使用したクラス コンポーネントを使用した初期化は、関数コンポーネントとよく似ています。 関数コンポーネントを使用する場合と同様に、認証状態へのアクセスを必要とするコンポーネント ツリーの最上位レベルに MsalProvider コンポーネントが必要です。

次のスニペットでは、 MsalProvider コンポーネントを使用してアプリケーション全体をラップし、すべての子コンポーネントで MSAL インスタンスを使用できるようにします。 これにより、子コンポーネントは、ユーザー認証、トークンの取得、保護された API の呼び出しに MSAL を使用できます。

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

const pca = new PublicClientApplication(config);

class App extends React.Component {
    render() {
        return (
            <MsalProvider instance={pca}>
                <YourAppComponents>
            </ MsalProvider>
        );
    }
}

コンポーネントの保護

MSAL React では、コンポーネントを保護し、ユーザーの認証状態に基づいて条件付きでレンダリングできます。 これは、関数コンポーネントの使用と同様に機能します。 主な例は次のとおりです。

  • AuthenticatedTemplate - このコンポーネントは、ユーザーが認証された場合にのみ子をレンダリングします。 ユーザーが認証されていない場合、何もレンダリングされません。
  • UnauthenticatedTemplate - このコンポーネントは、ユーザーが認証されていない場合にのみ子をレンダリングします。 ユーザーが認証されている場合、何もレンダリングされません。
  • MsalAuthenticationTemplate - このコンポーネントは、子をレンダリングする前にユーザーの認証を試みます。 相互作用の種類 (リダイレクトまたはポップアップ) を prop として指定できます。ユーザーが認証されていない場合は、認証プロセスが開始されます。

次のスニペットは、 AuthenticatedTemplateUnauthenticatedTemplateMsalAuthenticationTemplate を使用して React コンポーネントを保護する方法を示しています。 MSAL Provider が子コンポーネントを囲んでいることに注目してください。

import React from "react";
import { MsalProvider, AuthenticatedTemplate, UnauthenticatedTemplate, MsalAuthenticationTemplate } from "@azure/msal-react";
import { PublicClientApplication, InteractionType } from "@azure/msal-browser";

const pca = new PublicClientApplication(config);

class App extends React.Component {
    render() {
        return (
            <MsalProvider instance={pca}>
                <AuthenticatedTemplate>
                    <span>This will only render for authenticated users</span>
                </ AuthenticatedTemplate>
                <UnauthenticatedTemplate>
                    <span>This will only render for unauthenticated users</span>
                </ UnauthenticatedTemplate>
                <MsalAuthenticationTemplate interactionType={InteractionType.Popup}>
                    <span>This will only render for authenticated users.</span>
                </ MsalAuthenticationTemplate>
            </ MsalProvider>
        );
    }
}

クラス コンポーネント内の MSAL React コンテキストへのアクセス

useMsal フックを使用して、クラス コンポーネント内の MSAL React コンテキストにアクセスすることはできません。 これは、フックは、インスタンスなしで機能を使用できる関数コンポーネントでのみ使用できるためです。 クラス コンポーネントにはインスタンスがあるため、他に 2 つのオプションがあります。 生のコンテキストを直接使用するか、 withMsal 上位のコンポーネントを使用してコンポーネントのプロパティにコンテキストを挿入できます。

生コンテキストへのアクセス

次のスニペットは、 MsalContext を使用して、クラス コンポーネント内の生のコンテキストにアクセスする方法を示しています。

import React from "react";
import { MsalProvider, MsalContext } from "@azure/msal-react";
import { PublicClientApplication } from "@azure/msal-browser";

const pca = new PublicClientApplication(config);

class App extends React.Component {
    render() {
        return (
            <MsalProvider instance={pca}>
                <YourClassComponent/>
            </ MsalProvider>
        );
    }
}

class YourClassComponent extends React.Component {
    static contextType = MsalContext;

    render() {
        const isAuthenticated = this.context.accounts.length > 0;
        if (isAuthenticated) {
            return <span>There are currently {this.context.accounts.length} users signed in!</span>
        }
    }
}

実際の例については、react-router-sampleProfileRawContext.jsx を参照してください。

withMsal HOC を介したアクセス

別の方法として、 withMsal 上位コンポーネントを使用して、コンポーネントのプロパティにコンテキストを挿入します。 次のスニペットは、 withMsal HOC を使用してクラス コンポーネント内の MSAL React コンテキストにアクセスする方法を示しています。

import React from "react";
import { MsalProvider, withMsal } from "@azure/msal-react";
import { PublicClientApplication } from "@azure/msal-browser";

const pca = new PublicClientApplication(config);

class YourClassComponent extends React.Component {
    render() {
        const isAuthenticated = this.props.msalContext.accounts.length > 0;
        if (isAuthenticated) {
            return <span>There are currently {this.props.msalContext.accounts.length} users signed in!</span>
        }
    }
}

const YourWrappedComponent = withMsal(YourClassComponent);

class App extends React.Component {
    render() {
        return (
            <MsalProvider instance={pca}>
                <YourWrappedComponent />
            </ MsalProvider>
        );
    }
}

実際の例については、react-router-sampleProfileWithMsal.jsx を参照してください。

クラス コンポーネントを使用したログイン

MSAL React コンテキストを取得するために実行する方法に関係なく、使用は同じになります。 コンテキスト オブジェクトを取得したら、PublicClientApplication呼び出したり、サインインしているアカウントを調べたり、認証が現在進行中かどうかを判断したりできます。

次の例では、 withMsal HOC アプローチを使用してログインする方法を示しますが、必要に応じて他のアプローチにすばやく適応できます。

Note

MsalProvider コンポーネントは、コンテキストを使用するコンポーネントの上の任意のレベルでレンダリングする必要があります。 次の例では、プロバイダーがあることを前提としており、これを示しません。

ボタンをクリックした結果としてログインする

次のスニペットでは、LoginButton上位コンポーネントを使用する React クラス コンポーネント withMsalを定義します。 ユーザーが認証されていない場合はログイン ポップアップをトリガーするか、認証された場合はユーザーをログアウトするボタンがレンダリングされます。

import React from "react";
import { withMsal } from "@azure/msal-react";

class LoginButton extends React.Component {
    render() {
        const isAuthenticated = this.props.msalContext.accounts.length > 0;
        const msalInstance = this.props.msalContext.instance;
        if (isAuthenticated) {
            return <button onClick={() => msalInstance.logout()}>Logout</button>    
        } else {
            return <button onClick={() => msalInstance.loginPopup()}>Login</button>
        }
    }
}

export default YourWrappedComponent = withMsal(LoginButton);

ページ読み込み時のログイン

次のスニペットでは、ProtectedComponent上位コンポーネントを使用する React クラス コンポーネント withMsalを定義します。 マウントと更新時にユーザーの認証が試行され、ユーザーが認証されているかどうか、または読み込みページで認証が進行中かどうかを表示します。

import React from "react";
import { withMsal } from "@azure/msal-react";
import { InteractionStatus } from "@azure/msal-browser";

class ProtectedComponent extends React.Component {
    callLogin() {
        const isAuthenticated = this.props.msalContext.accounts.length > 0;
        const msalInstance = this.props.msalContext.instance;

        // If a user is not logged in and authentication is not already in progress, invoke login
        if (!isAuthenticated && this.props.msalContext.inProgress === InteractionStatus.None) {
            msalInstance.loginPopup();
        }
    }
    componentDidMount() {
        this.callLogin();
    }

    componentDidUpdate() {
        this.callLogin();
    }
    
    render() {
        const isAuthenticated = this.props.msalContext.accounts.length > 0;
        if (isAuthenticated) {
            return <span>User is authenticated</span>
        } else {
            return <span>Authentication in progress</span>;
        }
    }
}

export default YourWrappedComponent = withMsal(ProtectedComponent);

こちらも参照ください