「ログイン機能を実装したいけど、OAuth 2.0 って何をするものなの?」「OpenID Connect と OAuth の違いが分からない」「AWS Cognito を使おうとしたら User Pool と Identity Pool があって混乱した」――こういった悩みを持つエンジニアは非常に多いです。
この記事では、認証・認可の基礎概念から出発し、OAuth 2.0・OpenID Connect(OIDC)・AWS Cognito の仕組みを図解つきで徹底解説します。読み終えた後には「どのプロトコルを・いつ・なぜ使うべきか」が判断できる実務レベルの知識が身につきます。対象読者はWebアプリ開発経験があり、認証周りの実装を担当する予定のエンジニアです。
認証(Authentication)と認可(Authorization)の違い

セキュリティを学ぶうえで最初に押さえるべきなのが、認証(Authentication)と認可(Authorization)の違いです。この2つは混同されがちですが、役割がまったく異なります。
| 用語 | 英語 | 問いかけ | 具体例 |
|---|---|---|---|
| 認証 | Authentication | あなたは誰ですか? | パスポートで本人確認 |
| 認可 | Authorization | あなたは何をしてよいですか? | チェックした部屋のみ入室可 |
ホテルのチェックインで例えると分かりやすいです。フロントでパスポートを提示して「この人は確かに予約者本人だ」と確認されるのが認証です。その後、割り当てられた部屋のカードキーが渡されて「この部屋にだけ入れる」とアクセス範囲を制限するのが認可です。
重要:認証なしに認可は成立しません。まず「誰であるか」を確認(認証)し、その後「何ができるか」を制御する(認可)という順序が基本です。また、OAuth 2.0 は本来「認可」のフレームワークであり、認証は担いません。この区別は後ほど OpenID Connect を理解する際に非常に重要になります。
OAuth 2.0 とは何か
OAuth 2.0 は、あるサービスが別のサービスのリソースへアクセスする権限を、ユーザーのパスワードを渡さずに委任するための認可フレームワークです。RFC 6749 で標準化されています。
身近な例で言えば、「Twitter アカウントでログイン」や「Google カレンダーと連携する」機能がすべて OAuth 2.0 を使っています。ユーザーは Google のパスワードを外部アプリに教えることなく、Google カレンダーの読み取り権限だけを安全に渡せます。
OAuth 2.0 の4つの登場人物
| ロール | 英語名 | 説明 | 具体例 |
|---|---|---|---|
| リソースオーナー | Resource Owner | 保護されたリソースの所有者 | エンドユーザー本人 |
| クライアント | Client | リソースにアクセスしたいアプリ | スマートフォンアプリ・SPA |
| 認可サーバー | Authorization Server | アクセストークンを発行するサーバー | Google / Auth0 / Cognito |
| リソースサーバー | Resource Server | 保護されたリソースを持つサーバー | Google Calendar API |
OAuth 2.0 の4つのグラントタイプ
OAuth 2.0の「4つのグラントタイプ」は、どの方法でアクセストークンを取得するか(認可のフロー)の違いです。
前提👇
OAuth 2.0 は「ユーザーの代わりに他のサービスへアクセスするための仕組み」です。これを踏まえて4つ2つのグランドタイプを確認していきます。
- 認可コードフロー(Authorization Code Grant):最もセキュアで推奨される方法。サーバーサイドアプリや PKCE 付きのSPA・モバイルアプリで使用
- クライアントクレデンシャルフロー(Client Credentials Grant):ユーザーが介在しないマシン間通信(M2M)向け。バックエンドのバッチ処理やマイクロサービス間通信で使用
- インプリシットフロー(Implicit Grant):ブラウザ上でアクセストークンを直接取得する旧来の方法。現在は非推奨(PKCE 付き認可コードフローを使うべき)
- リソースオーナーパスワードクレデンシャルフロー(ROPC):ユーザーのID/パスワードをクライアントに直接渡す。信頼できるアプリのみ使用可・原則非推奨
現在(2024年以降)の主流は 認可コードフロー + PKCE です。SPAやモバイルアプリなど、クライアントシークレットを安全に保管できない環境では、インプリシットフローではなく必ずPKCEを使用してください。
認可コードフロー(Authorization Code Flow)の仕組み

