MkDocsで作ったサイトをAzureStaticWebAppsに公開したあと認証機能を付ける

# 背景
MkDocsで静的Webサイトを作った後に、それをAzure Static Web Appsに公開した。
ただ、普通に公開しただけでは全世界に公開していることになるので、認証機能を付けたいと考えた。

執筆時的には比較的新しい技術であることからも、情報が少なくかなり躓いたので、忘れないようにメモしたいと考えた。

# 認証機能の付け方

## 前提
1. MkDocsで静的サイトをAzure Static Web Appsに公開していること（まだ公開さえしていない場合は、[MkDocsを使用してAzure Static Web Appsに自己紹介サイトをデプロイする](https://qiita.com/tacotacorice/items/fa84b2c6088139b0c102)を参考に作ると良い）

## 手順
### 1. staticwebapp.config.jsonを用意する。

このstaticwebapp.config.jsonファイルは、AzureStaticWebAppsの設定ファイルです。

```json:staticwebapp.config.json
{
  "routes": [
    {
      "route": "/*",
      "allowedRoles": [
        "authenticated"
      ]
    }
  ],
  "navigationFallback": {
    "rewrite": "/index.html"
  },
  "responseOverrides": {
    "401": {
      "redirect": "/.auth/login/aad",
      "statusCode": 302
    }
  }
}
```

このファイルの主な内容は以下の通りです。

- routes:
すべてのパス（/*）に対して "authenticated" ロール（認証済みユーザー）のみアクセスを許可しています。つまり、未認証ユーザーはサイトのどのページにもアクセスできません。

- navigationFallback:
クライアントサイドルーティング（SPAなど）用に、存在しないパスへのアクセス時は /index.html にリライトします。

- responseOverrides:
401（未認証）エラーが発生した場合、/.auth/login/aad（Azure Active Directoryのログインページ）にリダイレクトし、HTTPステータスコード302（Found）を返します。

この設定により、アプリ全体が認証必須となり、未認証の場合は自動的にAzure AD認証に誘導されます。

:::note
この設定値ではAzureADの認証が通る人なら誰でも認証されてしまう状態です。
後半でさらに狭い範囲（特定のユーザー）にのみ見せられるように変更します。
:::

### 2. 1で作ったファイルをmkdocsのフォルダに配置する

この作業が一番手ごわかったです。
Microsoft社のAzure Static Web Appsのページ開設はBlazor等を想定して書かれているので、wwwrootとかに配置して下さいと書かれていますが、MkDocsベースで作った場合、そんなフォルダは普通ないと思います。

じゃあどこに置くのか。下記のどこかです。
1. mkdocs.ymlが置いてあるフォルダ
1. siteフォルダ（mkdocsでbuildやserveしたら作成されていると思う）
1. mkdocs用のmarkdownドキュメントが格納されているフォルダ

こればかりは環境依存が強すぎて正解はないと思います。
私の作成時には、他のアプリもいろいろ付け加えていたので上記3で上手く認証機能が動くようになりました。
何度か試してみて、認証が動くようになったらそこが正解です。

### 3. Azureポータルでロールを作る
ここからは特定のユーザーに対してのみ、サイトを公開するための方法です。

1. Azure PortalでAzure Static Web Appsの当該リソースのページに行き、ロール管理 > "招待"を押す
1. 以下の内容で招待リンクを生成し、招待者に連携する
    - 認証プロバイダー：Azure Active Directory
    - メールアドレス：閲覧権限を与えたい人のメールアドレス
    - ドメイン：そのまま
    - ロール：test_auth（正直ここはなんでもいいです。わかりやすい名前でロールは作って）
    - 招待の有効期限：なんでもいいです
1. 招待者側でリンクを開くと、Azureの認証画面が出ますので、そちらから認証する

### 4. staticwebapp.config.jsonを修正する

allowedRolesを先ほど作ったロール名に変更してデプロイをし直してください。
これで、そのロールを持った人しか見れなくなります。

```json:staticwebapp.config.json
{
  "routes": [
    {
      "route": "/*",
      "allowedRoles": [
        "test_auth"
      ]
    }
  ],
  "navigationFallback": {
    "rewrite": "/index.html"
  },
  "responseOverrides": {
    "401": {
      "redirect": "/.auth/login/aad",
      "statusCode": 302
    }
  }
}
```

## 躓いたポイント

- 上記2番のstaticwebapp.config.jsonを配置する場所は、環境依存がかなり強いです。
私の環境だと、mkdocsのドキュメントが置いてあるフォルダに配置しましたが、公式ドキュメントなどを見る限りそんな場所に配置することはほとんどないみたいです（mkdocsの構成を作るときにいろいろ手探りだったので、どこかでおかしくなったのかな）。
辺に迷わず、とりあえずtry errorで対応するのが一番早いと思います。
- Azure Portal上からホスティングプランを見たら、Standardプランのみカスタム認証にチェックがついていました。
なのでStandardプランにしなくてはならないのかなとちょっと調べましたが、カスタム認証というのはMicrosoft Entra ID認証（旧：Azure AD認証）と、Githubの認証以外を使いたい場合のときのことを言っているみたいです。

## 他のおすすめ機能

- Standardプラン以上だと、パスワード保護を有効にできます。
一人一人にパスワードを付与するのではなく、１つ長ーいパスワードを付けられるだけのようですが、人数が多いときや時間が無くてとりあえずパスワード保護を付けたい場合は、おすすめの機能です。
Azure Portalの構成タブから、パスワード保護を有効にできます。

# 感想

簡単に静的サイトを作れる時代になりましたが、こういう認証部分はやっぱりまだまだ難しいですね。

# 参考
- [Micorosoftの公式サイト](https://learn.microsoft.com/ja-jp/azure/static-web-apps/authentication-authorization)
-