AWS Cognitoの基礎知識と役割

AWS Cognitoとは何か

Webアプリやスマホアプリを開発していると、「ユーザー登録」「ログイン」「パスワード忘れの対応」など、認証に関わる機能を作る場面に必ず直面します。これらを自分でゼロから実装しようとすると、データベースの設計から始まり、パスワードの安全な保存方法、不正アクセスへの対策、サーバーの保守運用まで、非常に多くの時間と専門知識が必要になります。

AWS Cognitoは、こうした認証周りの面倒な作業をすべて肩代わりしてくれるサービスです。AWSが「フルマネージド型」と呼んでいる通り、サーバーの立ち上げやソフトウェアのアップデートといったインフラの管理は一切不要です。開発者はAWSのマネジメントコンソールから設定を行うだけで、安全なログイン機能をアプリに組み込むことができます。

例えば、月間アクティブユーザーが数万人のECサイトを運営しているとします。自前で認証サーバーを構築していた場合、セール時のアクセス集中に備えてサーバーの増設を計画しなければなりません。しかしCognitoを使えば、ユーザーが10人でも100万人でも自動で処理をさばいてくれるため、こうしたインフラの心配から解放されます。その結果、商品を紹介する画面や決済機能など、アプリ本来の価値を生み出すコアな開発に集中できるようになります。

AWSアカウントを持っていれば、Cognitoは無料枠として「毎月5万回のサインアップ」と「毎月5万回のMAU(月間アクティブユーザー)」まで無償で利用可能です。個人開発や小規模なプロトタイプであれば、コストをかけずに本格的な認証機能を試すことができます。

認証と認可の基本的な違い

Cognitoを理解する上で、まず押さえておきたいのが「認証」と「認可」という2つの言葉の明確な違いです。この2つはセットで語られることが多いですが、実は役割が全く異なります。

認証とは、簡単に言えば「あなたは本当にその人ですか?」と確認する作業です。ログイン画面でメールアドレスとパスワードを入力して、システム側が登録されている情報と一致しているかをチェックするのが認証にあたります。ホテルでいうところの「フロントでの本人確認」のようなイメージです。

一方、認可とは「その人には、どの情報までアクセスさせてよいか?」を決定する作業です。例えば、SNSアプリで自分のプロフィールは編集できても、他の人のプロフィールは編集できないようにするルール作りのことです。ホテルでいうと、一般客は客室とレストランまでしか行けないが、スタッフはバックヤードにも入れるといった「権限の違い」をイメージすると分かりやすいでしょう。

AWS Cognitoは、この2つのプロセスを統合してアプリケーションに提供します。ユーザーがログインに成功すると、Cognitoは「IDトークン」と「アクセストークン」という2種類の電子データ(合鍵のようなもの)を発行します。IDトークンにはユーザーの名前やメールアドレスといった「誰であるか」の情報が含まれており、アクセストークンには「何を許可されているか」の情報が含まれています。アプリケーション側は、これらのトークンを受け取って適切に処理することで、シームレスな認証と認可の仕組みを実現できるのです。

認証と認可は、英語でそれぞれ「Authentication」と「Authorization」と言います。システム設計のドキュメントなどでは、頭文字を取って「AuthN(オース エヌ)」「AuthZ(オース ゼット)」と略記されることがよくあります。略語を見かけた際は、この違いを思い出してみてください。

ユーザープール(User Pool)の仕組みと考え方

Cognitoを理解する上で、まずしっかりとイメージを掴んでいただきたいのが「ユーザープール」です。ここでは、ユーザープールがどのような役割を持ち、どのようにアプリケーションと関わるのかを解説します。

ユーザープールの基本概念

ユーザープールをひとことで言うと、「アプリケーションに内蔵された安全なユーザー管理システム」です。

Webサービスやスマホアプリを作るとき、ほぼ必ず必要になるのが「新規登録」「ログイン」「パスワード変更」「パスワードリセット」といった機能です。これらをゼロから自作しようとすると、パスワードの暗号化や、不正アクセス対策、メール認証の実装など、セキュリティに関わる難しい課題が山のように出てきます。

