Auth0 by Okta(以下、Auth0)は、堅牢なツールと機能のセットを提供し、アプリケーションの認証と認可を強化できます。その機能の1つがAuth0 Actionsです。Auth0 Actionsは、Auth0プラットフォームの動作をカスタマイズし拡張できます。この記事では、Auth0 Actionsを使って、拒否リストや許可リストなどの特定の条件に基づき、ログインリクエストを許可または拒否する方法についてご説明します。
前提条件
作業を実施する前に、次の前提条件を満たしておく必要があります。
- Auth0アカウント: アカウントを持っていない場合は、無料のAuth0アカウントを作成してください。
- 基本的なJavaScriptの知識: Auth0 Actionsは、JavaScriptを用いてロジックを記述します。この記事では、その実装例をご紹介します。個別ユースケースに合わせてさらにカスタマイズするには、JavaScriptの基本的な知識が必要になります。
新しいアクションを作成
はじめにAuth0 Actionを新規に作成します。Auth0 Actionsは、安全なAuth0環境で実行されるサーバーレス関数です。
Auth0 Actionを作成するには、Auth0ダッシュボードにログインし、左サイドバーからActions - Flowsを選択します。このページでは、カスタマイズできるさまざまなフローが表示されています。今回のユースケースでは、ログインフローを選択します。
選択後にログインフローページが表示され、Actionのインストール、作成、追加ができます。
画面には2つの主要セクションがあります。ページ中央ではログインフローを図示しており、右側はActionsパネルとなっています。
デフォルトのログインフローには、次の2つの状態が含まれています。
- Start: ユーザーはログイン情報を入力済みで、ログインの準備ができている状態
- Complete: ユーザーの認証情報(IDトークンと、必要に応じてアクセストークン)を発行した状態
この2つの状態の間でActionをドラッグ&ドロップし、ログインフローに対してカスタムロジックを追加できます。その一例として、トークンを発行する前にログインリクエスト拒否できます。
右のパネルには、2つのタブを持つActionsパネルがあります。
- Installed: Auth0 Actions MarketplaceからインストールされているActions
- Custom: このテナント用に作成されたActions
Auth0 Actionを作成するには、Actionsパネルで+(プラス)アイコンをクリックし、Build Customを選択します。
モーダルウィンドウには作成するAuth0 Actionの情報を入力します。今回は名前を「Validate User Login(ユーザーログインを検証)」としました。トリガーとランタイムはデフォルト値のままにしておきます。
Createをクリックすると、Auth0 Actionのコードエディターが表示されます。ここでは、コードの記述や依存関係パッケージのインストール、テストが可能です。
今回のAuth0 Actionでは、2つのJavaScript関数を使用し、ログインフローを変更できます。
onExecutePostLogin
: Auth0が検証したログイン認証情報をユーザーが提供した直後に何が起こるべきかを定義します。このメソッドは2つのパラメータ、event
およびapi
を受け取ります。event
: ユーザーやコンテキストのような、ログインリクエストに関する詳細を含むオブジェクトapi
: ログインの動作を操作するメソッドを含むオブジェクト
onContinuePostLogin
: 他のWebページにリダイレクトされた後、制御がAuth0 Actionに戻ったときの動作を定義します。これは、リダイレクトされた後にユーザーが戻ってきた場合にのみ使われるため、デフォルトではコメントアウトされています。
この記事では、onExecutePostLogin
関数に焦点を当てます。
拒否リストの利用
拒否リストは、特定のユーザーやIPアドレスからのログインをブロックする一般的な方法です。Auth0 Actionsを使用して拒否リストを実装するために、event
パラメータを通じて提供されるコンテキストを活用できます。event
オブジェクトには、ユーザーの詳細やIPアドレスなど、受信した認証リクエストに関する情報が含まれています。このオブジェクトにアクセスし、拒否リストと値を比較することで、認証リクエスト拒否などの適切な処理を実行できます。
拒否リストを使用したコードを実装する前に、ユーザーのログインリクエストをキャンセルする方法を知っておく必要があります。この場合はapi
パラメータを使用できます。
api.access.deny('reason');
このたった1行のコードで、ログインリクエストを拒否できます。deny
メソッドではreason
という1つのパラメータを使用します。このパラメータには、拒否の説明を記述します。
拒否リストに対応できるよう関数をアップデートしてみましょう。
// Array containing the email addresses that are blocked from logging on.
const denyList = ['myemail@example.com']
exports.onExecutePostLogin = async (event, api) => {
if (denyList.find(email => email === event.user.email)) {
api.access.deny("Your email address is blocked from logging in to our systems.");
}
};
この関数では、システムへのログインを禁止するEメールアドレスのリストがハードコーディングされています。onExecutePostLogin
は、ログインイベントにおいて入力されたユーザーのEメールアドレスがリストに含まれているかどうかを検証し、含まれている場合はユーザーのアクセスを拒否します。
Auth0 Actionのエディタでコードを追加した後はテストを実施します。開発モードでテストする最善の方法は、テストパネルを使うことです。以下に示すように、エディタのサイドバーにある再生ボタンをクリックすると、テストパネルにアクセスできます。
パネルを展開し、テスト用のイベントオブジェクトを必要に応じてカスタマイズできます。例えばuser
オブジェクトにはgiven_name
など、すべてのユーザープロパティが含まれていますが、今回のユースケースで重要なのはemail
です。
テストパネルの下部にあるRunボタンをクリックすると、Auth0は与えられたデータに対してAuth0 Actionを実行し、テスト結果をテスト結果ウィンドウに出力します。指定されたユーザーが拒否リストにない場合、次のようなテスト出力が表示されます。
JSONを更新し、拒否されたユーザーのEメールアドレスの1つを含めると、次のようなテスト出力が示されます。
テストを完了した後、関数をデプロイしログインフローへ追加できるようにします。
許可リストの利用
一方、許可リストは、ログインを確実に許可されているユーザーまたはIPアドレスを指定します。拒否リストを扱うのと同じように、event
オブジェクトを使って必要な情報にアクセスできます。許可リストと値を比較し、ユーザーまたはIPアドレスがリストにある場合のみ、ログインフローを進めます。そうでない場合は、認証リクエストを拒否し、アクセスを拒否できます。
拒否リストと同様に、許可リストはdeny
メソッドを使って、許可リストに含まれるユーザーからのリクエスト以外のすべてのリクエストを拒否します。
新しいコードは次のとおりです。
// Array containing the email addresses that are allowed to log in.
const allowList = ['myemail@example.com', 'j+smith@example.com']
exports.onExecutePostLogin = async (event, api) => {
if (!allowList.find(email => email === event.user.email)) {
api.access.deny("Your email address is not authorized to log into our systems.");
}
};
更新したコードでテストを実行すると、リストに基づいたログインの許可を確認できます。
APIにリストを移譲
拒否リストや許可リストに多くの項目がある場合、データベースやAPIなどの外部システムにリストを保存して管理した方法が実用的です。Auth0 Actionsではリストの取得と検証を外部APIに移譲できます。この場合はコード内で外部のAPIに対してリクエストを行い、その結果からユーザーのステータスを検証して認証リクエストを拒否または許可します。
この記事では、Eメールアドレスを受け取り、そのアドレスがアクセス許可されているかどうかを返すAPIエンドポイントがすで存在していると仮定します。
こちらがAPIの例です。
curl https://myaccessapi.com/users/is_authorized?email=myemail@example.com
{
is_authorized: false
}
このシンプルな例を踏まえて、コードを更新します。
const axios = require('axios');
exports.onExecutePostLogin = async (event, api) => {
const auth_result = await axios.get(`https://myaccessapi.com/users/is_authorized?email=${event.user.email}`)
if (!auth_result.is_authorized) {
api.access.deny("Your email address is blocked from logging in to our systems.");
}
};
外部のAPIを呼び出すにはあらかじめAuth0 Actions環境で利用可能となっているaxios
ライブラリを使用できます。他の依存関係を利用したい場合は、Auth0 Actionsのバンドルの一部としてnpm依存関係を追加できます。公式ドキュメントではAuth0 Actionsの依存関係についてより詳しく学べます。
ログインフローにAuth0 Actionを追加
Auth0 Actionsを実装し、テストを終えた後、デプロイを実行し、ログインフローの一部として使用しましょう。テスト結果に問題がなければ、画面右上のDeploy
ボタンをクリックします。実装されているコードと設定からログインフローで利用できる関数のスナップショットが作成されます。
関数の実装を変更した場合、変更箇所はすべて自動的に新しい下書きとして保存されます。この変更を反映する場合は、最新バージョンをデプロイする必要があります。
コードをデプロイしても、対象のAuth0 Actionがログインフローの一部として使われるわけではありません。ログインフロー画面に戻り、フロー図を参照してください。Auth0 Actionがフローの一部として表示されていない場合は、Auth0 Actionが、まだアクティベートされていないことを意味します。フローの一部としてAuth0 Actionをアクティブにするには、ActionsパネルのCustomタブから追加したいAuth0 ActionをStartからCompleteまでのステップの間で、ドラッグ&ドロップします。その後、画面右上のApplyボタンで変更を適用します。
まとめ
この記事では、Auth0 Actionsを活用してログインリクエストを許可または拒否する方法について説明しました。拒否リストや許可リストを使うことで、アプリケーションのセキュリティを強化し、特定の基準に基づいてアクセスを管理できます。また、リスト管理を外部APIに移譲するとスケーラビリティと柔軟性が得られる点についても説明しました。Auth0 Actionsを使用すると、ログインフローをカスタマイズし、アプリケーションにセキュリティの新たな層を加えることができます。
この記事の中で紹介した例は、最適なスタート地点です。次のステップとしてニーズに合わせてさらにカスタマイズが可能です。例えばEメールの代わりに、ドメインによる許可/拒否リスト、IPアドレス、国、曜日、時間などを判定材料にできます。
実装の際は常にテストしたうえで、アプリケーションに必要な要件について特殊なケースも含めて考慮する必要があります。Auth0 Actionsを効果的に使用すると、ユーザーに確実で安全な認証を提供できます。