認証とか認可とか
こっちにまとめた
一区切り
何もわからないので基礎知識を仕入れるところから
操作・構築は一旦後に回して、基礎知識を整理するのが目的
とりあえずこれ読む
Google の実サービスを操作してチュートリアルをする章以外を超超ざっくりまとめた
サマリ把握がちょっっっとだけできた
段落は本の章とは一致しない
適当なブロックで整理、まとめる都合で実際の本の段落の前後関係とはあまり一致しない
図は載せない、「これを読めばわかるメモ」ではなく「本を読み返すためのメモ」
OAuth とは
OAuth2.0 はサードパーティアプリケーションによる HTTP サービスへの限定的なアクセスを可能にする認可フレームワーク ( RFC6749 和訳 )
要点
- サードパーティ
- HTTP サービス
- 限定的なアクセス
- 認可フレームワーク
OAuth ( 明記しない限り 2.0 ) を使うと、ユーザはサードパーティアプリに HTTP サービスのユーザ名 / パスワードを教えなくて済む
逆に、教えている場合は
- 権限制御ができないので、サードパティアプリから全操作ができてしまう
- アクセス遮断には大元のパスワード変更が必要
- 攻撃を受けるとユーザ名 / パスワードが漏洩する可能性がある
ロール
登場ロールは4つ
リソースオーナー
リソースの所有者
だいたいユーザのこと
クライアント
リソースサーバを利用するアプリケーションのこと
画像管理アプリとする
- コンフィデンシャルクライアント
- サーバサイドのアプリケーションの場合
- セキュア
- パブリッククライアント
- ブラウザやネイティブアプリケーションの場合
- ブラウザを通すのでセキュアではない
リソースサーバ
画像を管理しているアプリケーションのこと
Google Photo とする
ここへのアクセスには常にアクセストークンを含む必要がある
認可サーバ
アクセストークンを発行するサーバのこと
Google の OAuth サービスとする
- リソースオーナーを認証する
- リソースオーナーの同意を得る
- アクセストークンを発行する
トークン
アクセストークン
2つの属性がある
- スコープ
- Google Photo の書き込み権限、シェア権限、といったコントロール
- 有効期限
- これをすぎるとリソースサーバは拒否する
リフレッシュトークン
アクセストークンの再発行を要求するときに使う
標準仕様では必須となっていない
アクセストークンはクライアント - リソースサーバ間でやり取りするのに対し、リフレッシュトークンはクライアント - 認可サーバ間でやり取りされる
認可コード
リソースオーナーがクライアントへ権限委譲することに同意した証
エンドポイント
3つの役割を理解する
認可エンドポイント
認可サーバに提供される
認可コードの発行が主な役割
トークンエンドポイント
認可サーバに提供される
アクセストークンの発行が主な役割
リダイレクトエンドポイント
クライアントが提供する
認可サーバから認可コードを受け取るのに使う
グランドタイプ
標準仕様では4つある
認可コード グラント
- 最も重要で最も複雑
- コンフィデンシャルクライアント ( サーバサイド ) に最適化されたグラント
- 4ロール登場する
- セキュアである
- アクセストークンがブラウザを経由しない
- 確認が多い
- リソースオーナーの認証を行う
- アクセス元の認証を行う
- SSL 証明書で認可サーバのアイデンティティを確認する
- リフレッシュトークンを発行できる
有料本なので図は載せない ( 29% のあたり )
インプリシット グラント
- パブリッククライアント ( ブラウザとか ) 向けのグラント
- ただし 2019 に非推奨になり、現在は認可コードグラント + PKCE が推奨
- 4ロール登場する
- シンプルではある
- 払い出されたアクセストークンがブラウザのリダイレクトエンドポイントを経由してクライアントに渡るので脆弱
有料本なので図は載せない ( 40% のあたり )
クライアント クレデンシャル グラント
- クライアント - 認可サーバ でアクセストークンを発行するグラント
- 3ロール登場する ( クライアント = リソースオーナーになる )
- アクセストークンはユーザ単位ではなくクライアント単位になる
- エンドユーザが登場しないのでユーザ名 / パスワードの入力も、権限以上の同意も行われない
有料本なので図は載せない ( 45% のあたり )
リソースオーナー パスワード クレデンシャル グラント
- 4ロール登場する
- リソースオーナーのユーザ名 / パスワードがクライアントを経由して認可サーバに行く
- クライアントは保存しない様にする
有料本なので図は載せない ( 48% のあたり )
リフレッシュトークンによる再発行
リソースサーバは有効期限が切れたアクセストークンを受け取ると 401 Unauthorized のエラーを返す
そうなったら、クライアントはトークンエンドポイントにリフレッシュトークンを投げて、新しいアクセストークンをもらう
PCKE と認可コード横取り攻撃
- Proof Key of Code Exchange の略でピクシーと読む
- OAuth の拡張仕様 ( RFC7636 ) で定義されている
パブリッククライアント向けのグラントとして ( インプリシットグラントではなく ) 推奨されている、認可コードグラント + PKCE について
認可コードを受け取るときに、リダイレクトエンドポイントのカスタムスキームでアプリを起動して行う
悪意あるアプリが同じカスタムスキームで控えている場合、そちらが OS に起動されて認可コードを横取りされてしまう可能性がある
有料本なので図は載せない ( 55% のあたり )
PCKE では3つのパラメータを用いてそれを防ぐ
- code_verifier: ランダム文字列
- code_challenge_method: plain | S256
- S256 にしとけ
- code_challenge: ランダム文字列を method で計算した値
ネイティブアプリがブラウザへこれを伝えて、ブラウザが認可サーバにこれを伝える
カスタムスキームで起動したアプリがもう一度この値を検証できれば、投げたアプリであることが確認できるのでなりすまされない
有料本なので図は載せない ( 60% のあたり )
OAuth 2.0 については、この辺も
今読めば頭に入る
そしたら OpenID Connect を確認する
そしたら SSO とか調べる
これ読む
OAuth の部分については軽めに整理した
OAuth とかセキュリティ対策とかがわかりやすい本だったけど、あんまり OpenID Connect 自体について細かく書かれている本ではなかった...
( 本の中で「本書は OpenID Connect と OAuth を明確に区別しない、大抵の場合は OpenID Connect は OAuth を利用することになるので、OpenID Connect という表記には暗黙的に OAuth を含んでいるものとする」と書いてあったし )
OAuth 2.0
- OAuth 2.0 ( 以後 OAuth ) はが先に登場
- 認可のプロトコル
- OAuth はユーザ認証としても使える
- アクセストークンがあれば、クライアントはユーザ登録しなくて済む
- ただし問題もある
- 認証情報 ( 手段や日時など ) や、ユーザ情報 ( id, mail など ) を取得する仕様が定まっていない
OpenID Connect
- OpenID Connect ( 以後 OIDC ) は OAuth をユーザ認証として活用するために拡張したもの
- 主な利用シーンとして考えられるもの
- SNS などのサイトのデータを利用したい
- SNS などのサイトに認証を任せたい
- SSO プラットフォームにしたい
- バックエンドサービス間で安全に通信したい
エンドポイントの種類
軽めに
- 認可エンドポイント
- トークンエンドポイント
- リダイレクションエンドポイント ( 英語だとなんて言ってるんだろ )
Authorization Server が提供するエンドポイントの一覧は /.well-known/openid-configration
で参照できる
これは OIDC の仕様で定められている
フローの種類
軽めに
グラントのこと
英語だとどっちなんだろ
- 認可コードフロー
- 認可コードをランダムに生成し、それと引き換えにアクセストークンを取得する
- インプリシットフロー
- SPA のクライアントを想定
- OAuth が登場した頃は JS から別ドメインの URL にアクセスできなかったため
- 今は CORS で別ドメインにアクセスできるし、脆弱なので、非推奨
- ハイブリッドフロー
- 認可コードフローとフローは同じだが、リダイレクト URL に認可コードの他にもトークンを含める
- クライアントが複数の Authorization Server と連携する場合に発行元を識別できるのでセキュア ( 後述 )
- クライアントクレデンシャルフロー
- ユーザが出てこない
- バッチ処理でユーザが管理しないコンテンツにアクセスするとかに使う
- リソースオーナーパスワードクレデンシャルフロー
- ユーザ ID とパスワードをクライアントに渡す
- OAuth のドラフトでは MUST NOT be used になっている
認可コードフロー
- 認可リクエスト
- scope: 空白区切、OIDC の仕様で示されるもの + 任意に定めたもの
- response_type: code
- response_mode: query | fragment、フラグメントはリダイレクト先サーバに送信されない
- client_id: 文字列
- redirect_uri: 文字列
- 認可レスポンス
- リダイレクションエンドポイントへのリクエスト
- トークンリクエスト
- SPA の場合、クライアントのドメインとトークンエンドポイントのドメインは ( ほぼ ) 異なる
- トークンレスポンスのヘッダに CORS ヘッダの付与をして、クライアントからのアクセスを許可する必要がある
- CORS ヘッダの設定は Authorization Server 側で必要
JWT
- OIDC は認証情報 ( 手段や日時など ) や、ユーザ情報 ( id, mail など ) を記載した ID トークンと呼ぶものを発行する
- ID トークンは Json Web Token の形式で記される
- OFC7519 で標準化されている
- Claim と呼ばれる KV で記す
- 標準的なものは RFC7519 や OIDC の仕様で定まっている
- iss ( Issuer )
- sub ( Subject )
- azp ( Auhorized Party )
- aud ( Audience )
- exp ( Expiration Time )
- iat ( Issued At )
- jti ( JWT ID )
- acr ( Authentication Context Class Reference )
- nonce
- name
- profile ( profile url )
- JWT は3つで構成される
- ヘッダ ( アルゴリズム情報など )
- ペイロード ( iss や sub など )
- 電子署名
- その3つを Base64URL エンコードをして
.
でつないだものが JWT - BASE64URL デコードするなら https://jwt.io とか使うといいよ
ユーザ情報の取得
アクセストークンを取得した後は、ユーザに関する情報を Authorization Server のユーザ情報エンドポイントから取得できる
ただ、通常は ID トークンにも含まれているので、リクエストする必要はない
セキュリティの脅威と対応
HTTPS にすれば防げることは除く
リダイレクションエンドポイントの CSRF
- Cross-site Request Forgery
- 攻撃者が用意した悪意あるリンクをユーザに踏ませる
- OIDC においては、リダイレクションエンドポイントのリンクを攻撃者が用意する手口がある
- 認可リクエストとリダイレクションエンドポイントへのリクエスをに state パラメータを使い対応する
オープンリダイレクト
- リダイレクト先として意図しない URL に誘導すること
- OIDC においては、認可リクエストの redirect_uri パラメータの攻撃者のサーバの URL を設定する手口がある
- Authorization Server に事前にリダイレクト先の URL を登録し、redirect_uri パラメータをチェックすることで対応する
Referrer ヘッダによる認可コードの漏洩
- リダイレクションエンドポイントにリダイレクトした後の画面で表示中の URL には認可コードが含まれる
- そこから攻撃者の外部サイトに渡った場合、Referrer ヘッダから認可コードを盗む手口がある
- SPA の場合は response_mode で fragment を指定することで対応する
- MPA の場合は一度他の安全な画面にリダイレクトさせることで対応する
他のクライアントに発行したアクセストークンの転用
- 1つの Authorization Server を複数のクライアントが利用している場合、攻撃者が運営するクライアントが潜む場合がある
- 悪意あるクライアントがアクセストークンを転用して正当な Resource Server にアクセスする手口がある
- アクセストークンの有効性の確認に、電子署名に加えて Client ID や Resource Server の識別子をチェックすることで対応する
Authorization Server の混同
- 1つのクライアントが複数の Authorization Server を使う場合、攻撃者が運営 ( 乗っ取った ) Authorization Server が潜む可能性がある
- その場合2つの脅威がある
- 正当な Authorization Server が発行した認可コードが攻撃者の Authorization Server に漏洩する
- リダイレクションエンドポイントの URL を Authorization Server ごとに別にする
- 正当な Authorization Server の攻撃者のアカウントでユーザがクライアントを使ってしまう
- どの Authorization Server を使ったかクライアントが管理し、リダイレクションエンドポイントへのリダイレクト時に検証する
- 正当な Authorization Server が発行した認可コードが攻撃者の Authorization Server に漏洩する
- 2つを踏まえると、選択した Authorization Server を管理し、リダイレクションエンドポイントを Authorization Server ごとに別にして、リダイレクト時に検証することが望ましい
URI スキーマの不正な登録
- ブラウザ以外でクライアントが動作するアプリで OIDC を使用する場合に、固有スキーマ (
myapp:
など ) にリダイレクトする - 攻撃者が同じ固有スキーマのアプリをインストールさせ、そちらを起動させる手口がある
- PKCE ( 認可コードフローを拡張したもの ) を用いて、認可リクエストを送ったクライアントしかアクセストークンを取得できなくすることで対応する
一番分かりやすい OpenID Connect の説明 - Qiita
OpenID Connect はあくまで OAuth 2.0 の拡張仕様だよ
認可コードグラントで最後にアクセストークンが手に入るところで、ID トークンを要求して取得できる点が違うよ
ID トークンはユーザの情報 ( 氏名とかメアドとか ) を含んでいるし、アクセストークンと同じフローで本人認証を済ませているので、このトークンを引き回すことができればユーザ認証を繰り返さなくて良いよ
= SSO という理解
トレンド比較
製品 ( 世界 )
製品 ( 日本 )
OSS ( 世界 )
OSS ( 日本 )
OAuth 2.0 + OpenID Connect のフルスクラッチ実装者が知見を語る - Qiita
自分でゼロから作る場合の要点が書いてある
仕様としては OpenID Connect は OAuth 2.0 の拡張だけど、実装は全然拡張では対応しきれない
→ 2 択が 8 択になるんだろうなぁ
→ OpenID Connect 全フロー解説 - Qiita
OAuth 2.0 を実装する、OpenID Connect を実装する、という段階を計画すると破綻するっぽいので、それだけ覚えておけば今は十分
ざっと読んだけど、詳細はその必要に迫られたらもう一度確認する
1行でまとめるとこれ
OpenID Connect をフルスクラッチ実装するのは正気の沙汰ではない
Cognito
2 )
概要 ( 参考- 認証、認可、ユーザ管理を行うサービス
- Cognito は SDK
2, 3, 5 )
主なコンポーネントは2つ ( 参考ユーザープール
- ユーザのサインアップとサインインオプションを提供するユーザディレクトリ
- フルマネージド
- 直接サインインするか、IdP を通じて連携する
- 以下に対応
- OAuth 2.0
- SAML 2.0
- OpenID Connect
- MFA
- カスタマイズ可能なサインイン UI
- ソーシャルログイン
- ユーザープールからの SAML および OIDC IdP 経由のサインイン
- ユーザプロファイルの管理
- 漏洩チェック、乗っ取り保護、電話とメール検証
- Lambda トリガーによる移行
- サインイン失敗5回で一時ロックアウト
ID プール
- AWS の他のサービスに対するアクセスをユーザに許可する
- 匿名ゲストユーザに対応
- IdP のサポート
- Amazon Cognito ユーザプール
- Facebook, Google, Login with Amazon, Sign in with Apple
- OIDC プロバイダ
- SAML プロバイダ
1 )
2機能ある ( 参考( 上とどう違う? Cognito Identity の内訳? )
Cognito Identity
- AWS のサービスを利用するユーザーに 一意のアイデンティティ を与えるサービス
- 匿名ユーザとして ID を発行する方法
- パブリックなログインプロバイダの ID と紐づける方法
- Facebook, Google, Amazon, Twitter, etc...
Cognito Sync
- AWS のサービスを利用するユーザーに 固有のデータあストレージ を与えるサービス
- Cognito Identity により一意になったユーザに対して、ユーザデータを保存する場所を提供する
- デバイスによらずデータが同期される
2, 4 )
料金 ( 参考- Monthly Active User に基づいて支払いが発生する
- サインアップ、サインイン、トークンの更新、パスワードなどの操作が MAU にカウントされる
- 直接サインインは 50,000 MAU まで、SAML 連携ログインは 50 MAU までは無料
- 試算
- 月 300 万 MAU とすると、超ざっくり 100 万円/月
- ただし SAML / OIDC 連携の場合は MAU 単価が 15 倍くらい高いっぽい
- 高度なセキュリティ機能 ( 監査含む、詳細未調査 ) を有効にすると、450 万円/月 上乗せっぽい
- MFA の SMS を送信するのは別途料金
6 )
シナリオ ( 参考ユーザプールで認証
- 直接
- IdP 連携
- ソーシャルサインイン
- SAML / OIDC
ユーザプールを使用してサーバリソースにアクセス
- ユーザプールにサインインするとユーザプールトークンが得られる
- バックエンドのアクセスに使う
- ユーザプールにドメインを設定すると Cognito によって UI がプロビジョンされ、サインインページを持て OAuth 2.0 基盤にできる
API Gateway / Lambda のアクセス制御をする
- インフラレベルでやるかな?
ID プールを使用して AWS サービスを使う
- ユーザプールトークンを ID プールトークンに変換する
- それで S3 や Dynamo を使う
サードパーティで認証し、ID プールを使用して AWS サービスを使う
- ほぼ同上
Cognito と AppSync を連携する
- ユーザトークン ( もしくは ID トークン? ) を利用して AppSync ( GraphQL のやつ? ) を利用する
感想
- ID プールはいらないかな?
- ID 管理を cognito に任せる場合、サインインが MAU にカウントされるので 100 万円/月 は見ないといけない?
- SAML / OIDC 連携する割合を想定しないと破産する?
- グループというのを設定するとアクセストークンでそれが得られる
"cognito:groups": ["admin"]
- スコープは自分で設定できるの? → カスタムスコープの管理でできる ( 参考 8 )
- PHP の SDK がないっぽい??
- 参考 7 を見る限りは...
-
java のサンプル は結構簡単に
iss
とか取れてる - 低レベル API ってのはあるっぽい
- Cognito じゃあなくて aws-sdk だから、もっと汎用なのか...??
- ID トークンの検証ちょっとめんどくせーな...
-
java のサンプル は結構簡単に
参考
Cognito のデータ移行について
ちょっと追記
2つある
ユーザの初サインインの時に Lambda トリガーで
- ユーザが既存のパスワードを引き続き使用できる
- ユーザプールへの移行後にパスワードを再設定しなくて良い
一括移行
- csv をアップロードする
- パスワードは csv 書式に含まれない
- 初回サインイン時にパスワードの変更が必要
所感
- Lambda トリガー方式
- 👍 パスワードが変わらない
- 👎 移行完了時期の検討がつかない
- 一括方式
- 👍 移行タイミングを制御できる
- 👎 パスワードが変わる
- どちらも料金が不明...
- サインアップにカウントされてしまうと 1500 万 MAU ( 400 万円 ) くらいかかる
参考
Keycloak
1 )
概要 ( 参考- OIDC 対応
- SAML 対応
- Keycloak を IdP として利用できる
- 認証バックエンドとして Active Directory を利用できる
- フロー
- ユーザが SP にアクセス
- SP が認証済みか調べ、まだなら Keycloak のログイン URL をリダイレクトレスポンスする
- Keycloak でログインする
- SP に Keycloak が発行した認証トークンが送られる
- 対応ソーシャル
- GitHub
- Microsoft
- PayPal
- OpenShift v3
- Gitlab
- BitBucket
- StackOverflow
- TFA
- パスワードリカバリ
- 電子メールによる検証
- 強制パスワード変更
アイデンティティー・ブローカリングというのができる
既存の OIDC もしくは SAML プロバイダと連携し、それに登録されている ID で Keycloak にログインさせる
Keycloak 管理コンソールで設定するだけ
これを使うと Cognito のユーザプールで Keycloak 認証ができる?
ケルベロスに関する記述はカット
ユーザやロールやクライアントの設定を管理するコンソールがある
ユーザの画面をカスタマイズでき、ブランディングと統合できる
レルム管理
ユーザやロールなどを含む SSO に関する設定
- パスワード再発行機能の ON/OFF
- 初回ログイン時のメールによる本人確認
- メアドログイン可否
- UI テーマ
- 言語設定
- セッションタイムアウト
- ブルートフォースアタックの検知とブロック時間の設定
- ID/PW の総当たりのこと
- SAML/OIDC クライアント管理
- ロール管理
- IdP 連携
クライアント管理
クライアントごとに設定できる
- SAML/ OIDC どちらか
- 認証エンドポイント
- SSL 関連
- Keycloak が持つ属性とアプリに渡す属性のマッピング
- ロール情報
アダプタ
SDK のことかな?
- Java
- JBOSS
- WildFly
- Tomcat
- Jetty
- Spring
- Javascript
- NodeJS
アプリにアダプタを入れるかリバプロを立てることで SSO を実現できる
フェデレーション
既存のユーザ DB と認証情報を統合するフェデレーション機能がある
LDAP または Kerberos に対応している
監査
セッションやイベントの管理が可能
- 例
- ユーザのセッションの強制切断
- ログインユーザのログ参照
SSO
- エージェント方式が可能
- Keycloak Proxy 方式 ( = リバプロ方式 ) が可能
- アプリが OIDC / SAML が喋れれば SSO 可能
所感
- また PHP がない
- とはいえリバプロは単一障害点としてしんどそう
- 勢いのある OSS という点がどう影響するかよくわからない
- しばらくはマイナーアップデートとか bug fix に追われたりする?
- ポリシーやライセンスが変わったりしないか ( 例えば OpenAM みたいに )
- Keycloak 自体のデータベースが必要なはず、それと Keycloak の APP サーバ
- スタンドアロン版ってのを立ててみたら DB は localhost っぽかったけど...
- H2 っぽい
- MySQL に変えられるけど、結局ローカルっぽい
- スタンドアロン版ってのを立ててみたら DB は localhost っぽかったけど...
- 共有 DB と冗長 Keycloak という構成も可能 ( 参考 4 )
参考
- Keycloak〜OpenAMに替わるシングルサインオン〜 | OSSでのシステム構築・デージーネット
- Keycloak とは?動作確認や機能、特徴などを解説 | OSSサポートのOpenStandia™【NRI】
- Keycloakのインストールと構築例 | Think IT(シンクイット)
- Keycloakを冗長構成で動かしてみる - Qiita
連携
まだざっくり...
Cognito で Keycloak にログイン?
CognitoにOpenID Connectを使ってKeycloakを連携させてみる | DevelopersIO