はじめに
本記事の目的
- ReactアプリにおけるOIDC・OAuth準拠した認証・認可の実装例として、Microsoft社が提供するフレームワークであるMicrosoft Authentication Library(以降、MSAL)を試してみる。
対象読者
- OIDC及びOAuthに関する基礎知識を持つ、フロントエンドエンジニアを対象読者として想定する。
環境構成イメージ
OpenID Provider設定
Dockerコンテナ設定・起動
- Keycloak及びPostgresをDocker基盤上で動かすために、Composeファイルを作成する。
version: '3'
services:
postgres:
image: postgres:15
restart: always
environment:
POSTGRES_USER: $POSTGRES_USER
POSTGRES_PASSWORD: $POSTGRES_PW
POSTGRES_DB: keycloak
ports:
- 5432:5432
volumes:
- ./postgres:/var/lib/postgresql/data
keycloak:
image: quay.io/keycloak/keycloak:23.0.0
container_name: keycloak
tty: true
stdin_open: true
ports:
- 8080:8080
environment:
KEYCLOAK_ADMIN: $KEYCLOAK_ADMIN
KEYCLOAK_ADMIN_PASSWORD: $KEYCLOAK_ADMIN_PASSWORD
KC_DB: postgres
KC_DB_USERNAME: $POSTGRES_USER
KC_DB_PASSWORD: $POSTGRES_PW
KC_DB_URL_PORT: 5432
KC_DB_URL_HOST: postgres
KC_DB_URL_DATABASE: keycloak
command:
- "start-dev"
depends_on:
- postgres
start-devオプションを用いて、Keycloakを開発モードで起動している。Production環境でKeycloakを利用する場合には、本記事の設定をそのまま流用しないように留意すること。
- Docker Composeコマンドを実行し、コンテナ群を起動する。
docker-compose up
Keycloak設定
-
Keycloakの管理画面にログインする。
- ブラウザでlocalhost:8080にアクセスする。
- Docker Compose時に指定した
KEYCLOAK_ADMIN
及びKEYCLOAK_PW
の値を用いて、ログインする。
-
Clients
>Create client
から、OIDC Clientを作成する。
OIDC Clientを作成する際、Redirect URI及びWeb originsにReactアプリケーションの情報を登録すること。
-
Users
>Add user
から、動作確認で利用するログインユーザを作成する。
-
Realm settings
>OpenID Endpoint Configuration
から、OIDCエンドポイント情報を取得する。
Reactアプリ構築
- Reactプロジェクト作成した上で、MSAL系ライブラリをインストールする。
# Reactプロジェクトを作成
npx create-react-app myApp --template typescript
# msal系ライブラリをインストール
npm install @azure/msal-react @azure/msal-browser
# 開発サーバ起動
npm start
- KeycloakのOIDCエンドポイント情報を.envファイルに格納する。
-
index.tsx
にて、認証インスタンスを実装する。
export const MsalInstance = new msal.PublicClientApplication({
auth: {
// protocolModeにOIDCを指定することで、Azure以外のOPにも対応可能
protocolMode: msal.ProtocolMode.OIDC,
authorityMetadata: JSON.stringify({
authorization_endpoint: process.env.REACT_APP_AUTHORIZATION_ENDPOINT,
token_endpoint: process.env.REACT_APP_TOKEN_ENDPOINT,
issuer: process.env.REACT_APP_REALM_ENDPOINT,
userinfo_endpoint: process.env.REACT_APP_USERINFO_ENDPOINT,
}),
clientId: process.env.REACT_APP_CLIENT_ID ?? "poc-client",
},
});
-
App.tsx
にて、認証処理ロジックを実装する。
import React from "react";
import "./App.css";
import {
useMsal,
AuthenticatedTemplate,
UnauthenticatedTemplate,
} from "@azure/msal-react";
function App() {
const { instance } = useMsal();
return (
<div className="App">
<h1>MSAL App</h1>
<AuthenticatedTemplate>
<div>Login Succeeded</div>
</AuthenticatedTemplate>
<UnauthenticatedTemplate>
<button onClick={()=>instance.loginPopup()}>Login via Keycloak</button>
</UnauthenticatedTemplate>
</div>
);
}
export default App;
動作確認
機能観点での動作確認
- 未認証でフロントエンドアプリにアクセスした場合、ログインボタンが表示される。
- ログインボタンを押下すると、ポップアップでKeycloakのログイン画面に遷移する。
- Keycloakの認証情報を入力すると、ログイン成功画面にリダイレクトされる。
セキュリティ観点での動作確認
- 認証リクエストのクエリパラメータを確認したところ、
-
response_type
にcode
が指定されており、認可コードフローが使用されている。 -
code_challenge
及びcode_challenge_method
が指定されており、PKCEによる認可コード横取り対策が実装されている。 -
nonce
が指定されており、リプレイアタック対策が実装されている。 -
state
が指定されており、CSRF対策が実装されている。
-
- ブラウザのSession Storageに格納されたIDトークンをjwt.ioを用いてデコードしたところ、
at_hash
が含まれており、トークンインジェクション対策が実装されている。
参考
- Azure Active Directory B2C を使用して独自の React アプリケーションで認証を有効にする
- Using MSAL in a React SPA with Keycloak
- OAuth 2.0 Security Best Current Practice
- 2. OAuth 2.0 Security Best Current Practice
注意事項
- 本記事は万全を期して作成していますが、お気づきの点がありましたら、ご連絡よろしくお願いします。
- なお、本記事の内容を利用した結果及び影響について、筆者は一切の責任を負いませんので、予めご了承ください。