10
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

株式会社船井総研デジタルAdvent Calendar 2022

Day 9

Azure ADの認証をReactアプリケーションに追加してみた。

Last updated at Posted at 2022-12-08

はじめに

今回は、ReactアプリケーションにAzure ADを活用した認証を追加して見たいと思います。

Azure ADの設定

アプリケーションの作成

Azure AD に今回のアプリケーションを追加し、設定していきます。

Screen Shot 2022-11-08 at 10.18.51.png

Screen Shot 2022-11-08 at 10.23.53.png
Screen Shot 2022-11-08 at 10.37.09.png

Redirect URL は React のアプリケーションが動いているホストを指定する。今回はローカル開発環境下で動いているので、localhostを指定する。React にRedirect専用のページを用意するならそのpath 含めて指定する。

Screen Shot 2022-11-09 at 11.12.39.png

Azure AD にアプリケーションの追加ができたら、Application (client) IDが発行される。このIDはReactからAzure ADに通信をするために必要なので、メモしておこう。 
Screen Shot 2022-11-08 at 10.49.30.png

アプリケーションの設定

Screen Shot 2022-11-08 at 10.52.26.png
認証が成功した際の発行するトークンの種類(アクセストークンとIDトークン)の設定をします。React(SPA) アプリケーション場合は、両方有効化する必要があります。(と書いています)僕はこれに気づかず、かなりつまりました。

Screen Shot 2022-11-08 at 10.54.01.png

ユーザの作成

テスト用の新しいユーザをAzure ADに追加します。

Screen Shot 2022-11-08 at 13.53.32.png
Screen Shot 2022-11-08 at 13.47.37.png
Screen Shot 2022-11-08 at 13.59.05.png

ログインするときに必要なユーザーネームは、ここで設定した任意の名前とPrimary domainの組み合わせです。この情報も必要なのでメモしておこう。
パスワードは、一時的なパスワードなので、初回ログイン時にまた新たにパスワードの設定を求められます。だからこの時点では適当なパスワードかAuto-generate passwordを選択して自動生成しよう。

Screen Shot 2022-11-08 at 14.03.59.png

ユーザの作成ができた瞬間は画面に反映されないので、Refreshボタンをクリックしてみてください。おそらく先程作ったユーザが出てくるので。

Screen Shot 2022-11-08 at 14.08.42.png

こんな感じに。

Screen Shot 2022-11-08 at 14.10.23.png

React プロジェクトの作成

viteを使ってReactプロジェクトを作る

開発ツールとして、Vite を使います。Webpack と比べて、かなり軽くて高速です。

typescript のテンプレートが用意されているので、以下のコマンドでテンプレートから React プロジェクトを生成します。

npm create vite@latest azure-ad-auth-react -- --template react-ts

Create React App と違ってライブラリーのインストールまではしてくれないので、npm installをします。

cd azure-ad-auth-react && npm install

package.jsonに開発用の実行devスクリプトが定義されているので、実行します。もちろんホットリロードが効きます。

npm run dev
❯ npm run dev

> azure-ad-auth-react@0.0.0 dev
> vite


  VITE v3.2.3  ready in 337 ms

  ➜  Local:   http://127.0.0.1:5173/
  ➜  Network: use --host to expose

無事Reactが動きました。ものすごく簡単、そして高速です。

Screen Shot 2022-11-08 at 10.15.28.png

開発サーバのポート番号を変更します。Azure AD で登録したRedirect URLにあわせます。今回は3333。

vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  server: {
    port: 3333
  }
})

無事変更されました。
Screen Shot 2022-11-09 at 15.14.21.png

Microsoft Authentication Libraries (MSAL)を使ってAzure AD に認証する

Azure ADとの認証を円滑にするために、オープンソースプロジェクトとして、Microsoft Authentication Libraries (MSAL)というものがあります。遠慮なく使わさせてもらいます。今回はReactを使ってブラウザーから直接認証を行うので、MSALの一部である@azure/msal-browserというものをインストールして、使っていきます。

npm install -E @azure/msal-browser

viteのテンプレートとして生成されたApp.tsxをそのまま編集していきます。

src/App.tsx
import { useState } from "react";
+ import { AccountInfo, PublicClientApplication } from "@azure/msal-browser";
import reactLogo from "./assets/react.svg";
import "./App.css";

+ type Account = Partial<AccountInfo>;

