no versions found for AlierOnNodeReferences / auth/abstractauthprotocol_verify / en

AbstractAuthProtocol: verify()

リクエストに付与されている認証情報を検証して、リクエストを受諾するか棄却するかを判定します。

この関数は非同期関数です。

構文

authProtocol.verify(request) => Promise<{ ok[, status][, reason][, scheme] }>

引数

  • request: http.IncomingMessage | { method, path, body, headers, query }

    検証する対象のリクエストです。オブジェクトだった場合、以下のプロパティを持ちます:

    • method : string

      メソッド名を表す文字列です。

    • path: string

      リクエストされたパスを表す文字列です。

    • body: string | Buffer | { [key: string]: number | string | boolean | object | Uint8Array | null }

      リクエストのボディです。Content-Type リクエストヘッダの値によって型が異なります。

      Content-Type リクエストヘッダの値
      -- --
      text/* string
      application/json { [key: string]: number | string | boolean | object | null }
      multipart/form-data { [key: string]: number | string | boolean | object | Uint8Array | null }
      application/x-www-urlencoded { [key: string]: string }
      その他のコンテンツ形式 Buffer
    • headers: { [header_name: string] : { value, params }[] }

      リクエストのヘッダをパースしたオブジェクトです。

      プロパティ名 header_name は小文字変換されたリクエストヘッダ名(例: "content-type")です。

      各プロパティ値は対応するリクエストヘッダ行をまとめたの配列であり、配列成分は単一のヘッダ行を表しています。

      各ヘッダ行は専用のパーサによって valueparams の2つプロパティを持つオブジェクトに変換されます。

      • value: string

        そのヘッダの主要な を表す文字列であり、常に設定されます。

      • params: { [param_name: string]: string }?

        そのヘッダに許される必須でないパラメタが設定されます。パラメタの指定がなかった場合は params プロパティ自体が null となります。

    • query: { [param_name: string]: any }

      リクエストのクエリパラメタです。

返値: Promise<({ ok, status, reason, scheme })>

検証結果です。

  • ok: boolean --- 検証に成功した場合は true、そうでなければ false です。。
  • status: number | undefined --- 検証に失敗した場合のレスポンスのステータスコードです。
  • reason: any | undefined --- 検証に失敗した理由です。
  • scheme: string | undefined --- 検証を実行した認証方式名です。

const { IncomingMessage }      = require("node:http");

const { Router }               = require("@suredesigns/alier/Router");
const { WebApi }               = require("@suredesigns/alier/WebApi");
const { AbstractAuthProtocol } = require("@suredesigns/alier/Auth");

/* 何かの認証プロトコルの実装 */
class MyAuthProtocol extends AbstractAuthProtocol {

    async verify(request) {
        if (request === null || typeof request !== "object") {
            return {
                ok    : false,
                scheme: this.scheme,
                status: 400,
                reason: {
                    error            : "invalid_request",
                    error_description: "malformed request"
                }
            };
        }

        if (request instanceof IncomingMessage) {
            /* IncomingMessage 用の処理 */
            const authz = request.headers.authorization;

            if (authz == null) {
                return {
                    ok    : false,
                    scheme: this.scheme,
                    status: 401,
                    reason: {
                        error            : "invalid_token",
                        error_description: "unauthorized"
                    }
                };
            }

            const { scheme, token68, params } = /* authz を scheme, token68, params に分割 */;

            /* Authorization ヘッダの検証の実装 */

            if (/* 認証成功条件 */) {
                return { ok: true };
            } else if (/* 401 Unauthorized を返す条件 */) {
                return {
                    ok    : false,
                    scheme: this.scheme,
                    status: 401,
                    reason: {
                        error            : "invalid_token",
                        error_description: "unauthorized"
                    }
                };
            } else if (/* 403 Forbidden を返す条件 */) {
                return {
                    ok    : false,
                    scheme: this.scheme,
                    status: 403,
                    reason: {
                        error            : "insufficient_scope",
                        error_description: "permission denied"
                    }
                };
            } else {
                return {
                    ok    : false,
                    scheme: this.scheme,
                    status: 404,
                    reason: {
                        error            : "invalid_request",
                        error_description: "bad request"
                    }
                };
            }
        } else {
            /* 一般の非 null オブジェクト用の処理 */
            const authz = request.headers.authorization?.[0];

            if (authz == null) {
                return {
                    ok    : false,
                    scheme: this.scheme,
                    status: 401,
                    reason: {
                        error            : "invalid_token",
                        error_description: "unauthorized"
                    }
                };
            }

            const { scheme, token68, params } = /* authz を scheme, token68, params に分割 */;

            /*  以下同上  */
        }
    }
}

const my_protocol = MyAuthProtocol();

//  認証処理を実装した WebApi クラスのインスタンス
//  このクラスは GET メソッドを受け付ける、Web認証を要求する WebApi を生成する。
//  MyAuthProtocol で実装した verify() は WebApi の基底クラス WebEntity が提供する verify() から呼び出される。
const my_api = new class MyApi extends WebApi {
    constructor() {
        super({
            path         : "/api/which/requires/authorization",
            authProtocols: [ my_protocol ]
        });
    }

    async get(params) { /* GET  メソッドの実装 */ }
};

//  Router を生成; リクエストおよびレスポンスの処理を行う
donst router = new Router();

//  WebApi を Router に登録する
router.enable(my_api);

//  リクエストの受付を開始する
router.listen(/* 使用可能なポート番号 */);

解説

関数 verify()WebEntity::verify() 関数の中で呼び出されます。

WebEntity のコンストラクタ引数 o.authProtocols には複数の AbstractAuthProtocol インスタンスを含めることができますが、どの認証プロトコルの実装が使われるかは、Authorization リクエストヘッダのスキーム名が認証プロトコルのプロパティ scheme に一致するかどうかで判断されます。スキーム名が一致したプロトコルに対して、そのプロトコルが実装する関数 verify() が呼び出されます。