0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

React × NestJS × FirebaseAuthで作りながら理解する認証(前編)

Last updated at Posted at 2025-08-09

フロントエンドエンジニアとして働いていながら、認証/認可がイマイチわかっていなかった私。

Chat GPTに相談しながらReact × NestJS × FirebaseAuthで簡単な認証/認可の流れを実装しながら確認しました。

  • この記事のコードの一部はChat GPTが書いたものが含まれています
  • 文章の一部もChat GPTに相談して解説してもらったものが含まれています
  • 記事の全体的な構成は、筆者と同じように認証/認可がよくわからない人向けに、筆者が考えて構成したものです

認証とは

認証とは、「ユーザーが本人であること」を証明する仕組みです。
今回はFirebase Authenticationを使ってその"証明書”となる IDトークンを発行し、Nest.js側でそのトークンを検証します。

認証はほとんどのアプリで実装されている機能です。
たとえばQiitaでもマイページの表示、投稿の編集などは、ログインしているユーザー本人だけが操作できるようにする必要がありますよね。
この「本人確認」の仕組みが認証です。

今回実装する認証の流れ

今回実装する認証は、以下のような流れを想定しています。

  1. フロント側でメールアドレスやGoogleアカウントなどでログインを行う
  2. Firebase AuthenticationがIDトークン(JWT)を発行する
  3. NestJS側でIDトークンを検証する
  4. 検証がOKなら続きの処理を行う
  5. 処理結果をレスポンスとして返し、フロントは画面に結果を表示する

🛠 実装のステップ

▪️前編(今回はここまで)

前編では先ほどの処理の流れの3、4を実装します。
バックエンド側での「認証」機能を作成します。

  1. Firebaseの環境構築
  2. NestJSでバックエンドを構築
  3. AuthGuard の作成(IDトークンのJWT検証)
    a. これで「認証」を行う

▪️後編

後編はフロントエンド側でログインし「IDトークン」を取得し、結果を表示します。

  1. フロントでの ID トークン取得ユーティリティ作成
    a. 「認証」はバックエンド側で行いますが、利便性のためフロントでも検証
  2. フロント画面でのログイン表示

1. Firebaseの環境構築

まずはFirebaseの環境を構築します!

セットアップ

Firebaseをプロジェクトにインストールします。

npm install firebase

Firebaseコンソールにログインしてプロジェクトを構築します。コンソール画面から「Firebaseプロジェクトを作成する」ボタンを押下します。

基本的には画面に沿って設定するだけですが、選択肢がある場合は以下の通り設定します。

  • 今回はWebアプリとしてプロジェクトを作ります
  • Firebase Hostingも設定
  • すでにViteでアプリを構築済みなので「Use an existing project」を選びます
  • デプロイ用のディレクトリは「dist」に設定します(Viteでビルドした時の初期設定に合わせる)

デプロイしてみる

セットアップができたらFirebaseをデプロイしてみます。

# アプリをビルドします
npm run build
# Firebaseをデプロイします
firebase deploy

コンソールにHosting URLが表示されるので、クリックして画面が表示されたら基本的な構築は完了です!🥳

2. NestJSでバックエンドを構築

APIで送られたリクエストが「本人かどうか」をバックエンド側で検証するロジックを構築します。

具体的には、APIが呼ばれたときにNestJSのAuthGuardという仕組みを使って、リクエストに含まれるIDトークン(JWT)を検証します。

検証がOKなら「認証済み」として処理を進めます。逆にNGの場合は401 Unauthorizedエラーを返し、不正なアクセスをブロックします。

バックエンドのプロジェクトを作成

NestJSのプロジェクトを作成します。

# Nest CLIがなければインストール
npm install -g @nestjs/cli

# 新規プロジェクト作成(backendフォルダに)
nest new backend
cd backend
npm install

Firebase Admin SDKのセットアップ

まずはFirebaseのサービスアカウントキーをFirebaseコンソールから取得します。

  1. Firebaseコンソールを表示
  2. 歯車マークを押下
  3. 「プロジェクトの設定」
  4. 「サービスアカウント」タグ
  5. 「新しい秘密鍵を生成」
  6. jsonファイルをダウンロード

サービスアカウントキーは秘密鍵です。これはGithubの公開リポジトリなど、不特定多数から見られないように管理します。

取得したサービスアカウントキーを保存

取得したサービスアカウントキーをプロジェクトルート/src/var/secrets/ディレクトリを作成して保存します。
/var/secrest/ディレクトリは.gitignoreに追加しておきましょう。

環境変数を追加

backendディレクトリに.envファイルを追加します。
この.envファイルに環境変数を追加し、先ほどのサービスアカウントキーの絶対パスを渡します。

