投稿日:
更新日:
OAuth 2.0 に基づく認証・認可
- Authors
- Name
- ごとれん
- X
- @ren510dev
目次
- 目次
- はじめに
- AAA フレームワーク
- 概要
- AAA フレームワークの関係性
- AAA フレームワークのまとめ
- OAuth 2.0 と OIDC
- 概要
- OAuth 2.0 と OIDC の相違点
- OAuth 2.0 と OIDC の関係性
- フローの例
- OAuth 2.0 と OIDC のまとめ
- 【注釈】トークンの種類
- 【注釈】用語
- Cognito による認証・認可
- 構成要素
- 認証(Authentication)
- 認可(Authorization)
- コールバック URL(Callback URL / Redirect URI)
- 認証・認可フローの例(Cognito のみを使用する場合)
- Cognito による認証・認可のまとめ
- おわりに
- 参考・引用
はじめに
クラウドサービスや Third-party ベンダが普及する昨今、各サービスを連携する上で、OIDC や OAuth 2.0 という言葉をよく耳にすると思います。 これらの仕組みは、サービスを利用する際のセキュリティを担保する上で重要となる、認証・認可を提供するための基本的な規約(プロトコル)になります。
OAuth 2.0 や、その仕組みを流用して拡張された OIDC は複雑で、認証・認可において多くのフローを辿ります。
毎回、再調査をするのが大変なので、認証・認可の仕組みについて一度整理しておきたいと思います。
AAA フレームワーク
概要
- セキュリティ機能を設定するためのアーキテクチャ上の枠組み
- システムにアクセスするユーザやアプリケーションの身元確認、アクセス権管理、使用状況のトラッキングを包括的に行うための基本的な枠組み(フレームワーク)を提供
Authentication(認証)
- 概要
- システムのユーザが主張するアイデンティティ(身元)が正しいことを確認するプロセス
- 認証には、ユーザ名とパスワード、バイオメトリクス、MFA 等が含まれる
- フロー
- ユーザ入力:ユーザがログインフォーム等で認証情報を入力
- 情報送信:認証情報を認証サーバに送信
- 確認:認証サーバがデータベースやディレクトリサービスで一致する情報を検索
- 結果:認証が成功した場合はアクセス可能(失敗した場合はアクセスを拒否)
- 例
- ユーザ名 / パスワード:最も一般的な形態
- ユーザはシステムにユーザ名とパスワードを入力
- バイオメトリクス:指紋、顔認識、または虹彩スキャンを使用して認証
- 多要素認証(MFA:Multi-Factor Authentication):上記の一つ以上の要素を組み合わせて使用
- パスワードとスマートフォンで送信されるワンタイムパスコード(OTP)等
- ユーザ名 / パスワード:最も一般的な形態
Authorization(認可)
- 概要
- 認証されたユーザがシステム内で何をすることが許されているか(どのリソースにアクセスできるか)を決定するプロセス
- アクセス制御とも呼ばれる
- フロー
- ポリシ確認:認証されたユーザに対して、システムはそのユーザのアクセス権限を確認
- アクセス制御:リソースや操作(ファイルの読み取り、書き込み、削除 等)へのアクセスが許可されるか、拒否されるかを判断
- 適用:決定されたアクセス権限に基づき、ユーザの要求を実行
- 例
- ロールベースアクセス制御(RBAC:Role Based Access Control):ユーザに役割(ロール)を割り当て、役割に基づいたアクセス権限を決定
- 属性ベースアクセス制御(ABAC:Attribute Based Access Control):ユーザやリソースの属性に基づいて、アクセス権限を決定
- ポリシ:設定されたアクセス制御リスト(ACL:Access Control List) により、特定のユーザが特定のリソースに対して持つアクセス権限を管理
Accounting(アカウンティング)
- 概要
- システムのリソース使用状況をトラッキングし、記録するプロセス
- トラブルシューティングや監査の目的で使用されることが一般的
- フロー
- トラッキング:ユーザがシステムやリソースにアクセスする際の活動を記録
- 保存:ログやデータベースに活動履歴を保存
- 分析:必要に応じて、活動履歴に関する情報を解析して不正行為の検出やパフォーマンスの向上に役立てる
- 例
- ログイン/ログアウト記録:ユーザのログイン、ログアウトのタイムスタンプを記録。
- リソース使用記録:ネットワーク使用量、CPU 使用率、API コールの回数 等をトラッキング
- 監査ログ:管理者による設定変更やデータアクセスの記録
AAA フレームワークの関係性
- 認証
- ユーザの身元を確認し、システムにアクセス可能かを決定
- 認可
- 認証されたユーザに対して、システム内のどのリソースにアクセス可能であるか(操作を許可するかどうか)を決定
- アカウンティング
- ユーザの活動やシステムリソースの利用状況をトラッキングして記録
- アカウンティングにより、システムの使用状況をモニタリングしてセキュリティポリシの適用状況を確認
AAA フレームワークのまとめ
- 認証(Authentication)は、ユーザが "誰であるか" を確認するプロセス
- 認可(Authorization)は、認証されたユーザがシステム内で "何をできるか" を決定するプロセス
- アカウンティング(Accounting)は、ユーザがシステム内で "何をしているか" をリソースの使用状況をトラッキングして記録するプロセス
- これらの要素が相互に関連し、セキュリティを維持しながらユーザの有効なアクセスを保証する
- 認証がユーザを 識別 し、認可が行動を 制御 し、アカウンティングがその行動を 記録 することで、一貫したセキュリティフレームワークを構築する
OAuth 2.0 と OIDC
概要
- OAuth 2.0 と OIDC(OpenID Connect)はネットワーク上での認証と認可のためのプロトコル
- OAuth 2.0 と OIDC は連携して使用されることが多いが、それぞれ異なる目的を持つ
OAuth 2.0
定義
- 目的
- 主に認可(Authorization)を行うためのプロトコル
- 機能
- クライアントがリソース所有者(ユーザ)に代わってリソースサーバ(API サーバ)にアクセスするためのアクセス許可を得る仕組みを提供
- トークン
- アクセストークン を発行し、リソースサーバに対するリクエストの認証に使用する JWT 形式のトークンを提供
- 目的
OAuth 1.0(現在はほとんど使用されていない)との比較
特徴 OAuth 1.0 OAuth 2.0 署名の必要性 必須(HMAC-SHA1、RSA-SHA1) 不要(Bearer Token を直接使用) トークンの種類 リクエストトークン、アクセストークン アクセストークン、リフレッシュトークン 複雑性 高い(署名生成と検証が必要) 低い(Bearer Token で簡略化) セキュリティ 署名による保護 TLS/SSL で暗号化 スコープ なし サポート(アクセス範囲の指定) グラントタイプ 1 つ(複数パラメータの取得プロセス) 複数(認可コード、インプリシット、リソースオーナーパスワード、クライアントクレデンシャル) トークンの形式 独自形式(プラットフォーム毎に異なる) JWT が一般的 リフレッシュトークン なし あり 典型的な使用シナリオ
- Third-party アプリケーションが、ユーザの代わりに Google Drive や Facebook API 等のリソースにアクセスすることを許可
- アクセストークンを使用してバックエンド API へのアクセスを許可
OIDC:OpenID Connect
- 定義
- 目的
- OAuth 2.0 の上に構築された認証(Authentication)プロトコル
- OAuth 2.0 で提供される認可の仕組みに認証を追加したもの
- 機能
- ユーザの認証を行い、そのユーザに関する識別情報(ID トークン等)をクライアントに提供
- トークン
- ID トークン を発行し、ユーザの認証情報を含む JWT 形式のトークンを提供
- 目的
- 典型的な使用シナリオ
- Web アプリケーションがユーザのログイン状態を確認し、ユーザのプロファイル情報を取得するために使用
- シングルサインオン(SSO)機能を提供
OAuth 2.0 と OIDC の相違点
- 目的と機能
- OAuth 2.0
- 認可 を目的としており、ユーザのリソースへのアクセスを制御
- 例:クライアントアプリケーションが特定の API リソースにアクセスするためのアクセストークンを取得
- OIDC
- 認証 を目的としており、ユーザの ID を提供
- OAuth 2.0 のフローを拡張し、ユーザ情報の識別および認証を行う
- 例:Web アプリケーションがユーザのログインを処理し、ユーザプロファイル情報を取得
- OAuth 2.0
- トークンの種類
- OAuth 2.0
- アクセストークンのみを発行し、API リクエストの際にリソースサーバがそのトークンを認証
- OIDC
- アクセストークンに加えて ID トークンを発行し、ユーザの認証情報(OIDC の仕様として定義あり)を提供
- ID トークンの検証を行うことで、アプリケーションは認証結果を保持することが可能である
- ユーザ情報エンドポイント(UserInfo Endpoint)にアクセスすることで、ID トークンに紐付くユーザの追加情報を取得可能
- OAuth 2.0
- トークンの利用
- OAuth 2.0
- アクセストークンをリソースサーバに提供し、保護されたリソースにアクセス
- OIDC
- ID トークンをクライアントアプリケーションに提供し、ユーザの認証および識別に使用
- OAuth 2.0
- 使用するエンドポイント
- OAuth 2.0
- 認可エンドポイント(Authorization Endpoint)
- トークンエンドポイント(Token Endpoint)
- OIDC
- 認可エンドポイント(Authorization Endpoint)
- トークンエンドポイント(Token Endpoint)
- ユーザ情報エンドポイント(UserInfo Endpoint)※ 追加
- OAuth 2.0
- メタデータとディスカバリ
- OAuth 2.0
- 固定のエンドポイントで構成される
- OIDC
- ディスカバリドキュメント(
.well-known/openid-configuration
)を使用して動的にエンドポイント一覧や構成情報を提供 - クライアントアプリケーションは IdP の設定を自動的に発見
- ディスカバリドキュメント(
- OAuth 2.0
OAuth 2.0 と OIDC の関係性
- 拡張プロトコル
- OIDC は OAuth 2.0 を拡張して構築されている
- OIDC のフロー内に OAuth 2.0 の認可フローが含まれる
- これにより、認証と認可が統合されたフローを提供する
- 共同使用
- 一般に、クライアントは OIDC を使用してユーザの認証を確立し、OAuth 2.0 を使用してリソースへのアクセスを認可する
- 例:ユーザが Web アプリケーションにログインする際に、OIDC で認証し、その後 OAuth 2.0 の認可によりユーザの Google Drive ファイルへのアクセスを許可する
フローの例
- 認証要求(OIDC)
- ユーザがクライアントアプリケーションを使用し、認可エンドポイントにリダイレクトされる
- 認可エンドポイントはユーザ認証を行い、認可コードを発行
- 認可コードの交換(OAuth 2.0 と OIDC)
- クライアントはトークンエンドポイントに認可コードを送り、アクセストークンと ID トークンを取得
- リソースアクセス(OAuth 2.0)
- クライアントはアクセストークンを使用して、リソースサーバにリソースへのアクセスをリクエスト
- ユーザ情報の取得(OIDC)
- 必要に応じて、ユーザ情報エンドポイントに ID トークンを使用してユーザの詳細情報を取得
ログインにおける認証・認可シーケンス
サービス連携における認可シーケンス
OAuth 2.0 と OIDC のまとめ
- OAuth 2.0 は、認可のためのプロトコルであり、アクセストークンを発行することで、リソースサーバへのアクセスを制御する
- OIDC は、認証のためのプロトコルであり、OAuth 2.0 を拡張して ID トークンを発行し、ユーザの認証情報を提供する
- OAuth 2.0 はリソースへのアクセス許可を扱うのに適しており、OIDC はユーザの認証を扱うのに適している
- OAuth 2.0(認可)と OIDC(認証)のプロトコルを組み合わせることで、セキュアでスムーズな認証・認可フローを提供可能
【注釈】トークンの種類
アクセストークン
- 認可サーバ(IdP)が発行するトークン
- クライアントがリソースサーバにアクセスするために使用される
- API のリクエストの認証に使用
- 例:API リクエストを行う際に、アクセストークンを使ってアクセス制御を行う
ID トークン
- OIDC において認証されたユーザの情報を含むトークン
- JWT(JSON Web Token)形式で、ユーザプロファイルデータ等が含まれる
- 例:ID トークンはアプリケーション内でのユーザのセッション管理やプロファイル表示に使用される
リフレッシュトークン
- アクセストークンや ID トークンの有効期限が切れた際、新たなトークンを発行するために使用されるトークン
- リフレッシュトークンを使用することで、ユーザが再度認証することなく継続的にリソースにアクセス可能となる
- リフレッシュトークン自体にも有効期限(長期間)があり、通常アクセストークンや ID トークンよりも長く設定される
- リフレッシュトークンの有効期限が切れた場合は、再度ユーザに認証を要求する
比較
特徴 | アクセストークン | ID トークン | リフレッシュトークン |
---|---|---|---|
目的 | API リクエストの認可 | ユーザの認証情報を提供 | アクセストークンおよび ID トークンの再取得 |
使用範囲 | リソースサーバへのアクセス許可 | ユーザの認証状態確認、プロファイル表示 | 新しいアクセストークンおよび ID トークンの取得 |
スコープ | API へのアクセスを制限 | ユーザ情報を含む | 長期間の認証維持のための使用 |
寿命 | 短期(数分から数時間) | 通常、アクセストークンと同等か、それよりも長い | 長期(数日から数ヶ月、場合によっては 1 年) |
内容 | ユーザ ID、スコープ、発行者、受信者、有効期限 等 | ユーザ ID、メールアドレス、認証時刻、発行者、有効期限 等 | トークンの識別子および発行情報 等 |
形式 | JWT が一般的 | JWT が一般的 | トークン形式(JWT, SAML, Opaque 等) |
ペイロードにおけるクレームの種類
- アクセストークン
{
"sub": "user123", // Subject: ユーザまたはリソースオーナの識別子
"aud": "your-api", // Audience: トークンの受信者(通常はリソースサーバ)
"iss": "your-auth-server", // Issuer: トークンの発行者
"exp": 1516239022, // Expiration: トークンの有効期限
"iat": 1516233022, // Issued At: トークンの発行日時
"jti": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", // JWT ID: JWT の一意の識別子
"scope": "read write", // トークンで許可される操作の範囲(例:読み取り、書き込み)
"username": "JohnDoe" // 認証されたユーザの名前(オプション)
}
- ID トークン
{
"sub": "user123", // Subject: ユーザの一意識別子
"aud": "your-client-id", // Audience: トークンの受信者(通常はクライアントアプリケーション)
"iss": "https://your-auth-server", // Issuer: トークンの発行者(認可サーバまたは IdP)
"exp": 1516239022, // Expiration: トークンの有効期限
"iat": 1516233022, // Issued At: トークンの発行日時
"jti": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", // JWT ID: JWT の一意の識別子
"auth_time": 1516233020, // ユーザが認証された日時
"nonce": "n-0S6_WzA2Mj", // リプレイ攻撃を防ぐための一意の値
"email": "[email protected]", // ユーザのメールアドレス
"email_verified": true, // メールアドレスの検証状態
"name": "John Doe", // ユーザの名前
"locale": "en-US" // ユーザの地域情報
}
【注釈】用語
- リソースサーバ
- 保護されたリソース(API やデータ)を提供するサーバ
- アクセストークンを使用してアクセス制御を行う
- 例:REST API サーバがリソースサーバとして機能し、アクセストークンを使用してリクエストを認証
- クライアント
- リソース所有者の代わりにリソースサーバにアクセスするアプリケーション
- OAuth 2.0 や OIDC で認証や認可を利用する
- 例:Web アプリケーションやモバイルアプリケーションがクライアントとして機能し、ユーザの代理でリソースにアクセスする
- 認可エンドポイント(Authorization Endpoint)
/oauth2/authorize
- クライアントがユーザをリダイレクトして認可を求め、認可コードを取得するためのエンドポイント
- 例:クライアントアプリケーションは認可エンドポイントにユーザをリダイレクトして認可を取得する
- トークンエンドポイント(Token Endpoint)
/oauth2/token
- クライアントが認可コードやリフレッシュトークンを使用してアクセストークンおよび ID トークンを取得するためのエンドポイント
- 例:クライアントアプリケーションが認可コードを使用してアクセストークンを取得する際に使用
- ユーザ情報エンドポイント(UserInfo Endpoint)
/oauth2/userInfo
- OIDC におけるエンドポイントで、ID トークンに基づいて認証されたユーザの追加情報を提供
- 例:ユーザのプロファイル情報(名前、メールアドレス 等)を取得するために使用される
- 認可コード
- OAuth 2.0 認可コードフローにおいて、ユーザが認証され、クライアントに渡される一時的なコード
- クライアントアプリケーションは認可コードを使用してアクセストークンを取得
- 例:認可コードはクライアントアプリケーションがトークンエンドポイントに対してアクセストークンをリクエストするために使用される
Cognito による認証・認可
- Cognito はユーザの認証・認可・ユーザ管理を簡素化するための AWS マネージドサービス
- モバイルアプリケーションやウェブアプリケーションに対してシームな認証・認可を提供
構成要素
ユーザプール(User Pool)
- ユーザの認証とディレクトリ管理を提供
- ユーザはサインアップ(登録)し、サインイン(ログイン)することで、ユーザプールに追加される
- 例:アプリケーションのユーザプロファイルや認証プロセスの管理に使用
ID プール(Identity Pool)
- 認証されたユーザ(および未認証のゲスト)に対して一時的な AWS 認証情報を発行して、AWS リソースにアクセス可能にする
- 例:認証後に S3 や DynamoDB 等の AWS マネージドサービスリソースにアクセスするための認証情報を提供
ID プロバイダ(IdP:Identity Provider)
- 認可サーバ(認証情報を提供するサービスプロバイダ)とも呼ばれる
- 例:Google, Facebook, Instagram 等の Third-party IdP を連携することで認証情報を提供
- IdP を Cognito に追加する場合は こちら を参考に
認証(Authentication)
ユーザプールでの認証
- サインアップ(Sign-Up)
- クライアントアプリケーション(例:ウェブアプリ、モバイルアプリ)が、ユーザの登録情報(ユーザ名、パスワード、メールアドレス 等)をユーザプールに送信
- ユーザプールはユーザの属性を検証して確認メールや SMS を送信(Amazon SNS と組み合わせたりする)
- サインイン(Sign-In)
- ユーザがクライアントアプリケーションを通じて既存のアカウントでログインを試みる
- クライアントアプリケーションはユーザプールに対して認証リクエストを送信し、ユーザプールはユーザ名とパスワードを確認
- 認証が成功すると、ユーザプールは「アクセストークン」「ID トークン」「リフレッシュトークン」を生成してクライアントアプリケーションに返送
Third-party IdP との認証
- 認証リクエスト
- クライアントアプリケーションは外部 IdP にリダイレクトしてユーザが認証情報を提供
- 認証が成功すると、外部 IdP はユーザプールにトークンを返送
- トークンの交換
- ユーザプールは外部 IdP から受け取ったトークンを、「アクセストークン」「ID トークン」「リフレッシュトークン」に変換してクライアントアプリケーションに提供
認可(Authorization)
ID プールでの認可
- 認証済みユーザ
- ユーザプールで認証されたアクセストークンと ID トークンを使用して ID プールに対してリクエストを送信
- ID プールは、クライアントアプリケーションから受け取ったトークンを検証して一時的な AWS 認証情報(アクセスキー ID、シークレットアクセスキー、セッショントークン)を生成して返送
- これらの認証情報を用いて、ユーザは AWS リソースにアクセスする
- 未認証ユーザ(ゲストユーザ)
- ID プールは未認証ユーザにも一時的な AWS 認証情報を発行可能(アクセス権限は制限される)
- アクセス制御ポリシを用いて、認証済み、および未認証ユーザに対する異なる権限を適用する
コールバック URL(Callback URL / Redirect URI)
- 認証プロセスが完了した後に、認可サーバ(IdP)からクライアントアプリケーションに認可コードやトークンを返すための URL
- 事前に、認可サーバ(Cognito ユーザプールにおけるアプリケーションクライアント)に登録しておくことで、そのエンドポイントに対してトークンを返送する
認証・認可フローの例(Cognito のみを使用する場合)
- ユーザのリダイレクト
- ユーザがクライアントアプリケーションにログインしようとすると、ユーザプールの認可エンドポイントにリダイレクトされる
- ユーザはログインに必要な情報を入力
- ユーザプールはユーザの認証情報を確認
- 認可コードの受け取り
- 認証に成功すると、Cognito はクライアントのコールバック URL に認可コードを返送
- 3-4. トークンの交換
- クライアントアプリケーションはトークンエンドポイントに認可コードを送信してアクセストークンおよび ID トークンを取得
- 5a-8a.【リソースへのアクセス】:AWS リソースにアクセスする場合
- クライアントアプリケーションは ID プールを介して一時的な AWS 認証情報を取得し、必要な AWS リソースにアクセス
- 5b-6b.【リソースへのアクセス】:リソースサーバ(API サービス)にアクセスする場合
- トークンエンドポイントから返送される 主に アクセストークン(ユーザの認証情報を含む JWT 形式のトークンを提供)を Bearer Header に含めてバックエンド API にリクエストを送信
- バックエンドはアクセストークンに基づいてユーザを認可
Cognito による認証・認可のまとめ
- Amazon Cognito は、ユーザプールと ID プールの連携を通じて強力な認証および認可フレームワークを提供
- ユーザプールはユーザの認証とトークンの発行を管理し、ID プールはこれらのトークンを使用して AWS リソースへのアクセスを制御
- 一般に ID プールは、クライアントアプリケーションが AWS リソースにアクセスする必要がある場合にのみ構築される
- 例:外部 IdP のトークンを受け取り、AWS リソースにアクセスするための一時的な認証情報を発行
おわりに
今回のブログでは、OAuth 2.0 と OIDC に着目して、認証・認可について整理してみました。 実際はユースケースによって、実装方法が変わったり、認証・認可のフローや使用するプロバイダも異なったりします。 なので、ステレオで理解するよりも、まずは、認証・認可における "各コンポーネントがそれぞれどんな役割を担っているのか"、"何のための手続きをしているのか" をしっかりと把握しておくことが重要だと思います。
また時間がある際に Keycloak 等を使用してハンズオンしてみたいと思います。