皆さん、こんにちは。
今回は「NestJSでロールベースの認可を実現する」について紹介させていただきます。
NestJSでロールベースの認可を実現するには、カスタムガードを作成し、ルートハンドラーに付与したメタデータをチェックする方法が一般的です。以下に、その基本的な定義方法とサンプルコードを示します。
RolesGuardの作成
RolesGuardは、NestJSのCanActivateインターフェースを実装し、リクエスト時にユーザのロール情報をチェックします。ガード内では、Reflectorサービスを利用して、エンドポイントに付与したロールメタデータを取得します。
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { Observable } from 'rxjs';
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private readonly reflector: Reflector) {}
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
// エンドポイントに設定されたロールメタデータを取得
const requiredRoles = this.reflector.get<string[]>('roles', context.getHandler());
// ロールが設定されていなければアクセスを許可
if (!requiredRoles) {
return true;
}
// HTTPリクエストからユーザ情報を取得(認証済みのユーザ情報が格納されている前提)
const request = context.switchToHttp().getRequest();
const user = request.user;
// ユーザが存在し、かつユーザのロールにrequiredRolesのいずれかが含まれているかチェック
return user && user.roles && requiredRoles.some(role => user.roles.includes(role));
}
}
Rolesデコレーターの作成
RolesGuardが参照するためのロール情報は、カスタムデコレーターで付与します。これにより、各ルートハンドラーで必要なロールを簡単に設定できます。
import { SetMetadata } from '@nestjs/common';
export const Roles = (...roles: string[]) => SetMetadata('roles', roles);
コントローラーでの使用例
作成したRolesGuardとRolesデコレーターを利用して、特定のエンドポイントにアクセス制限を実装します。
import { Controller, Get, UseGuards } from '@nestjs/common';
import { Roles } from './roles.decorator';
import { RolesGuard } from './roles.guard';
@Controller('cats')
@UseGuards(RolesGuard) // コントローラー単位でガードを適用
export class CatsController {
@Get()
@Roles('admin') // このエンドポイントはadminロールを持つユーザのみアクセス可能
findAll() {
// エンドポイントの処理
return 'This route is restricted to admins.';
}
}
解説
-
Reflectorの利用:
Reflectorサービスは、メタデータ(ここではroles)を取得するために使います。これにより、デコレーターで設定されたロール情報をガードで読み出すことができます。 -
リクエストのユーザ情報:
認証処理(例えばPassportを利用)によって、リクエストオブジェクトにuserプロパティが追加されている前提です。ここからユーザのロール情報(例:user.roles)を取得し、必要なロールと照合します。 -
柔軟な設計:
ロールが設定されていないエンドポイントはデフォルトでアクセスを許可するようにしているため、特に制限が不要なルートはそのまま利用できます。
このように、NestJSではカスタムガードとデコレーターを組み合わせることで、柔軟なロールベース認可を簡単に実装できます。各プロジェクトの要件に合わせて、ガードのロジックやエラーハンドリングをさらにカスタマイズすることも可能です。
今日は以上です。
ありがとうございました。
よろしくお願いいたします。