Alternative Architecture DOJO

オルターブースのクラウドネイティブ特化型ブログです。

Azure Static Web Appsの認証機能でログイン処理を実装する

こんにちは、MLBお兄さんこと松村です。
前回の記事に引き続き、未だに MLB のロックアウトは終わっていません。キャンプインはまだ先になりそうです涙


SPA のホスティングに適している Azure Static Web Apps の勉強を兼ねて、自分自身にだけ必要な Web サイトを作っています。
自分だけがアクセスできる仕組みは別途記事を書こうと思いますが、今回は Azure Static Web Apps の認証・承認の機能でログイン処理を簡易的に実装する流れを紹介します。

認証と承認

Static Web Apps には認証と承認のための機能が提供されています。

詳細についてはドキュメントを読んでいただきたいですが、標準でサポートしている ID プロバイダーは3種類あります。

  1. Azure Active Directory
  2. GitHub
  3. Twitter

また、承認は「ロール」という情報がアクセス時にユーザーに付与されます。
認証前の状態は「匿名(anonymous)」ロールとなり、何らかの ID プロバイダーで認証を済ませた状態は「認証済み(authenticated)」となります。
当然ですが、認証を前提としたページは authenticated ロールが必要で、匿名アクセスをすると HTTP 401 となります。

認証の構成

上記3つの ID プロバイダーであれば、認証の構成を行う必要はありません。
ID プロバイダーごとにログイン用エンドポイントが用意されており、アクセスするだけで認証のフローが始まります。

  1. Azure Active Directory ... /.auth/login/aad
  2. GitHub ... /.auth/login/github
  3. Twitter ... /.auth/login/twitter

その他、細かな構成は staticwebapp.config.json ファイルに定義することができます。

docs.microsoft.com

少しずつ認証を構成してみる

サンプルコード

下記の HTML を例とします。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>Vanilla JavaScript App</title>
</head>
<body>
  <h1>Vanilla JavaScript App</h1>
  <p>Hello <span id="username"></span>.</p>
</body>
</html>

ローカル環境で Static Web Apps の認証機能を利用する場合は、Static Web Apps CLI で実行しましょう。
上記の HTML ファイルが app ディレクトリにあるとすると、下記のコマンドを実行します。

$ swa start app

ログインリンクの設置

前述した ID プロバイダーごとのログイン用エンドポイントにアクセスするためのリンクを設置します。
今回は GitHub アカウントでログインするためのリンクを書きます。

<p><a href="/.auth/login/github">Login with GitHub</a></p>

ログイン用エンドポイントにアクセスすると、ローカル環境では下図のような画面が表示されます。
実際に GitHub ログインが行われるわけではなく、テスト用の認証情報を入力することができます。

ユーザー情報を取得する

認証を済ませたユーザー情報は /.auth/me というエンドポイントに取得することができます。
fetch 関数などでエンドポイントに GET リクエストを行うと、JSON でデータが返ってきます。詳しくはドキュメントにまとまっています。

docs.microsoft.com

fetch('/.auth/me')
  .then(response => response.json())
  .then(json => {
    console.log('json', json);
    document.getElementById('username').innerText = json.clientPrincipal.userDetails;
  })
  .catch(error => console.log('error', error));

エンドポイントをそれっぽくする

エンドポイントは /.auth/login/github のままでもいいですが、GitHub に限ったものですし、できれば /login のように分かりやすくしたいです。
staticwebapp.config.json でルートの構成をします。

{
  "routes": [
    {
      "route": "/login",
      "redirect": "/.auth/login/github"
    }
  ]
}

ついでにログインリンクも変更しましょう。

<p><a href="/login">Login with GitHub</a></p>

ページを認証必須にする

認証必須であれば、ログインリンクではなく構成として認証必須としちゃいましょう。
staticwebapp.config.json をこちらの構成とします。

{
  "routes": [
    {
      "route": "/login",
      "redirect": "/.auth/login/github"
    },
    {
      "route": "/",
      "allowedRoles": ["authenticated"]
    }
  ]
}

この構成は「ログインさせる」というよりは、ルートページにアクセスできるのが「認証済み(authenticated)ロール」に限定すると理解すると良いでしょう。

ログインしていない状態でページにアクセスすると、そのセッションでは authenticated ロールをもっていないため、HTTP 401 となります。

HTTP 401 のときにログインページに遷移させる

HTTP 401 ページが表示されていたところで、ユーザーはログインすることができません。
なので HTTP 401 となったときに、強制的にログインページへリダイレクトさせましょう。
例によって staticwebapp.config.json を変更し、こちらの構成とします。

{
  "routes": [
    {
      "route": "/login",
      "redirect": "/.auth/login/github"
    },
    {
      "route": "/",
      "allowedRoles": ["authenticated"]
    }
  ],
  "responseOverrides": {
    "401": {
      "redirect": "/login",
      "statusCode": 302
    }
  }
}

docs.microsoft.com

これで自動的にログインページに遷移させることができました。

ログアウトリンクの設置

ログインを実装したので、ログアウトも実装しておきましょう。
/.auth/logout にアクセスすることでログアウトを行うことができます。

docs.microsoft.com

staticwebapp.config.json にてログアウト用のエンドポイントを構成し、HTML にリンクを設置します。

{
  "routes": [
    {
      "route": "/login",
      "redirect": "/.auth/login/github"
    },
    {
      "route": "/",
      "allowedRoles": ["authenticated"]
    },
    {
      "route": "/logout",
      "redirect": "/.auth/logout"
    }
  ],
  "responseOverrides": {
    "401": {
      "redirect": "/login",
      "statusCode": 302
    }
  }
}
<p><a href="/logout">Logout</a></p>

デプロイして動作確認

これまでのコードを Azure Static Web Apps にデプロイし、動作を確認してみます。
ローカル環境と異なるのは、ログインエンドポイントにアクセスすると、実際に ID プロバイダーのアカウントを使用する点です。(そりゃ当然)
今回は GitHub のアカウントを使うため、このような画面が表示されます。(一度認証を実行すると、以降は表示されません。)


Azure Static Web Apps の機能だけでログインにまつわる処理を実装することができました。
次回は自分だけがアクセスできる仕組みを書こうと思います。

www.alterbooth.com

www.alterbooth.com

cloudpointer.tech