ユーザープールを使うと、これらの機能が最初から用意されています。ユーザーのメールアドレスやパスワードなどの情報は、Cognitoが安全なデータベースとして一元管理してくれます。開発者は「ユーザープールを作る」という設定をするだけで、本番環境で使えるレベルの認証機能を手に入れることができます。

例えば、会員制のECサイトを構築する場合を考えてみましょう。ユーザープールを一つ作成しておけば、「メールアドレスとパスワードで登録」「登録時に確認メールを送信」「ログイン成功時にセッションを開始」といった一連の流れを、自分でデータベースを用意することなく実装できます。

ユーザープールには、パスワードの複雑さ(文字数や記号の有無)や、ユーザーに許可するログイン試行回数など、セキュリティに関する詳細なポリシーを設定できます。初期設定のままでも安全ですが、アプリケーションの要件に合わせてカスタマイズすることが推奨されます。

発行されるトークンの役割

ユーザーがユーザープールで正常にログイン(認証)を完了すると、Cognitoは「トークン」と呼ばれるデータを発行します。このトークンは、JWT(JSON Web Token)という形式で作られています。

JWTは、簡単に言うと「情報が詰まった暗号化されたテキスト」です。改ざんが困難であり、誰でも中身を読み取って確認できるという特徴があります。Cognitoは主に3種類のトークンを発行し、それぞれ異なる役割を持っています。

IDトークン 「この人は誰なのか」という情報を持ちます。ユーザー名やメールアドレス、電話番号などが含まれています。例えば、フロントエンドのアプリケーションで「〇〇さん、こんにちは」と表示する際に、このトークンの中身を参照します。

アクセストークン 「この人は何を許可されているのか」という情報を持ちます。主にAPIを呼び出す際の「鍵」として使われます。例えば、バックエンドのAPIが「このリクエストは本当にログイン済みのユーザーからのものか」を確認するときに、アクセストークンを検証します。

更新トークン アクセストークンやIDトークンには有効期限があります(デフォルトでは1時間程度)。期限が切れるたびにユーザーに再ログインを求めると体験が悪くなるため、更新トークンを使って新しいトークンを取得します。更新トークンの有効期限は長めに設定でき(30日や90日など)、ユーザーに気づかれない形でセッションを維持する役割を担います。

Warning

トークンはユーザーの権限を証明する重要なデータです。アクセストークンやIDトークンを第三者に盗まれると、不正にAPIが操作されるリスクがあります。アプリケーション側で適切に管理し、安全な場所に保存する必要があります。

外部IDプロバイダー(IdP)との連携

現代のWebサービスでは、「Googleでログイン」「LINEでログイン」といった、自分のサービス以外のアカウントを使ってログインできる機能が当たり前になっていますよね。これを実現するのが、外部IDプロバイダー(IdP)との連携機能です。

ユーザープールは、Google、Facebook、Apple、Amazonといった主要なソーシャルログインに標準で対応しています。また、企業向けのシステムではSAML 2.0やOpenID Connectという規格を使った連携もサポートしており、社内のActive Directoryなどとも繋ぐことができます。

ここで重要なのが、「外部IdPで認証されたユーザーも、最終的にはユーザープール内で管理される」という点です。

例えば、ユーザーが「Googleでログイン」ボタンを押したときの流れは以下のようになります。

  1. ユーザーがGoogleのログイン画面で認証を行う
  2. Googleから「この人は正しいユーザーです」という証明を受け取る
  3. Cognitoがその証明を確認し、ユーザープール内に該当ユーザーのデータを作成(または更新)する
  4. ユーザープールからJWTトークンが発行される

この仕組みのおかげで、アプリケーション側から見ると「ユーザー名とパスワードでログインしたユーザー」も「Googleでログインしたユーザー」も、どちらも同じように「Cognitoのトークンを持ったユーザー」として扱えます。ログイン方法が複数あったとしても、バックエンドのAPI側では「トークンを検証する」という同じ処理で対応できるのです。

Important

外部IdPと連携する場合、各IdP(GoogleやAppleなど)の開発者コンソールでクライアントIDやシークレットキーを取得し、Cognito側に設定する必要があります。この設定が漏れていると連携が動かないため、必ず双方の設定が完了しているか確認してください。

