# org-master-sync phase3: 本番プリザンター投入 + Keycloak本番切替 2026-08-12実施。本番プリザンター(`nextoffice.next-hd.co.jp`)へのマスタ投入と、Keycloak `nexthd`レルムの検証環境→本番環境切替、SSO確認画面の完全排除を実施した記録。 ## 1. 本番プリザンターへのマスタデータ投入 - `.env.production`にemail-overrides(`kenichiro.nogi=460`, `mitsuharu.takahashi=678`)を設定 - `merge-master.js --no-create-groups`実行 → **613件新規作成**(グループ・組織テーブルへの新規作成なし、既存一致分のみ反映) - 役職マスタ8件・職級マスタ6件・利用権限タイプマスタ4件、LINEWORKS取得結果と完全一致 - Groups APIは新規作成ゼロ(既存59グループから変化なし) - 所属グループ(Class035)は反映時点で全員空 — 本番Groups APIに一致するグループが存在しなかったため(意図通り、別途対応) 途中、本番プリザンターがバージョンアップ+SSO対応作業中で一時的にAPI不通(502)になる場面あり。復旧後に再開。 ## 2. Keycloak `nexthd`レルムの洗い替え **背景:** これまでの`nexthd`レルムは検証環境プリザンター(`nextoffice2.next-hd.net`)のマスタ(SiteId=1)を基準に同期していた351件。本番運用切替につき、本番マスタ(SiteId=502552)ベースへ全面入れ替えが必要だった。 **手順:** 1. 旧351件(検証同期分)を全削除(`DELETE /admin/realms/nexthd/users/{id}`、`service-account-org-master-sync`除く) 2. `sync-keycloak.js --execute`を`.env.production`で実行 → **351件新規作成**、update/delete 0件 3. サンプル確認(`ntkco12216` → `kenichiro.nogi_502662`): `Class011=460`, `Class036=kenichiro.nogi@next-hd.co.jp`、正しく反映 **ハマった点:** 初回実行時、削除より先にcreate/updateが走る設計のため、旧351件が残った状態で本番データのcreateを試み、メールアドレス重複エラー(`User exists with same email`)で失敗。旧データを先に全削除してから再実行して解決。 **プリザンターSAML Client URL変更:** Keycloak Admin API経由で`clientId`(EntityId)・`redirectUris`を`nextoffice2.next-hd.net`→`nextoffice.next-hd.co.jp`へ更新。表示名も「プリザンター(本番)SSO」に変更。 ## 3. 検証用レルム`nexthd-test`の複製 `nexthd`が本番専用になるため、今後も継続利用する検証環境として`nexthd-test`を新規作成。 **試して失敗した方法:** - Keycloak管理コンソールの「Create realm」でpartial-exportしたJSONをそのままアップロード → 内部UUID(`id`)が既存レルムと衝突し`Conflict detected` - `id`を再帰的に全削除 → 今度は`authenticationFlows`内の相互参照(親子関係)が壊れ`Unable to resolve auth flow binding override` - `authenticationFlows`のidだけ保持 → 別のid衝突(`constraint_auth_pk`) **成功した方法: 空レルム作成 + Partial Import** 1. Keycloak管理コンソールで`nexthd-test`を空レルムとして作成 2. `PartialImportRepresentation`形式(`{ifResourceExists, clients, identityProviders, identityProviderMappers, groups}`。`authenticationFlows`は対象外、Keycloak仕様上の制約)でJSON生成、`id`/`internalId`を再帰削除 3. `clients`内の`authenticationFlowBindingOverrides`(元レルムのカスタムフローid参照)を削除しないと`Unable to resolve auth flow binding override for: browser`で失敗するため要除去 4. Partial Import画面からアップロード → クライアント9件・IdP1件・グループ63件、正常インポート 5. **ユーザー(351件)とグループメンバーシップ(1940件)はPartial Import非対応のため別途Admin API経由で個別複製**(`GET /admin/realms/nexthd/users`→`POST /admin/realms/nexthd-test/users`、グループ紐付けは元レルムの`GET /users/{id}/groups`→`PUT /users/{id}/groups/{groupId}`) `org-master-sync`クライアントのシークレットは複製時にリセットされる(平文コピーされない仕様)ため、GUIから再発行が必要だった。`.env`の`KEYCLOAK_REALM`/`KEYCLOAK_ADMIN_CLIENT_SECRET`を`nexthd-test`向けに更新済み。 ## 4. SSO確認画面の完全排除(最重要の技術的知見) **要件:** LINEWORKS SSOログイン時、確認画面(Account already exists → Add to existing account のワンクリックも含む)を一切出さず完全自動ログインさせたい。 **試して失敗したアプローチ(Keycloak 26.0.8実機検証):** 1. `Confirm link existing account`をDisabled → 新規ユーザー作成画面に見える`Update Account Information`が出た - 真因判明: `Update Profile on First Login`(Review Profileステップの個別設定)が`missing`。LINEWORKSがfirstName/lastNameを送らない(``が空、NameIDのみ)ため「情報不足」判定 → `off`に変更して解消 2. 改めて`Confirm link existing account`をDisabled → `Account verification options`配下の`Verify Existing Account by Re-authentication`がフォールスルー実行され、パスワード未設定で`Invalid username or password` 3. `Verify Existing Account by Re-authentication`もDisabledに変更 → その孫ステップ`Username Password Form for identity provider reauthentication`はUI上Requirement変更不可(常にRequired固定)で実行され、同じエラーが再発 **結論:** Keycloakの標準First Broker Loginフローは、親ステップをDisabledにしても配下のRequired固定ステップがフォールスルー実行される仕様上の制約があり、フロー設定の調整だけでは確認画面を完全に消せない。 **最終解決策(実機検証済み):** Keycloak Admin API `POST /admin/realms/{realm}/users/{id}/federated-identity/{provider}` で、SSOログイン前に**federated-identityを事前登録**する。`userId`はSAML NameIDと一致する値(LINEWORKSメールアドレス)。これによりKeycloakは「初回ログイン」と判定せず、**First Broker Loginフロー自体を丸ごとスキップ**し、通常のBrowserフローのみで確認画面なし・即ログイン成功する。 **実装:** - `apps/org-master-sync/src/lib/keycloakClient.js`に`getFederatedIdentities`/`linkFederatedIdentity`追加 - `sync-keycloak.js`のユーザーcreate/update時に自動リンク(未リンクの場合のみPOST、既にリンク済みなら何もしない) - 351人全員へ一括登録実施済み - テスト94件全パス **フロー設定は`Disabled`のまま維持する方針(ユーザー確定)。** federated-identity登録漏れのユーザーは「確認画面を出す」のではなく「`Invalid username or password`でログイン自体を弾く」方が安全という判断。サイレントにログインさせないことをデフォルトの安全策として採用。 ## 残課題 - ~~`Authentication.json`の`Provider`を`null`→`"SAML"`に変更してSSO有効化~~ → 対応済み(本番側で`"SAML"`に更新確認済み) - ~~SAML署名証明書のSubject DNが旧URL(`nextoffice2.next-hd.net`)のまま~~ → 放置確定。SSOログイン成功済み=署名検証は正常通過している証拠(署名検証は公開鍵でのバイト列検証のみでCNの中身は見ない)。エラーが出る場合はKeycloak Client詳細→Keysから鍵再生成 - ~~`nexthd-test`レルムのFirst Broker Loginフロー・認証フローカスタマイズ(Account verification options等)は未複製~~ → 対応済み。`Confirm link existing account`/`Account verification options`をDisabled、IdP`Update Profile on First Login`を`off`に変更、351人分`federated-identity`も一括登録。`nexthd-test`のSAML Client URLはたまたま`nextoffice2.next-hd.net`のまま(複製タイミングが本番URL変更"前"だったため)、検証環境として意図せず正しい状態