function App() {
  const [count, setCount] = useState(0);
+ const [isAuthenticated, setIsAuthenticated] = useState(false);
+ const [error, setError] = useState<any>(null);
+ const [user, setUser] = useState<Account | null>(null);

+ const publicClientApp = new PublicClientApplication({
+    auth: {
+     clientId: "ac40c95c-6e6c-4188-bee7-ac02b425fbc1",
+      redirectUri: "http://localhost:3333",
+      authority:
+        "https://login.microsoftonline.com/ryuichinishidevgmail.onmicrosoft.com/",
+    },
+    cache: {
+      cacheLocation: "sessionStorage",
+      storeAuthStateInCookie: true,
+    },
+  });

+  const login = async () => {
+    try {
+      const res = await publicClientApp.loginPopup({
+        scopes: ["user.read"],
+        prompt: "select_account",
+      });
+      setIsAuthenticated(true);
+      setUser({ ...res.account });
+    } catch (error) {
+      setIsAuthenticated(false);
+      setUser(null);
+      setError(error);
+    }
+  };

+  const logout = async () => {
+    await publicClientApp.logoutPopup();
+    setIsAuthenticated(false);
+    setUser(null);
+  };

  return (
    <div className="App">
      <div>
        <a href="https://vitejs.dev" target="_blank">
          <img src="/vite.svg" className="logo" alt="Vite logo" />
        </a>
        <a href="https://reactjs.org" target="_blank">
          <img src={reactLogo} className="logo react" alt="React logo" />
        </a>
      </div>
      <h1>Vite + React</h1>
      <div className="card">
        <button onClick={() => setCount((count) => count + 1)}>
          count is {count}
        </button>
        <p>
          Edit <code>src/App.tsx</code> and save to test HMR
        </p>
      </div>
      <p className="read-the-docs">
        Click on the Vite and React logos to learn more
      </p>
+      {isAuthenticated ? (
+        <div>
+          <button onClick={logout}>logout</button>
+        </div>
+      ) : (
+        <div>
+          <button onClick={login}>login</button>
+        </div>
+      )}
+      {error ? <div>{error.message}</div> : null}
+      <br/>
+      {user ? <div>Hello, {user.username}</div> : null}
    </div>
  );
}

export default App;

基本的に@azure/msal-browserPublicClientApplicationのインスタンスを通して、Azure AD とやり取りします。このインスタンスさえ作成してしまえば簡単に認証処理ができます。クラスのコンストラクタに指定する値は:

  • auth.clientId => 先程メモしたApplication (client) ID
  • auth.redirectUri => 先程自ら設定したRedirect URL
  • auth.authority => 'https://login.microsoftonline.com/{Primary Domain}' Primary Domain は Azure AD のoverviewに記載されています。

キャッシュの設定は、sessionStorageに保存して、authのstateはCookieとして保存する。

const publicClientApp = new PublicClientApplication({
    auth: {
     clientId: "ac40c95c-6e6c-4188-bee7-ac02b425fbc1",
      redirectUri: "http://localhost:3333",
      authority:
        "https://login.microsoftonline.com/ryuichinishidevgmail.onmicrosoft.com/",
    },
    cache: {
      cacheLocation: "sessionStorage",
      storeAuthStateInCookie: true,
    },
  });

public.loginPopup functionを実行するとlogin ページのポップアップがでてきて、そのまま簡単に認証ができます。scopesに権限を指定できます。今回はとりあえず read アクセスだけ。認証が成功すると、発行されたトークンを含め、デコードされたアカウントのオブジェクトが返ってくるので、その値をステートに登録しています。

 const login = async () => {
    try {
      const res = await publicClientApp.loginPopup({
        scopes: ["user.read"],
        prompt: "select_account",
      });
      setIsAuthenticated(true);
      setUser({ ...res.account });
    } catch (error) {
      setIsAuthenticated(false);
      setUser(null);
      setError(error);
    }
  };

ログアウト処理も、ものすごく簡単で、publicClientApp.logoutPopupを呼び出すだけで、ログアウトするためのポップアップページがでてきて、そこでログアウトができます。

  const logout = async () => {
    await publicClientApp.logoutPopup();
    setIsAuthenticated(false);
    setUser(null);
  };

あとは、ステートの値に応じてUIの表示を変えています。ログインが成功すれば。logoutのボタンを表示させ、現在ログインしているアカウントの名前を表示、そうでなければloginボタンを表示。何かしらエラーが発生すれば、それを画面に表示する。

      {isAuthenticated ? (
        <div>
          <button onClick={logout}>logout</button>
        </div>
      ) : (
        <div>
          <button onClick={login}>login</button>
        </div>
      )}
      {error ? <div>{error.message}</div> : null}
      <br/>
      {user ? <div>Hello, {user.username}</div> : null}

実際に実行してみます。

npm run dev

ログインボタンが表示されているので、クリックする。
Screen Shot 2022-11-08 at 14.24.44.png
ログインボタンをクリックすると、ログイン専用のポップアップページが出てくる。
Screen Shot 2022-11-08 at 14.38.44.png
先程、新しく作成したユーザのユーザネームとパスワードを入力して、sign in ボタンをクリック。
Screen Shot 2022-11-08 at 14.40.09.png
初回ログインなので、パスワードの変更を求められます。任意の新しいパスワードを入力する。
Screen Shot 2022-11-08 at 14.43.40.png
ログインが成功すると、下にユーザネームが表示される。
Screen Shot 2022-11-08 at 14.44.49.png

おわりに

Microsoft Authentication Librariesを利用することにより、思った以上に簡単にReactアプリケーションに認証機能を追加することができました。発行されたアクセストークンを使ってazureのリソースに簡単にアクセスすることができます。このようにAzureを活用すると安全なアプリケーションが爆速で開発できるようになります。

10
4
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
10
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?