Azure App Service Easy Auth をローカル開発環境で実現する方法

Azure App Service には **Easy Auth** と呼ばれる認証機能が組み込まれており、コードを変更することなくアプリケーションに認証を追加することができます。この機能は本番環境では非常に便利ですが、ローカル開発時にはどのように再現すべきかという課題があります。

この記事では、Docker を使用して Azure App Service の Easy Auth 機能をローカル開発環境で再現する方法を詳しく解説します。これにより、開発からデプロイまで一貫した認証フローをテストすることが可能になります。

## Easy Auth とは

Easy Auth（正式名称: App Service Authentication）は、アプリケーションコードを変更することなく、Microsoft Entra ID（旧 Azure Active Directory）、Google、Facebook、Twitter、GitHub などの認証プロバイダーを使った認証を簡単に実装できる機能です。

主な特徴:

- アプリケーションコードの変更が不要
- 複数の認証プロバイダーをサポート
- トークンの取得・管理を自動化
- ユーザー情報へのアクセスが簡素化

## 必要な環境

- **Azure アカウント**
  - Microsoft Entra ID（無料の範囲内で使用可能）
- **Docker がインストールされた開発環境**
  - Easy Auth ミドルウェアを docker hub から取得し利用します
- **ローカルで実行する Web アプリケーション**
  - 任意のアプリケーション。Node.js Express 等

## 詳細セットアップ手順

### 1. Microsoft Entra ID でのアプリケーション登録

1. **Azure ポータル**にログインし、**Microsoft Entra ID**に移動します
2. **アプリの登録** > **新規登録**を選択
   - **名前**: `EasyAuthTest`（任意の名前）
   - **サポートされているアカウントの種類**: 任意（単一テナントまたはマルチテナント）
   - **リダイレクト URI**:
     - タイプ: `Web`
     - URI: `http://localhost:8081/.auth/login/aad/callback`
3. **API のアクセス許可**を設定
   - **Microsoft Graph** > **User.Read** を追加
   - **委任されたアクセス許可**として追加する
   - アクセス許可を**管理者の同意**で付与（必要な場合）
4. **認証**セクションで設定を確認
   - **暗黙的フローと...** > **ID トークン**にチェック
5. **証明書とシークレット**でクライアントシークレットを作成
   - **新しいクライアントシークレット**を追加
   - **説明**: `Local Development`（任意）
   - **有効期限**: 適切な期間を選択（開発用途であれば数ヶ月程度）
   - 作成後表示される**値**を保存（後で使用）

### 2. Docker による Easy Auth ミドルウェアの設定

1. 以下の内容で環境変数ファイル `.env` を作成します:

```bash
APPSETTING_WEBSITE_AUTH_LOGOUT_PATH=/.auth/logout
APPSETTING_WEBSITE_AUTH_DEFAULT_PROVIDER=AzureActiveDirectory
APPSETTING_WEBSITE_AUTH_ENABLED=True
HOME=/home
HTTP_LOGGING_ENABLED=1
WEBSITE_AUTH_ALLOWED_AUDIENCES=http://localhost:8081/.auth/login/aad/callback
WEBSITE_AUTH_AUTO_AAD=False
WEBSITE_AUTH_CLIENT_ID=<Entra ID アプリのクライアント ID>
WEBSITE_AUTH_CLIENT_SECRET=<発行したクライアント シークレット>
WEBSITE_AUTH_DEFAULT_PROVIDER=AzureActiveDirectory
WEBSITE_AUTH_ENABLED=True
WEBSITE_AUTH_ENCRYPTION_KEY=<openssl rand -base64 32 で生成したランダムな文字列>
WEBSITE_AUTH_LOGOUT_PATH=/.auth/logout
WEBSITE_AUTH_OPENID_ISSUER=https://sts.windows.net/<該当 Azure のテナント ID>/
WEBSITE_AUTH_SIGNING_KEY=<openssl rand -base64 32 で生成したランダムな文字列>
WEBSITE_AUTH_TOKEN_STORE=True
WEBSITE_AUTH_UNAUTHENTICATED_ACTION=RedirectToLoginPage
WEBSITE_HOSTNAME=localhost
WEBSITE_INSTANCE_ID=localhost
WEBSITE_ROLE_INSTANCE_ID=0
WEBSITE_SITE_NAME=localhost
```

2. Docker コンテナを起動します:

```bash
docker run -d -p 8081:8081 --env-file .env \
  --name easyauth-middleware \
  appsvc/middleware:2001061754 \
  /Host.ListenUrl=http://0.0.0.0:8081 \
  /Host.DestinationHostUrl=http://host.docker.internal:3000 \
  /Host.UseFileLogging=true
```

- 注 1: `http://host.docker.internal:3000` の `3000` 部分はあなたの Web アプリケーションが動作しているポート番号に変更してください。
- 注 2: OSS の docker アプリケーションにより host.docker.internal が使用できない場合があります。 Docker ネットワーク設定を確認してください。

### 3. Web アプリケーションとの連携

1. ローカルの Web アプリケーションを起動します（例: `npm run dev`）
2. ブラウザで `http://localhost:8081` にアクセス
3. Microsoft Entra ID のログイン画面にリダイレクトされます
4. ログイン後、アプリケーションにリダイレクトされます

## 認証情報へのアクセス方法

Easy Auth でログインすると、次のエンドポイントからユーザー情報やトークンを取得できます:

- `/.auth/me` - ログインしているユーザーの情報を JSON 形式で取得
- `/.auth/refresh` - トークンを更新
- `/.auth/logout` - ログアウト

アプリケーションでは、以下のようなコードでユーザー情報を取得できます:

```javascript
// ユーザー情報を取得する例
async function getUserInfo() {
  const response = await fetch("/.auth/me");
  const authInfo = await response.json();
  return authInfo;
}
```

## トラブルシューティング

### Docker コンテナが起動しない場合

- ポート 8081 が他のプロセスで使用されていないか確認
- 環境変数ファイルのパスが正しいか確認

### 何らかのエラーが発生した

起動した docker コンテナのログを確認して下さい。ログは以下のファイルとしてコンテナ内部に保存されます。

```bash
cat /var/middleware/logs/middleware.log
```

## 本番環境との違い

ローカル環境で使用する Easy Auth ミドルウェアは本番環境の App Service とは完全に同一ではありません。また、このコンテナは Microsoft 公式でもありません（用意して欲しいなぁ）。必ず公開前に本番環境での動作を確認してください。

## まとめ

Azure App Service の Easy Auth 機能をローカル開発環境で再現することで、認証機能の開発やテストがよりスムーズになります。

## メモ系

docker が使えない環境の場合、 docker container に入っている以下の情報を元に、 dotnet アプリとして直接起動すること

- `/app` の dotnet のソースコード
- [docker hub](https://hub.docker.com/layers/appsvc/middleware/2001061754/images/sha256-175670190519836d5469bdc75a1ec5a1cd79b18bd96c17afdf1735454c306d14) の ENTRYPOINT 等の記述

## 参考資料

- [Running EasyAuth locally](https://hajekj.net/2020/05/01/running-easyauth-locally/)
- [Azure App Service Authentication Documentation](https://docs.microsoft.com/azure/app-service/overview-authentication-authorization)
- [Microsoft Entra ID アプリケーション登録](https://docs.microsoft.com/azure/active-directory/develop/quickstart-register-app)