認可コードフローは、ユーザー・クライアントアプリ・認可サーバー・リソースサーバーの4者が登場するフローです。以下の6ステップで進みます。
- ユーザーがログインボタンをクリックし、クライアントアプリにリクエストを送る
- クライアントが /authorize エンドポイントへリダイレクト(PKCE使用時は code_challenge を付与)
- 認可サーバーがログイン画面を表示し、ユーザーがID/パスワードを入力して認証
- 認可サーバーが短命の認可コード(Authorization Code)をコールバックURLへ返却
- クライアントが認可コードと code_verifier を /token エンドポイントに送付し、アクセストークン・IDトークン・リフレッシュトークンを取得
- 取得したアクセストークンを使って、リソースサーバーのAPIを呼び出す
ポイントはアクセストークンをブラウザのURLに直接露出させない点です。認可コードは一時的なもので、バックエンドのサーバー間通信でのみトークンと交換されます。これがインプリシットフローより安全な理由です。
PKCE(Proof Key for Code Exchange)とは
PKCE(ピクシー)は、認可コードフローの弱点である認可コード横取り攻撃を防ぐための拡張仕様です。SPAやモバイルアプリなど、クライアントシークレットを安全に保管できない環境で必須です。
# 1. code_verifier の生成(ランダムな高エントロピー文字列)
code_verifier=el6UJ6cSfyDJwOCo2bqVyOE33M21mQDLZvQ5ujMdk
# 2. code_challenge の生成(SHA-256ハッシュをBase64URLエンコード)
code_challenge=Eq4yyx7ALQHto1gbEnwf7jsNxTVy7WuvI5choD2C4SY
echo "code_verifier: "
echo "code_challenge: "認可サーバーとの接続開始時に、クライアント側でランダムな文字列(code_verifier)を作成します。この文字列をハッシュ化した値(code_challenge)とハッシュ化に使用したハッシュ関数(code_challenge_method)を認可サーバーのエンドポイントへリダイレクト時に送信します。
認証成功後、認可サーバーから認可コードがクライアント側に送られます。クライアントはその認可コードとランダムな文字列(code_verifier)を認可サーバーに送ります。
認可サーバーはその code_verifier をハッシュ化し、事前に受け取っていた code_challenge と一致するかを確かめます。整合性が合えば、認可サーバーはクライアントにアクセストークンを発行します。
OpenID Connect(OIDC)とは何か
OpenID Connect(OIDC)は、OAuth 2.0 の上に「認証」レイヤーを追加したプロトコルです。OAuth 2.0 単体では「誰がログインしているか」が分からないという問題を解決します。
OIDC が追加した最大の要素がIDトークン(ID Token)です。IDトークンは JWT(JSON Web Token)形式で、以下の情報が含まれています。
// IDトークン(JWT)のペイロード例
{
"iss": "https://accounts.google.com", // 発行者(Issuer)
"sub": "1234567890", // ユーザーの一意識別子(Subject)
"aud": "your-client-id", // 受信者(Audience)
"exp": 1700000000, // 有効期限(Unix時刻)
"iat": 1699996400, // 発行時刻
"email": "user@example.com",
"name": "山田 太郎"
}IDトークンは署名(RS256等)されているため改ざんを検知できます。アプリはIDトークンの sub クレームをユーザーの識別子として使い、email や name などのプロフィール情報を取得できます。これにより、シングルサインオン(SSO)が実現できます。
JWT(JSON Web Token)の構造
JWT は OAuth 2.0 や OIDC で広く使われるトークン形式です。ドット(.)で区切られた3つのパーツで構成されます。
# JWT の構造(ヘッダー.ペイロード.署名)
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyLWlkLTEyMyIsInNjb3BlIjoib3BlbmlkIGVtYWlsIn0.signature
# ヘッダー(Base64URLデコード後)
{
"alg": "RS256",
"typ": "JWT"
}
# ペイロード(Base64URLデコード後)
{
"sub": "user-id-123",
"scope": "openid email profile",
"exp": 1700000000
}
# 署名 = RSA_sign(header + "." + payload, 秘密鍵)JWT のペイロードは Base64URL でエンコードされているだけで、暗号化はされていません。センシティブな情報(パスワード等)はJWTのペイロードに含めないでください。署名により改ざん検知はできますが、内容は誰でもデコードして読めます。
JWTについてはこちらを参考にしてみてください
AWS Cognitoの全体像

