Contents
AWS Cognitoを用いたサーバーレスアプリの認証実装手順
サーバーレスアーキテクチャにおいてユーザー認証機能を効率的に実装するには、AWS Cognitoが最適な選択肢です。CognitoはIAMと連携しやすく、ユーザープールやフェデレートIDプールの柔軟な設定が可能で、サーバーレス環境に特化した設計となっています。本記事ではサーバーレス アプリ Cognito 認証 実装 手順を具体的なコード例付きでステップバイステップで解説します。
Cognitoユーザープールの設定手順
Cognitoを活用する際には、まずユーザー管理を行うためのユーザープールを作成する必要があります。ここではAWSコンソールでの基本的な設定手順とカスタマイズ方法を解説します。
ユーザープールの作成
以下にユーザープールの作成手順をステップバイステップで紹介します。
- AWS Management Consoleにログインし、「Cognito」サービスを開きます。
- 「ユーザープール」タブから「作成」ボタンをクリックします。
- プール名を入力し、認証方式(メール/電話番号など)を選択します。
ユーザープールは、アプリケーションの認証ロジックをCognitoに委譲するための基盤となるため、初期設定時の選択が将来的な拡張性に大きく影響します。
属性と認証ポリシーの設定
ユーザープール作成後は、ユーザー属性や認証ポリシーをカスタマイズします。以下に重要なポイントを整理しました。
ユーザー属性の追加
- 「属性」タブから電話番号や生年月日などの項目を登録できます。
- 例:
custom:departmentというカスタム属性を追加し、所属部署情報を管理する仕組みを作成。
認証ポリシーの設定
- 「ユーザープール設定」からパスワード強度やログイン失敗回数の制限を調整します。
| 項目 | 値 | 補足 |
|---|---|---|
| 最小文字数 | 8文字 | パスワードポリシーの一例 |
| 大文字・小文字 | 必須 | 指定可能なオプション |
| 記号使用 | 可 | セキュリティ強化に有用 |
パスワードポリシーの詳細設定は、セキュリティ対策セクションでも説明しているため、重複を避けています。
メール/電話番号検証の有効化
ユーザー登録時にメールまたは電話番号で確認を行う設定をします。以下に具体的な手順を示します。
- 「認証」タブから「登録時メール送信」や「電話番号確認」をオンにします。
- メールテンプレート(確認用リンク、パスワードリセット用など)をカスタマイズできます。
注意: テンプレート内の変数(例:
{##VerifyEmailURL##})はAWSが自動で置換するため、手動で編集する必要はありません。
API Gatewayとの連携方法
CognitoとAPI Gatewayを連携させることで、認証済みユーザーのみにアクセスを許可できます。以下に具体的な設定手順を示します。
Cognito認証ライブラリの導入
API GatewayでのCognito連携には、AWS SDKやLambda Authorizerが有効です。Node.jsでの実装例は以下の通り:
|
1 2 3 |
const AWS = require('aws-sdk'); // AWS SDK v3使用の場合指定可能(例: 'aws-sdk-js-v3') const cognitoIdp = new AWS.CognitoIdentityServiceProvider(); |
Lambda Authorizerの実装では、
event.authorizationTokenからIDトークンを取得し、検証処理を行う必要があります。
Authorizerの設定手順
以下にAuthorizerの設定手順をステップバイステップで解説します。
- API Gatewayの「Authorizers」セクションで「Cognito User Pool」を選択します。
-
作成したユーザープールのClient IDとUser Pool IDを入力し、認証トークンの検証方法を指定します。
-
メソッドレベルのアクセス制御: 各エンドポイントで「Authorizer」タブから設定済みの認証者を選択することで、特定のAPIにだけCognito認証を適用可能です。
REST APIエンドポイントの保護
REST APIエンドポイントを保護するには以下を行う必要があります。
- 作成したREST APIのメソッド(GET/POSTなど)を開き、「Authorization」セクションで「Lambda Authorizer」または「Cognito User Pool」を選択します。
- 「Method Request」タブで「Authentication Schemes」に認証方式を設定し、トークンが無効な場合の401 Unauthorizedエラーを返すようにします。
401/403エラー処理:
- 401 Unauthorized: IDトークンが無効または期限切れの場合。対処: ログイン画面に戻すか、リフレッシュトークンを使用して再認証を促す。
- 403 Forbidden: 認証済みユーザーでもアクセス権がない場合に発生。対処: API Gatewayのメソッドレベルで正しいAuthorizerが設定されているか確認する。
Lambda関数での認証処理
Lambda関数はCognitoと連携し、IDトークンの検証やユーザー情報を取得する役割を持ちます。以下に具体的な実装例を示します。
イベントオブジェクトの解析
Lambdaが受け取るイベントオブジェクトには、認証情報とリクエストデータが含まれています。
|
1 2 3 4 5 |
exports.handler = async (event) => { const token = event.authorizationToken; // トークンを検証するロジック... }; |
注意:
authorizationTokenはIDトークンであり、アクセストークンとは異なります。
IDトークンの検証ロジック
JWTの署名を検証し、ユーザーが有効なCognitoユーザープールに所属しているか確認します。
|
1 2 3 4 5 6 7 8 9 10 |
const jwt = require('jsonwebtoken'); const publicKey = await fetchPublicKey(); // Cognitoから公開鍵取得 try { const decoded = jwt.verify(token, publicKey, { algorithms: ['RS256'] }); return generatePolicy(decoded.sub, 'Allow', event.methodArn); } catch (err) { throw new Error('Invalid token'); } |
検証に失敗した場合は、Lambdaが403 Forbiddenを返すように設定します。
ユーザー情報の取得方法
検証済みトークンからユーザーID(sub)を得て、Cognitoユーザープールから属性情報を取得します。
|
1 2 3 4 5 6 7 8 9 |
const userPoolId = 'us-east-1_XXXXXX'; const params = { UserPoolId: userPoolId, Username: decoded.sub }; const userData = await cognitoIdp.adminGetUser(params).promise(); console.log(userData); // ユーザー属性の取得結果 |
IAM権限について: 管理者権限で呼び出す場合は、IAMロールに
Admin.GetUserの権限を付与する必要があります。
セキュリティベストプラクティス
Cognitoを安全に運用するためには、以下のようなセキュリティ対策が不可欠です。
パスワードポリシーの強化
- 最小文字数: 8文字以上
- 大文字・小文字・数字・記号の混在を必須とします。
- パスワード変更の頻度制限: 最大90日間ごと
管理コンソールの「ユーザープール設定」→「パスワードポリシー」から設定可能です。
MFA設定の推奨
2段階認証(MFA)を有効化することで、不正アクセスを防ぎます。
- ユーザーがMFAを有効にするかどうかを選択できるようにする。
- SMSまたはTotpアプリを使用した認証を設定します。
| 認証方式 | 用途 | 注意点 |
|---|---|---|
| SMS | モバイルユーザー向け | 国際運用には通話料がかかる可能性あり |
| TOTP | セキュアな環境向け | アプリが必要(Google Authenticatorなど) |
アクセスログの監視
CloudWatch LogsやCloudTrailと連携し、異常なアクセスを検出します。
- API Gatewayで「Execution Logging」を有効化します。
- CloudWatch Logsにアクセスログを送信し、401/403エラーの発生頻度や特定ユーザーの活動履歴を監視します。
最小権限の原則: ユーザーごとにアクセス可能なリソースを厳格に制限します。
よくあるエラーとその対処法
Cognitoとの連携で発生する代表的なエラーケースと解決策を以下に示します。
認証失敗時のステータスコード
- 401 Unauthorized: IDトークンが無効、または期限切れ。
- 対処: ログイン画面に戻すか、リフレッシュトークンを使用して再認証を促す。
- 403 Forbidden: 認証済みユーザーでもアクセス権がない場合に発生。
- 対処: API Gatewayのメソッドレベルで正しいAuthorizerが設定されているか確認する。
タイムアウト設定の最適化
Lambda AuthorizerやCognito API呼び出し時のタイムアウトを調整します。
- Lambda Authorizerのタイムアウト: デフォルトは3秒、必要に応じて最大29秒まで拡張可能です。
- Cognito SDKのタイムアウト:
AWS.config.httpOptions.timeoutで設定可能。
タイムアウトが発生する際には、CloudWatch Logsから詳細なエラーメッセージを確認し原因特定します。
リージョン不一致の回避
CognitoユーザープールとLambda、API Gatewayが同じリージョンに配置されているかを確認します。
- AWSリージョンの一覧: https://aws.amazon.com/jp/about-aws/global-infrastructure/regions/
- 不一致時のエラー例:
Invalid parameter: UserPoolId(ユーザープールIDが他リージョンに存在する場合)
リージョン設定は、AWS SDKの初期化時やCloudFormationテンプレートで明示的に指定することが推奨されます。
まとめ
本記事では、サーバーレス アプリ Cognito 認証 実装 手順をステップバイステップで解説しました。重要なポイントを以下に整理します:
- Cognitoユーザープールの設定: ユーザー属性と認証ポリシーをカスタマイズし、メール/電話番号検証を有効化
- API Gatewayとの連携: Lambda AuthorizerやCognito User Pool Authを用いたアクセス制御実装
- Lambdaでの認証処理: IDトークンの解析とユーザー情報取得ロジックの実装例
- セキュリティ対策: パスワードポリシー強化、MFA設定、CloudWatchによる監視
- エラー対応: 401/403エラーやタイムアウト、リージョン不一致の回避方法
実装時のエラー対策や詳細設定についてはコメントでご質問ください。