.env
GOOGLE_APPLICATION_CREDENTIALS=絶対パス

環境変数を扱う便利ライブラリ

cd backend # バックエンドプロジェクトのルートへ
npm install @nestjs/config

backend側のapp.module.tsnestjs/configを読み込む

app.modules.ts
import { ConfigModule } from '@nestjs/config';

@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true }),
  ],
  // そのほかの設定
})
export class AppModule {}

Firebase Admin SDKを設定する

Firebase Adminをインストールします。
Firebase AdminはFirebaseの“サーバーサイド専用”SDKで、今回作る認証のほか、データベースの機能などが使えます。

npm install firebase-admin

初期設定

backendディレクトリ直下にfirebase-admin.tsを作成します。
ここで先ほど環境変数に設定したサービスアカウントキーの登録処理が必要ですが、nestjs/configを使うと自動的に読み込んでくれます。

firebase-admin.ts
import * as admin from 'firebase-admin';

// nestjs/configがあれば.envファイルから勝手に環境変数を読み込んでくれる
admin.initializeApp(); 

3. 認証機能の作成

いよいよ認証機能を作ります!
Nest.jsにはCanActivateというインターフェースがあります。このインターフェースは「このリクエストを処理していいかどうか」を判定する仕組みです。

これを実装し、Nest.jsの仕組みであるDI(依存性注入)して使います。

IDを検証する関数を作る

IDを検証する仕組み自体はfirebase-adminにすでにあります。tokenを受け取って検証するだけの関数です。

firebase-admin.ts
import * as admin from 'firebase-admin';

// 初期化
admin.initializeApp();

/**
 * トークン(JWD)を検証する
 * @param token 
 */
export const verifyIdToken = (token: string) =>
  admin.auth().verifyIdToken(token);

AuthGuardを作る

ここのポイントは3つです。

  1. @Injectable()
  2. CanActivate
  3. HTTPヘッダーからBearerトークンを取得して検証
firebase-auth.guard.ts
import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common';
import { verifyIdToken } from './firebase-admin';

@Injectable()
export class FirebaseAuthGuard implements CanActivate {
  async canActivate(context: ExecutionContext): Promise<boolean> {
    // HTTPリクエストからauthorizationヘッダーを取得して検証する
    const req = context.switchToHttp().getRequest();
    const authHeader = req.headers.authorization || '';
    const token = authHeader.replace('Bearer ', '');
    if (!token) throw new UnauthorizedException('No token');
    try {
      // Firebase Adminで検証
      const decoded = await verifyIdToken(token);
      req.user = decoded;
      return true;
    } catch {
      // 検証してNGの場合はエラーを投げる
      throw new UnauthorizedException('Invalid token');
    }
  }
}

ポイント①@Injectable()

先ほども書いた、NestJSでDIをするための設定です。
これを書いたものはプロバイダーと呼ばれ、他のクラスなどで使いまわせます。

ポイント②CanActivate

こちらも先ほど書いたNestJSで認証機能を使うためのインターフェースです。implementsして使います。

ポイント③HTTPヘッダーからBearerトークンを取得して検証

今回は、HTTPリクエストのAuthorizationヘッダーを使用してトークンを送信/受信します。

AuthorizationにBearer(保持者)とそのIDトークンを設定してHTTPリクエストを送信し、そのヘッダーを解析してバックエンド側で認証を行います。

AuthGuardを使う

作ったAuthGuardを使ってみます。

モジュールに登録

@Injectable()を付けたクラスはモジュールに登録することで使えるようになります。
以下のようにproviderに渡してあげます。

app.module.ts
@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true}),
  ],
  controllers: [AppController],
  // ここに登録
  providers: [AppService, FirebaseAuthGuard],
})

APIリクエストを受け取って検証

フロント側からのリクエストを受け取るコントローラーでAuthGuardを使います。

@UseGuards()はガードを使うためのNestJSの仕組みです。ここに先ほど作ったガードを渡すと、リクエストが来た時にIDトークンを検証します。

app.controller.ts
import { Controller, Get, UseGuards } from '@nestjs/common';
import { FirebaseAuthGuard } from './firebase-auth.guard';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  // UseGuardsで使いたいGuardを登録する
  @UseGuards(FirebaseAuthGuard)
  @Get("/hello")
  getHello(): {data: string} {
    return {data: 'Hello World!'};
  }
}

これでバックエンド側の実装は完了です!

まとめ

送られたHTTPリクエストのIDトークンを検証する、という機能を実装しました。
後編ではフロント側のログイン機能を実装します。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?