AWS Cognito は、AWSが提供するフルマネージドの認証・認可サービスです。大きく2つのコンポーネントで構成されています。
| コンポーネント | 役割 | 発行するもの |
|---|---|---|
| User Pool(ユーザープール) | 認証(ユーザーディレクトリ) | JWT(IDトークン・アクセストークン・リフレッシュトークン) |
| Identity Pool(IDプール) | 認可(AWSリソースアクセス) | 一時的なAWS認証情報(アクセスキー・シークレット・セッショントークン) |
User Pool(ユーザープール)の機能と使い方
User Pool はユーザー管理と認証を担うコンポーネントです。主な機能は以下のとおりです。
- ユーザーのサインアップ・サインイン機能(メール/SMS認証付き)
- MFA(多要素認証)サポート
- パスワードポリシーの設定(最小文字数・複雑さなど)
- ソーシャルログイン連携(Google / Facebook / Amazon / Apple)
- Lambda トリガーによるカスタム認証フロー
- 認証成功時に JWT(IDトークン・アクセストークン・リフレッシュトークン)を発行
User Pool で発行された JWT は、そのまま自前の API Gateway や Lambda 関数の認証に使えます。API Gateway のオーソライザーに Cognito User Pool を設定するだけで、JWT の検証を自動化できます。
import boto3
from botocore.exceptions import ClientError
def cognito_signin(username: str, password: str) -> dict:
"""Cognitoユーザープールへのサインイン"""
client = boto3.client('cognito-idp', region_name='ap-northeast-1')
try:
response = client.initiate_auth(
AuthFlow='USER_PASSWORD_AUTH',
AuthParameters={
'USERNAME': username,
'PASSWORD': password,
},
ClientId='YOUR_APP_CLIENT_ID'
)
tokens = response['AuthenticationResult']
return {
'id_token': tokens['IdToken'], # ユーザー情報付きJWT
'access_token': tokens['AccessToken'], # API呼び出し用JWT
'refresh_token': tokens['RefreshToken'] # 更新用トークン
}
except ClientError as e:
print(f"認証エラー: {e.response['Error']['Message']}")
raiseIdentity Pool(IDプール)の機能と使い方
Identity Pool は、認証済みユーザー(または未認証ゲスト)に対して一時的なAWS認証情報を発行するコンポーネントです。主な用途はモバイルアプリやSPAから直接AWSサービス(S3・DynamoDB・Lambda等)にアクセスする場合です。
- User Pool で認証して JWT(IDトークン)を取得
- IDトークンを Identity Pool に送付
- Identity Pool がトークンを検証し、対応する IAM ロールにマッピング
- STS(Security Token Service)経由で一時的な AWS 認証情報(アクセスキー・シークレット・セッショントークン)を発行
- 発行された認証情報で S3 や DynamoDB に直接アクセス
import boto3
def get_aws_credentials_from_cognito(id_token: str) -> dict:
"""CognitoIDプールから一時的AWS認証情報を取得"""
identity_client = boto3.client('cognito-identity', region_name='ap-northeast-1')
USER_POOL_ID = 'ap-northeast-1_XXXXXXXXX'
IDENTITY_POOL_ID = 'ap-northeast-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
# 1. IdentityIDを取得
id_response = identity_client.get_id(
IdentityPoolId=IDENTITY_POOL_ID,
Logins={
f'cognito-idp.ap-northeast-1.amazonaws.com/{USER_POOL_ID}': id_token
}
)
identity_id = id_response['IdentityId']
# 2. 一時的AWS認証情報を取得
creds_response = identity_client.get_credentials_for_identity(
IdentityId=identity_id,
Logins={
f'cognito-idp.ap-northeast-1.amazonaws.com/{USER_POOL_ID}': id_token
}
)
return creds_response['Credentials']User Pool と Identity Pool の使い分け
| ユースケース | 必要なコンポーネント |
|---|---|
| API Gateway + Lambda でバックエンドAPIを保護したい | User Pool のみ(JWTオーソライザー) |
| SPAやモバイルアプリから直接 S3 にファイルをアップロードしたい | User Pool + Identity Pool |
| ゲストユーザー(未認証)にも限定的なAWSアクセスを許可したい | Identity Pool のみ(匿名認証) |
| Google / Facebook でのソーシャルログインに対応したい | User Pool(フェデレーション機能) |
Cognitoを使ったサーバーサイドでのJWT検証方法
User Pool から発行された JWT を自前のサーバーで検証する場合、Cognito が公開している JWK(JSON Web Key Set)を使います。Cognito の公開鍵 URL は以下の形式です。
# CognitoのJWK(公開鍵)エンドポイント