IDプール(Identity Pool)の仕組みと考え方

前のセクションでは、ユーザープールについて「誰であるか」を管理する仕組みとして解説しました。ここからは少し視点を変えて、「AWS上で何ができるか」を決めるための仕組みであるIDプール(Identity Pool)について見ていきましょう。

最初は私も「ユーザープールとIDプール、なんだか名前が似ていてややこしいな」と感じていたのですが、役割をイメージし分けるようになると、Cognitoの全体像がぐっとスッキリしてきます。

IDプールの基本概念

ユーザープールが会社の「社員名簿」だとすれば、IDプールは「入館証(セキュリティバッジ)の発行機」のようなイメージです。

IDプールの最大の役割は、認証されたユーザーに対して、AWSリソース(S3バケットやDynamoDBテーブルなど)に直接アクセスするための「一時的なAWS認証情報」を付与することです。一般的に、AWSのリソースにアクセスするにはアクセスキーやシークレットキーといった認証情報が必要になりますが、これをアプリ側で固定の文字列として埋め込むのはセキュリティ上非常に危険です。

IDプールを使うと、ユーザーがログインした直後に、そのユーザーだけが使える有効期限付きの認証情報を裏側で発行してくれます。アプリはそれを受け取って、S3から画像をダウンロードしたり、DynamoDBにデータを保存したりすることができるようになります。

重要なポイントとして、IDプール自体はユーザーのパスワードやメールアドレスといった情報を持ちません。あくまで「ユーザープールで認証されたよ」という証明(トークン)を受け取り、それを元にAWSの鍵を発行する窓口として機能します。

認証されていない(ゲスト)ユーザーへのアクセス許可

IDプールならではの面白い機能として、「ゲストアクセス」があります。

通常、AWSのリソースに触るにはログインが前提になりますが、IDプールでは「未認証(Unauthenticated)」の設定を有効にすることで、ログインしていないユーザーにも一時的な認証情報を発行できます。

これがどういう時に役立つかというと、例えばスマホゲームアプリを想像してみてください。アプリを初めて起動した時に、いきなり「会員登録してください」と言われると、多くのユーザーはそこで離脱してしまいますよね。でも、「まずはゲストとしてランキングを見てみましょう」という体験を提供できれば、ユーザーはサービスの魅力に触れることができます。

この場合、アプリはユーザープールでのログインをスキップし、直接IDプールに対して「未認証ユーザーとして認証情報をください」とリクエストします。するとIDプールは、非常に限定的な権限を持った一時的な鍵を発行し、アプリはその鍵を使ってDynamoDBにあるランキングデータ(読み取り専用)だけを取得できるようになります。

Warning

未認証アクセスを有効にする場合、必ず後述するIAMロールで権限を極限まで絞り込んでください。誤って書き込み権限や削除権限を与えてしまうと、誰でもデータを改ざんできる状態になってしまいます。

AWS IAMロールとの連携による権限管理

では、IDプールが発行した一時的な鍵で「何ができるか」は、どうやって決まるのでしょうか。ここで登場するのが「AWS IAM(アイアム)ロール」です。

IAMロールとは、簡単に言うと「AWS上での行動ルールブック」です。「S3のこのバケットの中身は見ていいけど、削除はダメ」「DynamoDBのこのテーブルにデータを書き込んでいい」といった許可ルールを細かく設定することができます。

IDプールには、主に以下の2つのIAMロールを紐付けることができます。

  1. 認証済みロール:ログイン済みのユーザーに割り当てられるルール
  2. 未認証ロール:ゲストユーザーに割り当てられるルール

先ほどのゲームアプリの例で考えると、未認証ロールには「ランキングテーブルの読み取りのみ許可」を設定し、認証済みロールには「自分のスコアだけランキングテーブルに書き込み許可、さらに自分のプロフィール画像をS3にアップロード許可」などを設定します。

ここでセキュリティ設計において絶対に守りたいのが「最小権限の原則」です。

Important

認証済みユーザーであっても、全てのAWSリソースへのフルアクセス権を与えるべきではありません。ユーザーが行う必要のある操作だけを厳密に許可する設計(最小権限の原則)を徹底することが、データ漏洩や不正操作を防ぐための不可欠な前提条件となります。

