認可画面のカナリアリリース
このドキュメントの目的
新しい認可画面を一部のリクエストにだけ見せて、段階的に切り替えることが目標です。
ui_config.signin_page を書き換えるだけだと全ユーザーが同時に切り替わり、問題があっても戻すまで全員が影響を受けます。バリアントを使うと、どのリクエストを新画面に送るかを RP アプリ側で制御できます。
所要時間
⏱️ 約15分
前提条件
- 管理者トークンを取得済み
- 組織ID(organization-id)とテナントID(tenant-id)を取得済み
- 新しい画面を配信済み(同じデプロイの別パスでも、別デプロイでもよい)
仕組み
テナントが名前付きのバリアントを宣言し、RP が認可リクエストにその名前を付けます。
RP -> /v1/authorizations?...&view_version=v2
↓
テナントの ui_config.variants から v2 を引く
↓
302 https://auth.example.com/v2/signin/?id=...&tenant_id=...
振り分けの主体は RP アプリです。どの割合を新画面に送るかは、RP がこのパラメータを付ける/付けないで決めます。
カスタムパラメータは OAuth 既知キー以外がすべてリダイレクト先のクエリと view-data に流れるので、画面側で自前に分岐できます。リクエストオブジェクトを使う場合は、その独自クレームも view-data に含まれます。ただしリダイレクト先の URL には載りません(署名・暗号化して送った値を URL に出さないため。PAR でリクエストオブジェクトを使った場合は、カスタムパラメータを URL に載せません)。FAPI Advanced のクライアントは、リクエストオブジェクトに入れた値だけが使われます。バリアントが必要なのは、新画面が別パスまたは別デプロイにある場合です。
設定
ui_config に variants を追加します。テナント設定の更新は全置換なので、GET したボディに追記して PUT してください。
"ui_config": {
"base_url": "https://auth.example.com",
"signin_page": "/v1/signin",
"signup_page": "/v1/signup",
"variant_param": "view_version",
"variants": {
"v2": {
"base_url": "https://auth-next.example.com",
"signin_page": "/signin",
"signup_page": "/signup"
}
}
}
| フィールド | 説明 |
|---|---|
variant_param | バリアント名を運ぶカスタムパラメータの名前(既定 view_version) |
variants.<名前> | そのバリアントが差し替える項目。base_url / signin_page / signup_page |
variant_param に OAuth/OIDC の予約語を指定しないdisplay prompt ui_locales login_hint acr_values などの既知パラメータ名を指定すると、カスタムパラメータとして扱われないためバリアントが一切選択されなくなります(エラーにはならず、全リクエストが既定画面に落ちます)。既定の view_version と衝突する場合は、auth_view_release のようなアプリ固有の名前にしてください。
継承のルール
バリアントは差分だけを書きます。ただしパスはそれを配信しているデプロイでしか意味を持たないため、base_url とパスは常に同じ側から解決されます。
| バリアントの宣言 | そのページの飛び先 |
|---|---|
| このページを宣言している | バリアントの base_url + バリアントのパス |
| ページを1つも宣言していない | バリアントの base_url + 既定のパス(同じパス体系のまま別デプロイへ) |
| 別のページだけ宣言している | 既定の base_url + 既定のパス(まるごと既定側へ) |
3行目が効くのは、たとえば base_url と signin_page だけを宣言したバリアントに prompt=create が来たときです。既定側の /v1/signup を新デプロイのオリジンに繋いでも、そのパスは新デプロイには存在しません。サインアップだけ 404 になるより、既定画面に落ちる方が安全なためこうしています。
新デプロイでサインアップも切り替えたい場合は、signup_page も宣言してください。
段階的な進め方
- バリアントを宣言する(この時点では誰も新画面に来ません。名前を付けたリクエストだけが対象です)
- RP アプリで一部のリクエストにパラメータを付ける(社内ユーザーのみ、1% のセッションのみ、など)
- 観測する。バリアント名はリダイレクト先のクエリと view-data に残るので、画面側でどちらのコホートかを記録できます
- 割合を上げる
- 切り替え完了後、既定の
signin_page/signup_pageを新しい値にしてバリアントを削除する
問題が出たら RP 側でパラメータを外すだけで戻せます。テナント設定の変更は要りません。
注意点
別オリジンに置く場合は CORS 設定が必要です。 画面は view-data API を XHR で呼ぶため、バリアントの base_url を cors_config.allow_origins に追加してください。追加を忘れると、リダイレクトも画面の表示も成功するのに view-data を取得できず、クライアント名・スコープ・認証方式が描画されないまま認証に進めない状態になります。サー バー側はエラーを返していないので、気づけるのはブラウザのコンソールだけです。
宣言していない名前は既定画面に落ちます。 認可 URL は公開 URL なので誰でも値を付けられます。受け取った名前はパスに連結されず、宣言済み候補のキーとしてのみ使われます。
ロールアウト中に 0% のままなら、まず variants のキーとリクエストの値が一致しているか確認してください(大文字小文字も区別します)。切り分けの目安は次のとおりです。
| 誤りの場所 | 例 | サーバーログ |
|---|---|---|
| 設定側(値の形が不正) | "v2": "/v2/signin"(オブジェクトでない) | 警告あり(そのバリアントを無視した旨) |
設定側(variant_param が予約語) | "variant_param": "display" | なし |
| リクエスト側(名前の typo) | ?view_version=v22 | なし |
リクエスト側の名前をログに出さないのは意図的です。公開 URL なので、未宣言の名前を毎回記録するとログ量を外部から制御できてしまいます。
エラー画面は対象外です。 リクエストのパース失敗時はカスタムパラメータ自体が存在しないため、エラー画面は常に既定の base_url から配信されます。
改ざんを防ぎたい場合は PAR を使ってください。 プッシュされたパラメータはクライアント認証で守られます。request object(JAR)の中にバリアント名を入れても現状は無視されます(#1836)。
関連ドキュメント
- 認可画面を別サイトに置く - 新しい画面が別サイトにあるとき
- テナント設定 -
ui_configのフィールドリファレンス - テナント設定(How-to) - テナントの作成