高瀬博道の技術ブログ

高瀬博道の技術ブログです。

もう2023年になったので、今さらNestJSに入門しようと思う - その14

前回

takasehiromichiex.com

Guards

ガードは、CanActivateインターフェースを実装する、@Injectable()デコレータがつけられたクラスです。

ガードの責任は、実行時に存在する特定の条件 (パーミッション、ロール、アクセスコントロールリストなど) に応じて、特定のリクエストがルートハンドラによって処理されるかどうかを決定することにあります。

これは、承認と呼ばれることがあります。

承認は、通常Expressアプリケーションのミドルウェアによって処理されていました。

トークンの検証や、オブジェクトへのプロパティのアタッチなど、特定のルートコンテクストおよびそのメタデータと強く結び付けられているわけではないため、ミドルウェアは認証に適した選択肢です。

しかし、ミドルウェアはその性質上、次にどのハンドラが実行されるかがわかりません。

一方、ガードはExecutionContextインスタンスにアクセスできるため、次に何が実行されるかを正確に把握することができます。

これらは、例外フィルタ、パイプ、およびインターセプタと同様に、request/responseサイクルの正確な時点で処理ロジックを挿入し、宣言的に実行できるように設計されています。

ちなみに、ガードは、全てのミドルウェアの後、および、インターセプタやパイプの前に実行されます。

認可ガード

それでは、ガードを作成してみましょう。

$ nest g guard guard/auth

以下のファイルが作成されました、

src/guard/auth/auth.guard.ts
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Observable } from 'rxjs';

@Injectable()
export class AuthGuard implements CanActivate {
  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    return true;
  }
}
src/guard/auth/auth.guard.spec.ts
import { AuthGuard } from './auth.guard';

describe('AuthGuard', () => {
  it('should be defined', () => {
    expect(new AuthGuard()).toBeDefined();
  });
});

ガードを修正してみましょう。

src/guard/auth/auth.guard.ts
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Observable } from 'rxjs';

@Injectable()
export class AuthGuard implements CanActivate {
  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    const request = context.switchToHttp().getRequest();
    return validateRequest(request);
  }
}

function validateRequest(request: any): boolean | Promise<boolean> | Observable<boolean> {
  throw new Error('Function not implemented.');
}

validateRequest()のメソッドは、必要に応じて適宜修正できます。

全てのガードは、canActivate()メソッドを実装する必要があります。

このメソッドは、現在のリクエストが許可されているかどうかを示すブール値を返却する必要があります。

trueが返却された場合、リクエストは処理されますが、falseが返却された場合、Nestはリクエストを拒否します。

まとめ

ここまでで、

  • ガードについて
  • 認可ガードの実装

を学びました。

次回は、もう少しガードを掘り下げようと思います。

コード

今回のコードは、以下に格納しました。

github.com

takasehiromichiex.com