例えば、認証済みユーザーが「自分の画像」だけをアップロードできるようにするには、「ユーザーIDという名前のフォルダの中だけ、アップロードを許可する」といったIAMポリシー(ルールの具体的な記述)を書くことになります。このように、IDプールはIAMロールという強力な権限管理システムと連携することで、1人1人のユーザーのアクセス範囲を安全かつ柔軟にコントロールしています。

ユーザープールとIDプールの使い分けと連携

Cognitoを使い始めた頃、私が一番最初につまずいたのがこの2つの違いでした。「結局どっちを使えばいいの?」「両方作らないとダメなの?」と、awsのマネジメントコンソールを前にして何度も悩んだ記憶があります。ここでは、その混乱をすっきりと解消できるように、それぞれの役割と連携の仕組みを整理していきたいと思います。

それぞれのユースケースと違い

ユーザープールとIDプールは、名前が似ているせいで混同されがちですが、その役割は明確に異なります。例えるなら、ユーザープールは「アプリケーションのドアマン」で、IDプールは「AWSリソースの鍵の管理者」です。

ユーザープールは、アプリ内のログイン機能そのものを担当します。ユーザーが誰であるかを確認し、パスワードの管理やサインアップの処理を行います。一方でIDプールは、そのログインしたユーザーに対して「AWS上のバックエンドリソース(S3やDynamoDBなど)にアクセスするための一時的な鍵(AWS認証情報)」を渡す役割を持ちます。

では、実際の開発現場ではどう使い分けるのでしょうか。判断の基準は「フロントエンドからAWSのサービスに直接アクセスさせるかどうか」にあります。

例えば、バックエンドにAPI Gatewayや自前のサーバー(EC2やECSなど)を挟む構成であれば、ユーザープール単体で十分です。ユーザープールが発行したトークンをAPIに送り、サーバー側でユーザーを判別すれば良いからです。この場合、AWSリソースへのアクセスはサーバー側で行うため、IDプールは必要ありません。

逆に、ReactやVue.jsなどのSPA(シングルページアプリケーション)やスマホアプリで、サーバーを介さずにS3に画像を直接アップロードさせたり、DynamoDBに直接データを書き込んだりしたい場合は、IDプールの出番です。

Tip

「ユーザープールはアプリのログインに、IDプールはAWSの直接アクセス権限付与に使う」と覚えておくと、迷うことが少なくなります。バックエンドサーバーを経由するならユーザープール単体でOKです。

両者を連携させるアーキテクチャ

「サーバーレスでサクサク動くアプリを作りたい」という場合、この2つを連携させるのがモダンな開発における王道パターンになります。具体的な流れを見ていきましょう。

まず、ユーザーがアプリ画面でIDとパスワードを入力してログインします。この認証を担当するのがユーザープールです。認証が成功すると、ユーザープールは「JWT(JSON Web Token)」という、ユーザーの身元が証明されたデジタルな身分証明書を発行します。

次に、アプリはそのJWTをIDプールに渡します。まるでホテルのフロントで身分証を見せるように、「私の身元はこれです」と提示するイメージです。IDプールはJWTを検証し、本当に正規のユーザーかを確認します。問題がなければ、IDプールはそのユーザーに専用の一時的なAWS認証情報(アクセスキー)を発行します。

最後に、アプリはこの発行された認証情報を使って、S3やDynamoDBなどのAWSリソースに直接アクセスします。

この連携の素晴らしいところは、アプリ開発者がAWSのシークレットキーなどをフロントエンドのコードに埋め込まなくて済む点です。AWSのセキュリティの基本ルールとして、長期間有効なアクセスキーをクライアント側に置くのは絶対にNGとされていますが、IDプールを使えば、ユーザーのログインごとに「数時間だけ有効な一時的な鍵」を安全に手渡す仕組みが自動で構築できます。

Warning

IDプールを経由してフロントエンドから直接AWSリソースにアクセスさせる際は、必ずIAMロールで「最小権限の原則」を徹底してください。例えば、「自分のフォルダの中の画像だけ読み書きできる」といった細かな制限をかけないと、悪意のあるユーザーが他の人のデータを書き換えてしまうリスクが生じます。

