Skip to content

feat: extend import ClientBlueprint with PKCE, device auth, origins, lifetimes - #36

Merged
NathaelB merged 1 commit into
mainfrom
feat/import-client-blueprint-fields
Sep 3, 2026
Merged

feat: extend import ClientBlueprint with PKCE, device auth, origins, lifetimes#36
NathaelB merged 1 commit into
mainfrom
feat/import-client-blueprint-fields

Conversation

@NathaelB

@NathaelB NathaelB commented Sep 3, 2026

Copy link
Copy Markdown
Member

Summary

ClientBlueprint gains five optional fields the console exposes but the import format couldn't reproduce: post_logout_redirect_uris, web_origins, require_pkce, device_authorization_grant_enabled, and the four per-client token lifetimes (access_token_lifetime, refresh_token_lifetime, id_token_lifetime, temporary_token_lifetime). All stay optional/empty-by-default so existing blueprint files keep importing unchanged.

New client endpoints, discovered and verified live (none of these were documented, guessed via the same 405-Allow-header technique as earlier PRs):

  • POST .../clients/{uuid}/post-logout-redirects — same {value, enabled} shape as the existing redirects endpoint.
  • POST .../clients/{uuid}/web-origins{value} only.
  • device_authorization_grant_enabled is settable at client creation (added to CreateClientRequest).
  • PKCE and the four lifetimes are not settable at creation (silently ignored) — they require PATCH .../clients/{uuid} afterward. New update_client_settings, applied once per client after creation/resolution, mirroring the existing update_realm_settings pattern.

Issue

Closes #25.

Stacked on #35

This branch is based on fix/import-conflict-detection (#35), not main — it extends is_conflict/ImportReport further and would conflict badly if built independently. Merge #35 first; this will retarget to main automatically once that branch is gone.

Also found while verifying

  • A duplicate web-origin returns 400 with "...this origin is already registered..." — no "exist" in the body, so is_conflict needed widening (added here, on top of fix: recognize 500 unique-constraint conflicts on import replay #35's).
  • post-logout-redirects has no duplicate check server-side: re-adding the same value returns 201 every time. An import replay will keep accumulating duplicate rows for this specific field. Not fixable from the CLI; flagging it rather than pretending otherwise.
  • Confirmed live that resolve_client's conflict path (client already exists) is itself broken the same way as the role case in fix: recognize 500 unique-constraint conflicts on import replay #35: duplicate client_id returns an opaque 500 ("Failed to create client", no diagnostic text), not 409. So realm import replay does not actually converge for realms with clients today, on top of the role-replay gap already noted in fix: recognize 500 unique-constraint conflicts on import replay #35. Both need the server-side 409 fix; no safe CLI-side text match exists for either.
  • Keycloak/Zitadel import sources default all five new fields rather than extracting them — Keycloak in particular stores the equivalents under a free-form attributes map with Keycloak-specific keys (e.g. PKCE under attributes."pkce.code.challenge.method"), which is real additional scope this issue didn't ask for.

Test plan

  • cargo build --workspace
  • cargo test --workspace (74 passed, +1 new: web-origin conflict wording)
  • cargo clippy --workspace --all-targets --all-features -- -D warnings
  • Manual import against a running FerrisKey server with all five new fields set, confirmed each counter in the report, cleaned up the test realm

@NathaelB NathaelB self-assigned this Sep 3, 2026
@coderabbitai

coderabbitai Bot commented Sep 3, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 25 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Team

Run ID: bd1266ba-0f8a-4225-b3ab-99f3142e1f9c

📥 Commits

Reviewing files that changed from the base of the PR and between ff34a65 and 64916be.

📒 Files selected for processing (7)
  • libs/ferriskey-cli-client/src/lib.rs
  • libs/ferriskey-cli-core/src/client.rs
  • libs/ferriskey-cli-core/src/import/apply.rs
  • libs/ferriskey-cli-core/src/import/mod.rs
  • libs/ferriskey-cli-core/src/import/sources/keycloak.rs
  • libs/ferriskey-cli-core/src/import/sources/zitadel.rs
  • libs/ferriskey-cli-core/src/realm.rs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Base automatically changed from fix/import-conflict-detection to main September 3, 2026 00:28
… lifetimes

post_logout_redirect_uris, web_origins, PKCE requirement, the Device
Authorization grant toggle, and per-client token lifetimes were
missing from ClientBlueprint, so an import couldn't reproduce them and
they were lost on the next realm.

Adds the corresponding client endpoints (POST .../post-logout-redirects,
POST .../web-origins, PATCH .../clients/{id} for PKCE/lifetimes — the
latter only settable after creation, unlike the rest of a client's
fields) and applies them in apply.rs. All five stay optional so
existing blueprint files keep importing unchanged.

Keycloak/Zitadel sources default these fields rather than extracting
them: Keycloak carries the equivalent settings under a free-form
`attributes` map with Keycloak-specific keys, which is a separate
scope of work.
@NathaelB
NathaelB force-pushed the feat/import-client-blueprint-fields branch from 589207a to 64916be Compare September 3, 2026 00:30
@NathaelB
NathaelB merged commit 0bda168 into main Sep 3, 2026
4 checks passed
@NathaelB
NathaelB deleted the feat/import-client-blueprint-fields branch September 3, 2026 00:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The import blueprint covers only part of a client

1 participant