認証モジュール
モジュールパス: /alier_sys/Auth.js
概要
認証処理をサポートするユーティリティモジュールです。開発者は認証処理の実装を気にすることなく認証機能をアプリケーションに組み込めます。
基本的な使い方
認証エージェントを作成してログインを呼び出すまでの流れは以下の通りです。
const agent = new AuthAgent({
id: "any-id",
protocols: new DigestProtocol({
host: "example.com",
path: "/login",
method: "GET",
getCredentialsCallback: (envelope) => {
Alier.Model.auth.eventHandler.post(envelope);
},
challengeTimeoutDelay: 3_000,
challengeInterval: 1_000,
})
});
const { ok, code } = await agent.login({ retryUnauth: true });
- 1行目で認証エージェントを作成しています。引数は
id
と認証プロトコルです。id
は認証エージェントの識別子であり、認証エージェント登録/取得インターフェースで使用されます。- 認証プロトコルには Alier が標準で提供している Digest 認証プロトコルを渡しています。Digest 認証プロトコルの引数は以下の通りです:
- Digest 認証を実施する上で必要な情報(接続先のエンドポイントなど)を持つオブジェクト。
- ユーザのクレデンシャル[^credentials]を取得するためのコールバック関数。イベントハンドラを利用してプロミスのラッパーである envelope をイベントリスナに渡しています。
- タイムアウト時間(ミリ秒)。4. のインターバルより長く設定してください。
- チャレンジを試行する間隔(ミリ秒)。3. のタイムアウトより短く設定してください。
- 15 行目で認証エージェントのログインを呼び出し、成功または失敗の処理結果と失敗コードを取得しています。
終了コード
agent.login()
の戻り値の終了コード code
のうち、共通のコードは以下の通りです。
コード | 意味 |
CANCELLED | コールバックで渡された envelope で discard を呼ばれた |
TIMEOUT | タイムアウト |
ABORT | その他中断命令をキャッチ |
他にもプロトコルごとに認証評価に失敗した場合などのコードがあります。
認証エージェント登録/取得インターフェース
レストフルオブジェクトで認証を使用するために Auth.js には認証エージェント登録、取得できるインターフェイス `AgentRepository が用意されています。
import { AgentRepository } from "/alier_sys/Auth.js";
// 登録
AgentRepository.registerAgent(new AuthAgent({ id: "any-id", protocols: new AnyProtocol() }));
// 取得
const agent = AgentRepository.pickAgent("any-id");
サンプルコード
ProtoViewLogic を交えたサンプルコード
ProtoViewLogic
を交えたサンプルコードです。
// クレデンシャル入力を管理するProtoViewLogic
class InputCredentialsVL extends ProtoViewLogic {
// 入力情報をログイン処理に渡すための関数
#submit;
// ログイン処理に入力がキャンセルされたことを通知するための関数
#cancel;
// クレデンシャルを渡したり、ログイン処理完了を受け取るためのプロミスラッパー
#envelope;
async messageHandler(msg) {
return await msg.deliver({
init: () => {
// 入力情報をプロミスに結び付けるresolve/rejectを更新する
Alier.Model.auth.update.addListener((envelope) => {
this.#envelope = envelope;
});
Alier.View.attach(this);
},
// 入力された情報を送信する
submit: async (msg) => {
// パラメータにユーザ名とパスワードが挿入されている
const credentials = {
username: msg.param.username,
password: msg.param.password
};
// 処理の完了を受け取るプロミスラッパー
const envelope = new Envelope();
// 入力待ちをクレデンシャルとプロミスラッパーで解決する
this.#envelope.post({ credentials, envelope });
// envelope はオプショナルなので渡さなくてもよい
// this.#envelope.post({ credentials });
// プロミスラッパーを入れ替える
this.#envelope = envelope;
},
// 入力待ちをキャンセルする
cancel: async () => {
const err = new Error("cancelled to input credentials");
// ログイン処理を中断する
this.#envelope.discard(err);
},
});
}
}
const vl = new InputCredentialsVL();
// 認証処理を実行するエージェント
const agent = new AuthAgent({
id: "any-id",
protocols: new DigestProtocol({
host: "example.com",
path: "/login",
method: "GET",
getCredentialsCallback: (envelope) => {
Alier.Model.auth.update.post(envelope);
},
}),
challengeTimeoutDelay: 5_000,
challengeInterval: 1_000,
});
// ログインを実行
// ok: ログイン成功または失敗を示す真偽値
// code: ログイン失敗時の失敗理由を表す失敗コードの文字列
const { ok, code } = await agent.login();
// ログイン成功
if (ok) {
// ログイン成功時の処理
}
// 入力キャンセル
if (code === "CANCELLED") {
// 入力キャンセル時の処理
}
// ...その他、入力情報が間違っているなどでログイン失敗
自動ログイン
起動時などでユーザ名とパスワードがすでに分かっている場合、ユーザ名とパスワードを自動取得するイベントリスナーをイベントハンドラーに追加することで自動ログインを実現できます。
class MyModel extends AlierModel {
#agent;
#eventHandler
constructor() {
super();
return this.initialize(() => {
this.#agent = new AuthAgent({
id: "any-id",
protocols: new DigestProtocl({
host: "http://example.com",
path: "/auth",
method: "GET",
getCredentialsCallback: (envelope) => {
this.#eventHandler.post(envelope);
},
challengeTimeoutDelay: 3_000,
challengeInterval: 1_000,
}),
});
});
}
async login() {
// ユーザ名とパスワードを自動取得するイベントリスナー
const listener = (envelope) => {
const { username, password } = ...; // ユーザ名とパスワードを何かしらの方法で取得
envelope.post({ credentials: { username, password } });
};
this.#eventHandler.addListener(listener);
// 認証に失敗したときはクレデンシャルの再入力がないので retryUnauth は false にする
const { ok, code } = await this.#agent.login({ retryUnauth: false });
// クレデンシャルの自動取得による自動ログインを無効化したい場合はリスナーを削除する
this.#eventHandler.deleteListener(listener);
}
}
warning
イベントハンドラーに ユーザ入力用のイベントリスナー がないか注意が必要です。
機能一覧
汎用機能
AuthAgent
--- 認証処理をとりまとめるエージェント機能。AgentRepository
--- 認証エージェントの登録/取得インターフェース。
Digest 認証
DigestProtocol
--- 認証プロトコルDigestAuthKey
--- 認証情報
インターフェースクラス
IAuthAgent
--- 認証処理を取りまとめるエージェント機能。IAuthProtocol
--- 認証プロトコル。AuthEntity
--- 認証情報を保持する。IAuthKey
--- 認証情報。AuthError
--- 認証エラー。
機能の関係性
---
config:
class:
hideEmptyMembersBox: true
fontSize: 8px
---
classDiagram
AgentRepository "1" o-- "*" AuthAgent : エージェントを集約
AuthAgent "1" *-- "1..*" IAuthProtocol : プロトコルでエージェントを構成
IAuthProtocol "1" ..> "1" AuthEntity : エンティティ
AuthEntity "1" ..> "1" IAuthKey : 認証情報