AWS Cognitoの主な認証方法とセキュリティ機能

ここまでユーザープールやIDプールの構造について見てきましたが、「実際にユーザーはどうやってログインするのか」という点が気になってきた方も多いのではないでしょうか。Cognitoの強みの一つは、アプリケーションの要件やセキュリティレベルに合わせて、さまざまな認証方法を選択できる点にあります。

このセクションでは、Cognitoがどのように安全な認証を実現しているのか、その仕組みを掘り下げていきたいと思います。

セキュアなパスワード認証の仕組み

「ユーザー名とパスワードでログインする」というのは、Webサービスにおいて最も一般的な認証方法です。実は、このシンプルなパスワード認証の中にも、Cognitoならではのセキュリティ上の工夫が隠されています。

まず知っておいていただきたいのが、Cognitoのユーザープールはデフォルトで「SRP(Secure Remote Password)プロトコル」という仕組みを採用している点です。SRPとは一体何でしょうか。

通常、パスワード認証というと「ユーザーが入力したパスワードをそのままサーバーに送信し、サーバー側で照合する」というイメージを持つかもしれません。しかし、もしこの通信の途中で誰かにデータを盗み見られてしまったら、パスワードがそのまま漏洩してしまいます。

SRPは、この問題を解決するための仕組みです。ユーザーがパスワードを入力した瞬間、そのパスワードは通信経路に流れる前にクライアント側で数学的な計算(ハッシュ化)によって変換されます。そして、変換されたデータだけがサーバーに送られます。サーバー側も同様の計算を行い、その結果が一致するかどうかを確認します。

SRPでは「ソルト」と呼ばれるランダムな文字列を各ユーザーごとに設定してハッシュ化を行います。これにより、同じパスワードを使っているユーザーがいたとしても、データベースに保存されるハッシュ値は全く異なるものになります。

つまり、SRPを使えば、サーバー側であってもユーザーの元のパスワードを知ることはできず、通信経路を盗み見られても元のパスワードは分からない、という状態を作り出せます。

もちろん、CognitoではSRPのほかに「パスワードをそのまま送信する(ただしHTTPSで暗号化される)」認証フローも選択可能です。レガシーシステムとの統合などでどうしても必要な場合を除き、基本はSRPを選んでおくのが安全です。私自身、最初は「なんか難しそう」と思って避けていましたが、AWSのSDKを使えばSRPの計算部分は裏側で自動的に処理してくれるので、開発者は意識しなくても使えるようになっています。

パスワードレス認証と多要素認証(MFA)

パスワード認証の安全性を高めるアプローチとして、近年「パスワードレス認証」が注目されています。Cognitoでも、このパスワードレスなサインイン手法に対応しています。

一つ目の方法は、ワンタイムパスワード(OTP)を使った認証です。ユーザーはメールアドレスや電話番号を入力するだけで、Cognitoから6桁程度の短いコードが送信されます。そのコードを入力して認証を完了させます。有効期限は通常5〜10分程度に設定されており、使い捨てなので盗まれても再利用できません。

二つ目の方法は、WebAuthnパスキーを使った認証です。パスキーとは、スマートフォンの生体認証(指紋や顔認証)や、USB接続のセキュリティキーを使ってログインする仕組みです。「パスワードを入力する」という動作自体がなくなるため、フィッシング詐欺のようなパスワードを騙し取る攻撃に対して非常に強い耐性を持ちます。

Tip

パスワードレス認証は、ユーザー体験(UX)の向上にもつながります。パスワードの入力ミスや「パスワード忘れ」のフローがなくなるため、サインインの離脱率を下げる効果が期待できます。

そして、パスワード認証を使う場合でも、セキュリティをさらに強固にするための仕組みが多要素認証(MFA)です。MFAは、「知っている情報(パスワード)」に加えて、「持っているもの(スマートフォン)」や「生体情報」など、別の要素での認証を求める仕組みです。

