最近業務で NestJS を使ったAPIサーバーを構築する機会があり、その際、ユーザー認証を Amazon Cognito と LINE Login で行いました。
認証自体は NestJSのGuards でそれぞれの認可サーバーを使用したトークンの検証を実装すればいいのですが、開発中はトークンを簡単に発行できる手段がなかったため、 Postman などのAPIクライアントツールで毎回トークンを発行し、リクエストヘッダーに張り付けて検証しており、とても不便でした。
そこで、本記事では、 Swagger の定義ファイルにOAuth2の認証情報を書き込むことで、Authorizeボタンのクリックするだけでトークンを発行できるようにし、この不便さを解消したいと思います。
本記事で作成するNestJSアプリケーションは、以下のリポジトリからクローン可能です。
GitHub - FOURIER-Inc/nestjs-swagger
Contribute to FOURIER-Inc/nestjs-swagger development by creating an account on GitHub.
https://github.com/FOURIER-Inc/nestjs-swagger
前提
全て一から説明すると膨大な文章量になってしまうため、本記事では以下の前提で説明します。
-
AWS CLIの設定が完了している
-
Amazon Cognitoでユーザープールの作成が完了している
-
LINE developers accountで、LINE Loginチャネルの作成が完了している
-
NestJSをある程度使ったことがあり、基本的な設定方法が分かる
環境構築
まずは、NestJSの初回セットアップから、Swaggerドキュメントを表示できるところまで準備します。
次に、Swaggerを表示するのに必要な、 @nestjs/swagger
をインストールします。
インストール後、 src/app.controller.ts
を以下のように書き換えます。Controllerのエンドポイントは、それぞれCognitoとLINEのGuardを設定し、認証してからでないとアクセスできないようにする予定です。
最後に src/main.ts
ファイルを以下のように編集し、Swaggerドキュメントが生成・表示されるようにします。
ここまでセットアップ出来たら、NestJSアプリケーションを立ち上げ、
ブラウザから http://localhost:3000/doc
を開き、Swagger Documentが表示されれば、初期セットアップは完了です。
現時点では、認証設定は何もしていないので、Authorizeボタンも表示されませんし、 /cognito
と /line
も制限なくアクセスできます。
Amazon CognitoとLINEのセットアップ
環境構築だけでもなかなか大変ですが、このセクションも結構手間がかかります。
内容自体はこのブログの主題から逸れてしまうため、サッとスクリーンショットを中心にどのような設定をしたか説明し、この後の実装で必要になるパラメータを確認していきます。
Amazon Cognito
ユーザープールを作成したあと、OAuth2に関連する設定がされているか確認します。
この時、以下のパラメータをメモしておいてください。
-
ユーザープールID
-
Cognitoドメイン(URL)
-
クライアントID
-
クライアントシークレット
ユーザープールの概要
ユーザープールID をメモします。
アプリケーションの統合タブ
ドメイン
Cognito ドメイン をメモします。
リソースサーバー
リソースサーバーが1つ設定されていればOKです。
アプリケーションクライアントのリスト
1つアプリケーションが設定されていればOKです。
アプリケーションクライアント > アプリケーションクライアントに関する情報
クライアントID と クライアントシークレット をメモします。
アプリケーションクライアント > ホストされたUI
スクリーンショットのように設定します。
この際、許可されているコールバックに、 http://localhost:3000/doc/oauth2-redirect.html
を設定します。
💡
Nginxなどでホスト名を変えている場合
ローカル開発において、Nginxなどで http://hogehoge.localhost
といったようにホスト名を変えている場合、コールバックURLに登録することができません。
自分も同じ問題にハマりましたが、 http://localhost?redirect=http://hogehoge.localhost/doc/oauth2-redirect.html
といった風に、クエリパラメータとしてリダイレクト先を設定し、Nginxの設定で redirect
パラメータが来た場合はリダイレクトするように設定すると、うまく動きます。
LINE Login
LINE Loginチャネルの チャネル基本設定 タブを開き、以下の項目を確認します。
-
Channel ID
-
Channel Secret
また、LINEログイン設定のコールバックURLに http://localhost:3000/doc/oauth2-redirect.html
を設定します。
Guardの追加
次にGuardを追加し、設定したエンドポイントで認証するように設定します。
Guardも簡単な紹介にとどめますが、リポジトリには、今回作成したNestJSアプリケーションがあるので、そちらも参考にしてください。
GitHub - FOURIER-Inc/nestjs-swagger
Contribute to FOURIER-Inc/nestjs-swagger development by creating an account on GitHub.
https://github.com/FOURIER-Inc/nestjs-swagger
Amazon Cognito
まずは、Amazon Cognitoのトークンを検証するため、 aws-jwt-verify
パッケージを追加します。
次に、以下のGuardの AWS_COGNITO_USER_POOL_ID
と AWS_COGNITO_USER_POOL_CLIENT_ID
を置き換えてください。
LINE Login
LINEはAWSと違いパッケージ等がないので、自分でトークンをサーバーに送信し、検証する必要があります。
送信するためのHTTPクライアントとして、 axios
パッケージをインストールします。 axios
の使用は個人的な好みなので、 fetch でも可能だと思います。
次に、以下のGuardの LINE_LOGIN_CHANNEL_ID
を置き換えます。
これらのGuardをControllerに設定します。後述しますが、複数のOAuth2スキーマを持つ場合、 @ApiOAuth2
に名前も指定する必要があります。
Swagger Documentに鍵マークが表示されれば完了です。
この時点でAPIをたたくと、Guardでの認証に失敗し、403レスポンスが返ってくると思います。
SwaggerのAuthorization設定
ようやく本題となるSwaggerの設定ですが、以下のように書けば、Amazon CognitoとLINE LoginのOAuth2スキーマを登録できます。
このコードのポイントは以下の通りです。
-
authorizationUrl
と tokenUrl
にはOAuth2の認証エンドポイントを指定します。Amazon Cognitoの場合はドメイン+固定パス、LINE Loginの場合は ドキュメント を参考に指定します。
-
scopes
に openid
を必ず含めます。
-
addOAuth2
の第2引数に名前を指定します。この名前はControllerの @ApiOAuth2
で指定した名前と一致している必要があります。
-
SwaggerModule.setup
の swaggerOptions.oauth2RedirectUrl
に、 http://localhost:3000/doc/oauth2-redirect.html
を指定します。
この設定後、Swagger Documentを開き、Authorizeをクリックすると、2つのOAuth2スキーマが設定されているのが確認できます。
ℹ️
OAuth2スキーマが1つの場合、 SwaggerModule.setup
関数の swaggerOptions
にて initOAuth
を設定することで、 client_id
と client_secret
のデフォルト値を設定することができます。
確認
全ての設定が完了したので、実際に認証をしてみます。
Amazon Cognito
/cognito
エンドポイントの右側の錠マークをクリックし、 client_id
、 client_secret
、 scopes
を入れた後、Authorizeをクリックします。
正しく設定されていれば、以下のように認証画面が出てくるので、ログインかサインアップをします。
ログインに成功すると、Swagger Documentにリダイレクトされます。
これで、 /cognito
エンドポイントを叩いた時、トークンの認証が行われ、200レスポンスが返るようになります。
LINE Login
LINEの認証の場合も同様に、 client_id
、 client_secret
、 scopes
を入れた後、Authorizeをクリックします。
正しく設定されていれば、以下のようにLINEのログイン画面が出てくるので、ログインします。
ログインに成功すると、Swagger Documentにリダイレクトされます。
これで、 /line
エンドポイントを叩いた時、トークンの認証が行われ、200レスポンスが返るようになります。
まとめ
この記事では、SwaggerのAuthorization機能で、Amazon CognitoとLINE LoginとのOAuth2認証をするための設定をし、発行したトークンでNestJSのGuardで認証できることを確認しました。
設定の主要ポイントは以下の通りです。
-
OAuth2の認証には、
クライアントID
と クライアントシークレット
が必要
-
NestJSのSwaggerには、
/oauth2-redirect.html
エンドポイントがあるので、認可サーバーの コールバックURL とSwaggerに リダイレクトURL に設定する
-
トークンの検証サーバーは、LINE Loginのように URL で指定する方法や、Amazon Cognitoのように サービスごとの固有パラメータ で指定する方法がある
2つの認可サーバーを設定したので、サーバーごとの違いもある程度理解し、OAuth2についても理解が深まりました。
この記事の内容が、皆さんのAPI開発に役立てられれば幸いです。