2026-08-09 22:42:51 +02:00
|
|
|
---
|
|
|
|
|
id: KEY-WP-0008
|
|
|
|
|
type: workplan
|
|
|
|
|
title: "Registration handoff and client-aware MFA policy"
|
|
|
|
|
domain: infotech
|
|
|
|
|
repo: key-cape
|
2026-08-16 01:05:27 +02:00
|
|
|
status: finished
|
|
|
|
|
owner: grok
|
2026-08-09 22:42:51 +02:00
|
|
|
topic_slug: netkingdom
|
|
|
|
|
created: "2026-08-09"
|
2026-08-16 01:05:27 +02:00
|
|
|
updated: "2026-08-16"
|
2026-08-09 22:42:51 +02:00
|
|
|
depends_on:
|
|
|
|
|
- NK-WP-0025
|
2026-08-25 20:13:23 +02:00
|
|
|
state_hub_workstream_id: "23eb67d4-cf10-57a1-92f6-90146a294bda"
|
2026-08-09 22:42:51 +02:00
|
|
|
---
|
|
|
|
|
|
|
|
|
|
# KEY-WP-0008 - registration handoff and client-aware MFA
|
|
|
|
|
|
|
|
|
|
Let a registered OIDC client offer NetKingdom signup and request step-up
|
|
|
|
|
without making KeyCape an account store or weakening high-assurance clients.
|
|
|
|
|
|
|
|
|
|
## T01 - Add a safe registration handoff
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
id: KEY-WP-0008-T01
|
|
|
|
|
status: done
|
|
|
|
|
priority: high
|
2026-08-25 20:13:23 +02:00
|
|
|
state_hub_task_id: "e5fb4d73-1e19-565c-80d5-e0eee274ce63"
|
2026-08-09 22:42:51 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Define an allow-listed registration URL for eligible clients and preserve
|
|
|
|
|
client ID, redirect URI, PKCE intent, tenant hint, and return context in a
|
|
|
|
|
signed, expiring state envelope. Registration completion must restart the
|
|
|
|
|
normal authorization flow and must not mint a token directly.
|
|
|
|
|
|
|
|
|
|
Done when unknown users can choose signup from an eligible authorization flow
|
|
|
|
|
without open redirect, client substitution, or state replay.
|
|
|
|
|
|
2026-08-16 01:05:27 +02:00
|
|
|
Implemented `prompt=create` and `/authorize/register` against the client's
|
|
|
|
|
static `registrationUrl`, plus HMAC-signed `kc_handoff` envelopes consumed
|
|
|
|
|
once at `/authorize/return`. Return restarts `/authorize` and never mints a
|
|
|
|
|
code. Ineligible clients get no signup link. Live registration entry remains
|
|
|
|
|
user-engine-owned per NK-WP-0025; KeyCape only issues the return envelope.
|
|
|
|
|
|
2026-08-09 22:42:51 +02:00
|
|
|
## T02 - Replace global MFA with client-aware minimum assurance
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
id: KEY-WP-0008-T02
|
2026-08-16 01:05:27 +02:00
|
|
|
status: done
|
2026-08-09 22:42:51 +02:00
|
|
|
priority: high
|
2026-08-25 20:13:23 +02:00
|
|
|
state_hub_task_id: "1ba50454-b6f5-578e-a526-da74b8082a89"
|
2026-08-09 22:42:51 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Replace the single require-for-all switch with policy that combines client
|
|
|
|
|
minimum assurance, requested ACR/step-up, tenant policy, protected action, and
|
|
|
|
|
current session assurance. Preserve mandatory MFA for platform/admin clients.
|
|
|
|
|
Allow coulomb-social ordinary login at password assurance when no stronger
|
|
|
|
|
rule applies.
|
|
|
|
|
|
|
|
|
|
Done when one low-assurance client cannot suppress MFA for another client or
|
|
|
|
|
reuse an under-assured session for a high-assurance request.
|
|
|
|
|
|
|
|
|
|
Implemented with nullable per-client `mfaRequired`: an explicit client value
|
|
|
|
|
overrides the provider default only for that client. Absent values preserve
|
|
|
|
|
the existing provider-driven policy.
|
|
|
|
|
|
2026-08-16 01:05:27 +02:00
|
|
|
2026-08-16: `DecideAssurance` now combines client minimum, requested ACR,
|
|
|
|
|
provider default, `max_age`, `prompt=login`, and current KeyCape login-session
|
|
|
|
|
level. An AAL1 session cannot satisfy an AAL2 client or `acr_values=aal2`.
|
|
|
|
|
`coulomb-social` in `config/dev-config.yaml` is `mfaRequired: false`; other
|
|
|
|
|
clients keep the provider default. Users without an enrolled factor are sent
|
|
|
|
|
to the client's `enrollmentUrl` instead of completing authorization.
|
|
|
|
|
|
2026-08-09 22:42:51 +02:00
|
|
|
## T03 - Support explicit step-up and fresh authentication
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
id: KEY-WP-0008-T03
|
|
|
|
|
status: done
|
|
|
|
|
priority: high
|
2026-08-25 20:13:23 +02:00
|
|
|
state_hub_task_id: "f7acbc12-e597-5d1e-8b29-bfa02237730f"
|
2026-08-09 22:42:51 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Implement supported ACR/max-age or equivalent IAM Profile parameters, invoke
|
|
|
|
|
privacyIDEA only when policy requires it, and return verifiable assurance
|
|
|
|
|
claims. Handle users without an enrolled factor through a safe enrollment
|
|
|
|
|
handoff rather than an authorization bypass.
|
|
|
|
|
|
|
|
|
|
Done when coulomb.social can request MFA for a profile/action and verify the
|
|
|
|
|
result from token claims.
|
|
|
|
|
|
|
|
|
|
Implemented `acr_values` preservation and AAL2/MFA forcing through the
|
|
|
|
|
privacyIDEA challenge. The existing token `assurance` claim reports `aal2`
|
|
|
|
|
and `mfa: true` only after successful verification.
|
|
|
|
|
|
|
|
|
|
## T04 - Prove policy isolation and compatibility
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
id: KEY-WP-0008-T04
|
2026-08-16 01:05:27 +02:00
|
|
|
status: done
|
2026-08-09 22:42:51 +02:00
|
|
|
priority: high
|
2026-08-25 20:13:23 +02:00
|
|
|
state_hub_task_id: "bc660767-387e-59a5-bfce-caccf4082c08"
|
2026-08-09 22:42:51 +02:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Test known and unknown users, registration link eligibility, state expiry and
|
|
|
|
|
replay, password-only coulomb-social login, profile/action step-up, no-factor
|
|
|
|
|
enrollment, OpenBao mandatory MFA, cross-client session reuse, and logout.
|
|
|
|
|
Keep static client registration and exact redirect rules unchanged.
|
|
|
|
|
|
|
|
|
|
Done when existing high-assurance clients pass unchanged and the new
|
|
|
|
|
coulomb-social journey passes live.
|
2026-08-16 01:05:27 +02:00
|
|
|
|
|
|
|
|
2026-08-16: isolation tests cover known/unknown users, registration
|
|
|
|
|
eligibility, state expiry/replay, password-only coulomb-social, ACR step-up,
|
|
|
|
|
no-factor enrollment handoff, OpenBao mandatory MFA, cross-client AAL1
|
|
|
|
|
session reuse, logout, and exact redirect enforcement. Full Go suite passes.
|
|
|
|
|
Live coulomb-social AAL1/AAL2 isolation was already proven on railiance01
|
|
|
|
|
under NK-WP-0025-T05 (2026-08-14); this closeout adds the KeyCape-side
|
|
|
|
|
regression suite and `/logout`.
|