Cognitoで設定できるMFAには、主に以下の2種類があります。

  • SMS: 登録済みの電話番号にショートメッセージでコードを送信する方法。設定が簡単でユーザーの導入ハードルが低いのがメリットです。
  • 認証アプリ(TOTP): Google AuthenticatorやAuthyなどのアプリを使う方法。SMSと違い、インターネット接続が不要で、SIMカードの乗っ取りのような攻撃のリスクを軽減できます。

Warning

SMSによるMFAは、携帯電話番号の移植(SIMスワップ)などのリスクがあることから、コードが傍受される可能性が指摘されています。特に金融系のサービスや、取り扱うデータの機密性が高いアプリケーションを開発する場合は、より安全な認証アプリ(TOTP)の利用を推奨します。

Cognitoでは、ユーザープールの設定画面から「MFAを必須にする」か「任意で選択可能にするか」を柔軟に設定できます。最初はMFAを任意にしておき、ユーザーが自分のアカウント設定画面から有効化できるようにしておくのも、堅牢性と使いやすさのバランスを取る良いアプローチだと思います。

Cognitoを使うと、これらの多様な認証フローを自前で実装する必要がありません。要件に合わせて設定を切り替えるだけで、セキュリティのベストプラクティスをアプリケーションに組み込むことができるのは、本当に助かりますよね。

AWS Cognitoのトークン管理とセキュリティ設計

ログインが成功すると、Cognitoからは「トークン」という鍵のようなものが発行されます。このトークンをどうやり取りし、どう保管するかが、アプリケーションの安全性を大きく左右します。最後のセクションでは、実際の開発現場でとても悩みやすい「トークンの管理と権限の設計」について、僕の経験を交えながら整理していきたいと思います。

クライアント側でのトークン保存方法

Cognitoの認証が通ると、ブラウザ(クライアント側)にIDトークン、アクセストークン、更新トークンの3つのJWT(JSON Web Token)が渡されます。このトークンをどこに保存するかには、主に「Local Storage」と「Cookie Storage」の2つの選択肢があります。

実は僕も最初は実装が一番簡単なLocal Storageを選びがちでした。しかし、セキュリティの観点から見ると、それぞれ明確なメリットとデメリットがあります。

