net-kingdom/canon/standards/iam-profile_v0.4.md
tegwick b808da601d
Some checks are pending
CI Smoke / host-smoke (push) Waiting to run
CI Smoke / container-smoke (push) Waiting to run
Draft execution-attribution and workload-step-up amendments; route remaining tasks
- playbook-capability-contract_v0.2.md (proposed): adds the
  execution-attribution receipt field list (NK-WP-0040-T01).
- iam-profile_v0.4.md (proposed): adds the workload-requested step-up
  contract (acr_values, no-factor refusal, assurance.level to flex-auth)
  (NK-WP-0042-T01).
- Route the remaining externally-owned decisions (NK-WP-0040-T02 to
  audit-core/Railiance, NK-WP-0042-T02 to user-engine, NK-WP-0039-T04 to
  flex-auth/tenant-engine) and mark those workplans blocked.

Assistant: claude-code
Assistant-Model: sonnet
Assistant-Process: 321494@bnt-lap001
Assistant-Session: 2c8a5cd1-573e-4bae-ab2b-29bc6c8ed4e9
2026-09-27 23:59:51 +02:00

99 lines
4.4 KiB
Markdown

---
id: netkingdom-iam-profile-v0.4
type: standard
title: "NetKingdom IAM Profile v0.4"
domain: netkingdom
status: proposed
owner: net-kingdom
created: "2026-09-27"
updated: "2026-09-27"
scope: core-platform
supersedes:
- canon/standards/iam-profile_v0.3.md
adr:
- docs/adr/ADR-0011-iam-profile-ownership-and-version-governance.md
- docs/adr/ADR-0016-mfa-user-preference-and-workload-step-up.md
related:
- NK-WP-0042
---
# NetKingdom IAM Profile v0.4
Everything in v0.3 stands unchanged except where this document says
otherwise. v0.3 remains `accepted` and normative; this document adds the
workload-requested step-up contract as a proposed amendment
(`NK-WP-0042-T01`). It does not require any workload to request MFA;
ADR-0016's default — MFA is a user preference — is unchanged, and the
enrollment/recovery usability gate in ADR-0016 §4 still applies before any
workload turns a requirement on.
## Workload-Requested Step-Up (proposed)
ADR-0016 lets a workload require AAL2 for all or part of its features
instead of leaving MFA to user preference. This section defines the
OIDC-level request and the no-factor refusal contract so every issuer
implements the same interface. **key-cape owns the implementation**; this
profile owns the interface, per NK-WP-0042-T01.
### Requesting step-up
- **Whole-client requirement.** A workload that requires AAL2 for all of
its sign-ins registers this at the client, unchanged from the existing
lightweight-mode client configuration (`mfaRequired` / P06 semantics).
This subsection does not change that path.
- **Per-request step-up.** A workload that requires AAL2 only for a
protected feature sends `acr_values` on the authorization request,
containing one of the `assurance.level` values this profile already
defines: `aal2` or `aal3`. The issuer MUST treat a recognized
`assurance.level` value in `acr_values` as a request for that floor.
- `max_age` MAY be combined with `acr_values` to also force a fresh
interactive login. `max_age` MUST NOT be used alone to request
strength: it bounds session age, not factor count. A request carrying
only `max_age` gets a fresh login at whatever assurance the user
already holds, not an implied AAL2.
- A request MUST NOT use a provider-native `acr` value as a substitute for
the profile's `assurance.level` vocabulary. Provider-native `acr`/`amr`
claims remain informational (Assurance Evidence, v0.3).
### No-factor refusal
If the requested floor is `aal2` or higher and privacyIDEA (or the
issuer's equivalent authoritative factor source) reports no active
factor for the user, the issuer MUST NOT silently issue a token at a
lower `assurance.level`. It MUST do one of:
- **Inline enrollment detour:** present the enrollment flow itself and,
on completion, resume and complete the original authorization request;
or
- **Explicit refusal:** fail the authorization request with an
OAuth-shaped error distinct from a generic `access_denied` (e.g.
`error=mfa_required`), so the requesting client can route the user to
enrollment itself.
Silent issuance of `assurance.level: aal1` (or omission of `assurance`)
in response to an `acr_values` request for `aal2`/`aal3` is nonconforming.
This governs the machine contract only; which of the two options a given
workload presents, and the exact enrollment/recovery UX, is
`NK-WP-0042-T02`'s open agreement with user-engine (U06) and a pilot
workload — this profile does not decide it.
### Reaching flex-auth
No new claim is introduced. The outcome is carried by the existing
`assurance.level` claim on the issued token (Assurance Evidence, v0.3):
a workload's per-request requirement is satisfied, refused, or detoured
before a token is issued, and flex-auth continues to read the issued
`assurance.level` exactly as the Identity To Authorization Contract table
already specifies. flex-auth MUST NOT infer a "requested vs. granted"
distinction from any other claim; there is only the token that was
issued.
### Non-goals
- This does not lower the IAM Profile v0.3 floor: privileged, destructive,
platform-root, secret, credential-vending, and emergency flows still
require `aal2` or stronger regardless of workload opt-in (ADR-0016 §3).
- This does not specify the enrollment/recovery user experience
(NK-WP-0042-T02) or which workloads turn step-up on (ADR-0016 §4).
- This does not add a Keycloak-specific or privacyIDEA-specific
mechanism; `acr_values` is the profile-level, provider-neutral request.