Web 認証・認可(JWT / OAuth / OIDC)
細かい話題を束ねた概念ページ。各節は元は独立ページだった。
JWT とトークン認証
トークン自体に認証情報と署名を含めるステートレス認証の仕組み。_moc-web-infra
JWT の構造
<ヘッダ.ペイロード.署名>。claim を含むJSONをbase64エンコードしたものに署名を付与する。暗号化ではなく署名である点に注意(中身は誰でも読める)。
Authorization: Bearer <token>ヘッダで送る。- ステートレス: クライアントが毎回JWTを送るのでサーバは状態を持たなくてよく、認証サーバへの問い合わせ不要でスケールする。
署名アルゴリズム
- HMAC(HS256): 共有鍵による Hash-based MAC(ハッシュは SHA256)。auth サーバとリソースサーバが同一なら使える。
- RSA(RS256): 秘密鍵で署名・公開鍵で検証。auth とリソースが分離していても公開鍵を配れば検証できる(RSASSA-PKCS1-v1_5)。
Refresh Token
アクセストークンは短命(15分程度が定石)にし、長命(数週間〜数ヶ月)の refresh token で再発行する。
- フォーマットは自由(ランダム文字列でよい)だが、盗難に備え revoke 機能を用意すべき。
- claim には不変な値を設定する。
- ユーザーごとに複数の token pair を持たせたい場合、refresh token を JWT 化して claim に一意idを持たせDBに保存する。
保存先と安全性
localStorage ≒ sessionStorage < http-only Cookie < サーバセッション。いずれも XSS の前には無力。
- sessionStorage はタブ間で共有されない → 複数タブで認証状態を共有するなら localStorage(アクセストークンが十分短命なら許容)。
- ページ読込で複数APIが並列に飛ぶと refresh が多重発火し race するため、リクエスト前にフックして有効期限を確認するなどクライアント側で制御する。
CWT
JWT のバイナリ(CBOR)版。
関連
OAuth / OpenID Connect と SSO
ソーシャルログイン(SSO)を支える認可・認証プロトコル。_moc-web-infra
OAuth と OIDC の違い
- OAuth 2.0 は認可(リソースアクセスの委譲)のプロトコルであり、認証のためのものではない。
- OpenID Connect(OIDC)は OAuth に認証機能を足したもの。ユーザー情報を含む ID Token(JWT)を発行する。
- 本来は OIDC を使うべきだが、Twitter など未対応のProviderが多く、仕方なく OAuth 認可で得たユーザー情報をAPIサーバに送って認証とする実装が現実的。
用語
- OAuth Provider: 認可を提供する側(Google, Twitter 等)
- IDaaS: OAuth Provider 機能をサービス提供するもの(Auth0, AWS Cognito, firebase Auth)。Firebase Auth は1万ユーザーまで無料、その後 $0.06/user。
- ID Token: ユーザー情報をエンコードしたトークン。Google の場合
sub(一意),email,pictureを claim として得る。
OIDC による SSO フロー
- ユーザーがログインボタンを押す
- クライアントが OAuth Provider に認証要求 → ログインフォーム
- callback URL に認証情報が返る
- クライアントが ID Token(含むユーザー情報)を取得
- クライアントが ID Token をAPIサーバに POST
- APIサーバが ID Token を検証(Google API Client 等。
audienceに clientId を設定) - 妥当ならユーザーを作成/取得し、自前の JWT を返す
OIDC Provider の自前運用
IDaaS は高価なので OIDC Provider を自作する選択肢がある。Keycloak(Java製OSS, IDaaS)が定番。Realm/Client を作り、docker Compose で立て、Let’s Encrypt でHTTPS化、スティッキーセッションに注意。
関連
- web-authentication / web-browser-security
- spring-framework Spring Security での実装