Local Storageの場合 ブラウザの永続的な保存領域にトークンを置く方法です。実装がシンプルで、ReactなどのSPA(シングルページアプリケーションではデフォルト的に使われることが多いです。ただし、JavaScriptからいつでも読み取れるという性質上、悪意のあるスクリプトが実行されるXSS(クロスサイトスクリプティング)攻撃を受けた際に、簡単にトークンを盗まれてしまうリスクがあります。

Cookie Storageの場合 ブラウザのCookie機能を使ってトークンを保存する方法です。特に「HttpOnly」という属性をつけて保存すれば、JavaScriptからトークンを読み取れなくなるため、XSS攻撃に対してLocal Storageよりも強力な防御壁になります。また、Next.jsなどのフレームワークでサーバーサイドレンダリング(SSR)を行う場合、ブラウザから自動的にCookieが送信されるため、サーバー側で非常にスムーズにトークンを検証できます。ただし、別のサイトから意図しないリクエストを送りつけるCSRF(クロスサイトリクエストフォージェリ)攻撃への対策は別途必要になります。

保存先XSS対策CSRF対策SSR(サーバー側)での使いやすさ
Local Storage弱い(JSで読み取れる)不要悪い(自前で送信処理が必要)
Cookie Storage強い(HttpOnlyで防げる)必要良い(自動で送信される)

Warning

Local Storageにトークンを保存する場合、XSS攻撃のリスクが高まります。少しでもセキュリティを高めたい場合は、特別な理由がない限りHttpOnlyを付けたCookie Storageを選ぶことをおすすめします。

RBAC(ロールベースアクセス制御)の実現

アプリケーションを運用していくと、「一般ユーザー」と「管理者」で、見られる画面や実行できる操作を変えたいという場面に出てきます。これをCognitoで実現するための王道の考え方が「RBAC(ロールベースアクセス制御)」です。

Cognitoのユーザープールには「グループ」という機能があります。例えば「Adminグループ」と「Generalグループ」を作り、それぞれのユーザーを振り分けます。そして、このグループに対してAWSのIAM(Identity and Access Management)ロールを紐づけます。

具体的な動きを見てみましょう。ユーザーがログインし、IDプールを通じてAWSリソース(S3やDynamoDBなど)へのアクセス権限を取得する際、Cognitoはそのユーザーが属しているグループに紐づいたIAMロールを自動的に選択します。

例えば、Adminグループには「S3バケットのすべてのファイルを読み書きできるIAMロール」を、Generalグループには「自分のフォルダ内のファイルだけ読み取りできるIAMロール」を割り当てておきます。こうすることで、アプリケーションのコード側で複雑な権限判定を書くことなく、「誰がどのリソースにアクセスできるか」という制御をAWSのインフラレベルでシンプルかつ安全に実装できます。

Important

IDプールでグループに応じたIAMロールを切り替えるには、IDプールの設定画面で「トークンからのロール選択ルール」を正しく有効化しておく必要があります。ここを忘れると、どのグループに属していても同じ権限になってしまうため注意してください。

トークンの有効期限と更新フロー

セキュリティを考慮すると、発行されたトークンを永遠に使い続けることはできません。Cognitoでは、アクセストークンとIDトークンに「有効期限」を設定します。デフォルトでは60分(1時間)に設定されており、最大で24時間まで延ばすことが可能です。

有効期限が切れた状態でAPIにアクセスすると、サーバーから「401 Unauthorized(認証エラー)」という返事が来てしまいます。これを防ぐために用意されているのが「更新(リフレッシュ)トークン」です。

更新トークンは、アクセストークンやIDトークンとは違い、非常に長期間有効なトークンです(デフォルトでは30日間で、最大で10年にまで延長可能です)。

更新フローの仕組みはとてもシンプルです。

  1. アクセストークンの有効期限(例えば1時間後)が切れる。
  2. アプリケーションがバックグラウンドで、Cognitoに対して「更新トークン」を使って「新しいアクセストークンを発行して」とリクエストを送る。
  3. Cognitoが新しいアクセストークンとIDトークンを返す。
  4. アプリケーションは古いトークンを新しいものに入れ替える。

この仕組みをアプリケーション側に組み込んでおくことで、ユーザーは一度ログインすれば、数日間〜数ヶ月間にわたって「再ログインを要求されることなく」安全なセッションを維持できます。最近のモダンな認証ライブラリ(AWS Amplifyなど)は、この更新フローを自動でやってくれるので、最初からうまく活用していきたいですね。

まとめ

AWS Cognitoを活用することで、開発者は認証や認可の複雑な実装・運用から解放され、アプリケーション本来の価値を生み出すコアな開発に集中できるようになります。本記事で解説した重要なポイントを最後に振り返りましょう。

  • Cognitoの役割: ユーザーの「認証(あなたは誰か)」と「認可(何ができるか)」を統合的に提供するフルマネージドサービスです。
  • 2つのプールの使い分け: ユーザープールはアプリへのログイン機能を管理する「社員名簿」であり、IDプールはAWSリソースへのアクセス権を一時的に付与する「入館証の発行機」です。これらを連携させることで、安全でスケーラブルなサーバーレスアーキテクチャが構築できます。
  • 柔軟な認証方法: パスワード認証の安全性を高めるSRPプロトコルをはじめ、ワンタイムパスワード(OTP)やWebAuthnを用いたパスワードレス認証、多要素認証(MFA)など、アプリケーションの要件に合わせたセキュリティ設定が容易に行えます。
  • トークン管理とセキュリティ: XSS攻撃のリスクを減らすため、トークンの保存先にはLocal StorageよりもCookie Storage(HttpOnly)の利用が推奨されます。また、RBAC(ロールベースアクセス制御)や更新トークンを活用することで、より堅牢な権限管理とシームレスなユーザー体験を両立できます。

最初はユーザープールとIDプールの違いやトークンの仕組みなど、覚えるべきことが多く感じるかもしれません。しかし、一度基本の構造を理解してしまえば、Cognitoがいかに強力で便利なサービスか実感できるはずです。本記事が、皆様のAWS Cognitoを用いた開発の一助となれば幸いです。