認証サバイバルガイド by Auth0
コンセプト
- 認証
- 人物のアイデンティティを特定するプロセス
- 認可
- 人物が権限を持っているかを判断するプロセス
- アイデンティティプロバイダ
- アイデンティティ情報を作成、維持、および管理するエンティティ
- e.g. Google, Facebook, Github
- デジタル署名
- 改ざんがないことを保証するための技術
- e.g. 「これは間違いなく Google が作ったデータだな」
- フレームワークとプロトコル
- フレームワーク=>仕様のみ
- プロトコル=>仕様と実装
OAuth 2.0
- 認可のためのフレームワーク
- サード(しばしばファーストも)パーティアプリケーションによる HTTP サービスへの限定的なアクセスを可能にする認可フレームワーク
- HTTP ベースのリソース(≒REST API)へのアクセス権(認可)を取得できるようにするためのもの
- ユーザ認証は OAuth の目的ではない
- アクセストークンの発行ルールとも言える
- パスワード等のクレデンシャルの共有が不要
- 登場人物(名もない画像編集アプリが、ユーザが Google Photo に保存しているファイルに対して編集を加える場合を想定)
- クライアントアプリケーション
- e.g. 名もない画像編集アプリ
- リソースサーバー
- e.g. Google Photo
- リソースオーナー
- e.g. Google ユーザー(かつ、名もない画像編集アプリのユーザー)
- 認可サーバー
- e.g. Google の認証サーバー
- クライアントアプリケーション
- 余談
- 誰が API を呼び出しているか知りたいだけなら、OAuth2 じゃなくても、API キーを使うだけで事足りる場合もあるので検討してみてね
- 認可サーバを自前で実装しようなどというバカな試みはやめておけ
- 脆弱性もあるし認証には使うな。認証には OIDC を使え。
OpenID Connect
- 認証のためのプロトコル
- ユーザ認証という特定の問題の解決に初めから重点を置いている
- ID トークンを発行する
- OAuth2 の曖昧な部分をはっきりさせている。例えば:
- OAuth2 ではトークンのフォーマットは規定されていないが、OpenID Connect では JWT と規定されている
- ユーザ情報を提供するための UserInfo エンドポイントについて規定されている
- まだ新しく発展途上である
エンタープライズプロトコル
- 企業内の問題は Active Directory などで解決してきたものの、
- ネットワークの外にあるアプリのために、SAML と WS-Federation という 2 つのプロトコルが作られた
SAML
- 異なるドメインをまたがるウェブブラウザベースの SSO
- 2 つのシステム感で必要な Web のやり取りを定義している
- 認証が済むと、真正性を検証可能な「トークン」が発行される
- ややこしいが、SAML といったときには、SAML で定義されているトークンのフォーマットだけを指す場合がある
- SAML のトークン部分だけが別のプロトコルで流用されることがある
WS-Federation
- ウェブブラウザベースの SSO
WS-***
というシリーズがいくつもあってどれもクソだが、その中でも FS-Federation はマシなプロトコル- 2 つのシステム感で必要な Web のやり取りを定義している
- SAML よりもはるかにシンプル
- トークンのフォーマットは事前に定義されていないが、多くの場合 SAML が使われる(ややこしい)
過去のプロトコル
過去のことは忘れて良い。互換性もまったくないし。
- OpenID 🪦
- OpenID 2.0 🪦
- OpenID Connect (現行)
- OAuth 1.0a 🪦
- OAuth 2.0 (現行)
トークンについての詳細
- 参照によるトークン(by-reference)
- Cookie ベースの認証
- ユーザ情報をサーバ側で Lookup する必要がある
- 値によるトークン(by-value)
- JWT ベースの認証
- 自己完結型トークンともいう
- トークン自体にユーザ情報が含まれている
トークンのフォーマット
- JWT
- 自己完結型トークン
- トークンにエンティティ(認証者)とトークンの対象(認証対象者)に関する情報が含まれている
- ステートレスな認証システムを作ることができる
- シンプル
- 使用方法にある程度の柔軟性がある
- トークンを表す方法が複数ある
- 署名及び暗号化の方法を任意に選択できる、など
- 一般的な構成
- Base64url でエンコード
- ヘッダ、ペイロード、署名などを HTTP で使いやすい方法で表す
- 暗号化はしない(OAuth2 等の仕様において HTTPS が必須とされているうえ、トークンコンテンツがそもそも秘匿情報ではない)
- SAML(トークンのフォーマットの話)
- JWT の登場前はメジャーだった。今はオワコン
- SOAP よりも HTTP がいい
- XML よりも JSON がいい
- SAML よりも JWT がいい
トークンのタイプ
- アクセストークン
- OAuth2 で定義されている
- 認可サーバーによって発行され、リソースサーバーで利用 される
- 保護されたリソースにアクセスするためのクレデンシャル
- アクセスできるか(権限)は知っているが、何にアクセスできるか(実際のコンテンツ)は知らない
- 数分から数時間で失効する
- フォーマットに要件はない
- が、一般的には自己完結型トークンを使ってサーバへの追加呼び出しを減らすのがよい
- アクセストークンをユーザ認証の手段として使うべきでない
- アプリが脆弱になるため
- ユーザの認証に使うトークンはすべて、そのトークンが特定のアプリケーションでの認証のために発行されたことを確認する方法を備えている必要がある
- リフレッシュトークン
- OAuth2 で定義されている
- 認可サーバーでのみ利用される(発行&利用)
- アクセストークンの再取得のために使う
- 寿命は数年から無期限
- 混乱ポイント「アクセストークンだけでよくね??」
- だめ。なぜなら:
- 認可サーバー側でアクセストークンを失効することができなくなるため
- トークンが全てのリクエストに使われるので流出の機会が増えるため
- だめ。なぜなら:
- ID トークン
- OpenID Connetct で定義されている
- JWT を使うことが義務付けられている
- アクセストークンやリフレッシュトークンには、トークンフォーマットの規定はない
トークンの保存
- 適切な方法でトークンを保存することは必須の要件
- モバイルなら
- 他のアプリがトークンにアクセスできないような場所に保存する
- e.g. Android なら SharedPreferences 機能など
- ブラウザなら
- ローカルストレージ or セッションストレージ (← これらがおすすめ)
- Cookie
- 詳細は本文参照
でも Cookie が好き
- Cookie が完全に時代遅れというわけではなく、役に立つ場面もある
- やみくもに Cookie を嫌わないこと
- ただし使うときは CSRF 対策、署名、暗号化などのセキュリティ対策はしっかりする