1必ず通す・必ず拒否する最小ガード
ガードの契約を最小単位で示す2つの実装です。canActivate() が true を返せば通過、false なら 403 で打ち切り、という2値の判定がガードのすべてであり、あらゆる認証・認可はこの上に乗ります。
import { CanActivate, ExecutionContext, Injectable } from "@nestjs/common";
@Injectable()
export class AllowAllGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
return true; // 通過 → ハンドラが実行される
}
}
@Injectable()
export class DenyAllGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
return false; // 拒否 → 403 Forbidden で打ち切り
}
}
// true / false を返すだけ、がガードの契約のすべて
2APIキーガード
リクエストヘッダの API キーを照合する実践的なガードです。context からリクエストを取り出してヘッダを見る、というガードの定番の体の動きを示します。社内ツールや外部連携 API で手軽に使われる認証方式です。
import { CanActivate, ExecutionContext, Injectable } from "@nestjs/common";
@Injectable()
export class ApiKeyGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
// ガードはまずリクエストを取り出すところから始まる
const request = context.switchToHttp().getRequest();
const apiKey = request.headers["x-api-key"];
return apiKey === process.env.API_KEY;
}
}
// curl -H "x-api-key: ..." を付けたリクエストだけが通過する
3canActivate の判定をプレーンTSで再現
「判定関数が false なら 403、true ならハンドラへ」というガードの動きをプレーン TypeScript で再現した例です。フレームワークがやっているのは、ハンドラの手前にこの if 文を自動で差し込むことだと分かります。
TypeScript
4適用範囲の3段階
ガードをハンドラ単位・コントローラ単位・アプリ全体のどこに掛けるかの使い分けです。実務では「全体に認証ガード + 公開エンドポイントだけ例外」の構成が多く、適用範囲の設計が認証設計そのものになります。
import { Controller, Get, UseGuards } from "@nestjs/common";
import { AuthGuard } from "./auth.guard";
@Controller("articles")
export class ArticlesController {
@Get("drafts")
@UseGuards(AuthGuard) // ① ハンドラ単位: 下書きはログイン必須
findDrafts() {
return [];
}
@Get() // 公開記事一覧は誰でも見られる
findAll() {
return [];
}
}
// ② コントローラ単位: @Controller の上に @UseGuards(...)
// ③ アプリ全体(main.ts): app.useGlobalGuards(new AuthGuard())
5ロールによる認可ガード
「ログインしているか(認証)」の次に来る「その操作をしてよいか(認可)」を担当するガードです。認証処理が request.user を設定済みという前提でロールを調べる、管理者専用 API の実務定番パターンです。
import { CanActivate, ExecutionContext, Injectable } from "@nestjs/common";
@Injectable()
export class AdminGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest();
// 先に動く認証処理が request.user を設定済み、という前提
const user = request.user;
return user !== undefined && user.role === "admin";
}
}
// 適用例: 管理画面系のコントローラにまとめて掛ける
// @Controller("admin")
// @UseGuards(AdminGuard)
// export class AdminController { ... }