https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json
# 例

https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_XXXXXXXXX/.well-known/jwks.jsonimport jwt
from jwt.algorithms import RSAAlgorithm
import requests
import json
def verify_cognito_jwt(token: str, user_pool_id: str, client_id: str, region: str) -> dict:
"""Cognito JWTトークンの検証"""
# JWKエンドポイントから公開鍵を取得
jwks_url = f"https://cognito-idp.{region}.amazonaws.com/{user_pool_id}/.well-known/jwks.json"
jwks_response = requests.get(jwks_url)
jwks = jwks_response.json()
# JWTヘッダーからkidを取得
unverified_header = jwt.get_unverified_header(token)
kid = unverified_header['kid']
# kidに対応する公開鍵を探す
public_key = None
for key in jwks['keys']:
if key['kid'] == kid:
public_key = RSAAlgorithm.from_jwk(json.dumps(key))
break
if not public_key:
raise ValueError("公開鍵が見つかりません")
# JWTを検証してペイロードを返す
payload = jwt.decode(
token,
public_key,
algorithms=['RS256'],
audience=client_id
)
return payload認証・認可設計の実務チェックリスト
- フロー選択:SPAやモバイルアプリには認可コードフロー + PKCE を使用する(インプリシットフローは禁止)
- トークン有効期限:アクセストークンは短命(15〜60分)に設定し、リフレッシュトークンで更新する
- スコープ最小化:アプリが必要とする最小限のスコープ(権限)のみを要求する
- JWTの格納場所:ブラウザでは localStorage より httpOnly Cookie が安全(XSS対策)
- HTTPS必須:すべての認証フローは HTTPS 上で実行する
- state パラメータ:CSRF攻撃を防ぐため、認可リクエストには必ず state パラメータを付与して検証する
- トークンの失効管理:ログアウト時はリフレッシュトークンを失効させる
まとめ
- 認証(Authentication)は「誰であるか」の確認、認可(Authorization)は「何をしてよいか」の制御
- OAuth 2.0 は認可のフレームワークであり、アクセストークンを発行してリソースアクセスを委任する
- OpenID Connect は OAuth 2.0 を拡張した認証プロトコルで、IDトークン(JWT)によってユーザー識別とSSO を実現する
- 現在の推奨フローは認可コードフロー + PKCE。インプリシットフローや ROPC は非推奨
- AWS Cognito の User Pool は認証担当(JWT発行)、Identity Pool は認可担当(一時的AWS認証情報の発行)
- 自前のAPIを保護するだけなら User Pool の JWT オーソライザーで十分。AWSサービスに直接アクセスする場合は Identity Pool も使う
認証・認可は「とりあえず動けばいい」ではなく、セキュリティ上の設計ミスが重大な脆弱性に直結する領域です。この記事で学んだ概念を土台に、実際のプロダクトでも正しいフローと設定を選択できるエンジニアを目指してください。
参考リソース
- RFC 6749 – The OAuth 2.0 Authorization Framework(IETF公式)
- Amazon Cognitoによる認証の仕組み(AWS公式ドキュメント)
- JSON ウェブトークンの検証(AWS公式ドキュメント)
- IDプールの認証フロー(AWS公式ドキュメント)
- Proof Key for Code Exchange(PKCE)を使った認可コードフロー(Auth0 Docs)
- Microsoft IDプラットフォームでのOpenID Connect(Microsoft Learn)
- 今から始めるAmazon Cognito入門 #1(DevelopersIO)
- OAuth 2.0 認可コードフロー+PKCEをシーケンス図で理解する(Zenn)



コメント