なになれ

IT系のことを記録していきます

Firebase Authenticationを使ったNestJSでの認証機能の作成方法

この記事では、Firebase Authenticationを使ったNestJSでの認証機能を作成する方法を解説します。

要約

  • Passportを利用する
  • Firebase Admin SDKをインストールする
  • Firebaseの認証ロジックを実装したPassportの実装を行う
  • コントローラーにPassportによるGuardを設定する

内容

まずは、PassportというNode.jsの認証ライブラリを使用します。NestJSでは、@nestjs/passportモジュールを使用してこのライブラリを利用することができます。以下のようにnpmモジュールをインストールします。

$ npm install --save @nestjs/passport passport passport-http-bearer
$ npm install --save-dev @types/passport-http-bearer

また、Firebase Authenticationを使用するためには、firebase-adminをセットアップする必要があります。以下のコマンドを使用して、firebase-adminをインストールします。

$ npm install firebase-admin --save

firebase-adminを利用できるようにするためには、main.tsファイルに以下のようなコードを追加します。

main.ts

import admin from 'firebase-admin';
import * as serviceAccount from './firebase.json';
...

async function bootstrap() {
...
  admin.initializeApp({
    credential: admin.credential.cert(serviceAccount as admin.ServiceAccount),
  });
  await app.listen(3000);
}
bootstrap();

次に、Firebaseの認証ロジックを実装したPassportの実装を行います。以下のコードがその例です。

firebase-auth.strategy.ts

import { Strategy } from 'passport-http-bearer';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable, UnauthorizedException } from '@nestjs/common';
import admin from 'firebase-admin';

@Injectable()
export class FirebaseAuthStrategy extends PassportStrategy(Strategy) {
  constructor() {
    super();
  }

  async validate(token: string): Promise<string> {
    try {
      const decodedToken = await admin.auth().verifyIdToken(token);
      return decodedToken.uid;
    } catch (err) {
      throw new UnauthorizedException();
    }
  }
}

validate関数のtokenの引数はAPIにアクセスした際のベアラートークンが格納されます。こちらをFirebase Authで取得したIDトークンが格納されるようにし、verifyIdTokenでトークンを検証します。

例えば、以下のようなcurlコマンドからのアクセスになると思います。

curl http://localhost:3000/posts -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2Vybm..."

ベアラートークンの部分はFirebase AuthのIDトークンになるイメージです。

NestJSのモジュールでFirebaseAuthStrategyを利用できるようにするには、以下のコードをauth.module.tsファイルに追加します。そして、このモジュールを大元のapp.module.tsで利用します。

auth.module.ts

import { Module } from '@nestjs/common';
import { FirebaseAuthStrategy } from './firebase-auth.strategy';
import { PassportModule } from '@nestjs/passport';

@Module({
  imports: [PassportModule],
  providers: [FirebaseAuthStrategy],
})
export class AuthModule {}

最後に、コントローラーにPassportによるGuardを設定します。これにより、PostsControllerで作成されたWebAPIのエンドポイントはFirebase AuthのIDトークンによる認証に守られることになります。

posts.controller.ts

import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  ParseIntPipe,
  Post,
  Put,
  UseGuards,
} from '@nestjs/common';
import { PostsService } from './posts.service';
import { AuthGuard } from '@nestjs/passport';

@Controller({
  path: 'posts',
  version: '1',
})
@UseGuards(AuthGuard('bearer'))
export class PostsController {
...
}

全体のコードは以下にあります。

github.com

まとめ

本記事では、Firebase Authenticationを用いてNestJSにおけるWebAPIの認証機能の作成方法を解説しました。Passportを使用して認証機能を実装するということがわかれば、そのほかの認証方法についてもロジック部分を変更すればできると思います。Firebase Authenticationを使ったNestJSの認証機能の実装を行いたい場合に、本記事が参考になればと思います。