JanssenProject / JanssenProject/jans

feat(jans-fido2): Per-RP assurance policy on RequestedParty (move from global config)

Open
#14,516 2 comments 1 reaction 1 assignee Claimed by @imran-ishaq View on GitHub
comp-jans-fido2 enhancement kind-feature
Dominant language
Java
Stars
648
Forks
174
Avg merge
1d 18h
Merged PRs (30d)
110

Description

**Is your feature request related to a problem? Please describe.**
Right now jans-fido2 makes every passkey/WebAuthn assurance decision globally, in jans fido2/model/src/main/java/io/jans/fido2/model/conf/Fido2Configuration.java (attestationMode, enabledFidoAlgorithms, enterpriseAttestation, hints, metadataServers, ...). A relying party - jans-fido2/model/src/main/java/io/jans/fido2/model/conf/RequestedParty.java - carries only id and origins.

So an operator hosting multiple relying parties on one FIDO2 server cannot apply different security policies per RP. Every RP is forced to share one global configuration. For example, on the same server you can't have:

- RP-A: low-friction consumer passwordless login (defaults), and
- RP-B: a higher-assurance app that must require user verification, enforce attestation, restrict registration to an
allow-list of authenticator models, forbid synced/exportable credentials, and disallow weak account-recovery
paths.

As passkeys move into regulated and high-assurance deployments, this per-RP flexibility is increasingly a hard requirement, and today it's simply not expressible.

**Describe the solution you'd like**
Extend RequestedParty with a per-RP assurance/policy object (or fields) so assurance decisions can be set per relying party instead of only globally:

- requiredUserVerification - require the UV (user-verification) flag for this RP
- attestationMode - monitor/enforced, resolved per RP
- allowedAaguids / blockedAaguids + minCertificationLevel - authenticator allow/deny, checked against the FIDO
metadata service
- allowSyncedPasskeys - device-bound-only vs. synced/multi-device credentials
- allowedTransports - usb / nfc / ble / internal / hybrid (convenience hint)
- recoveryRequirements / fallbackRules - account-recovery assurance, plus the option to let users disable
password login once a passkey is registered
- (optional) an assuranceLevel preset that expands to sensible defaults for the above

Resolution rule (backward compatibility is mandatory): enforcement reads the per-RP policy first, falling back to the existing global Fido2Configuration values when a field is unset. A RequestedParty with no policy MUST behave exactly as it does today - zero regression for existing Casa/Agama flows. The resolved policy is what the attestation/assertion verifiers consult.

Surface the new fields end-to-end:
- Config-API plugin jans-config-api/plugins/fido2-plugin + its swagger jans-config-api/plugins/docs/fido2-
plugin-swagger.yaml
- jans-cli-tui (020_fido plugin)
- Confirm jans-fido2/server-fips/ still builds (model-change parity)

Acceptance: RequestedParty accepts a per-RP policy; when absent, behavior is identical to today; the resolved (per-RP - global fallback) policy is the value the verifiers read.

**Describe alternatives you've considered**
- Keep everything global (status quo) - rejected; can't differentiate relying parties or mix assurance levels on
one deployment.
- Model shape - a single assuranceLevel preset that expands to defaults, vs. individual flags, vs. both (preset +
per-field overrides). Leaning toward both for flexibility; open for discussion.
- Precedence - per-RP field overrides global vs. layers on top of global; proposed field-by-field override with
global as fallback.
- FIDO interception (custom) script - could carry some of this logic, but it isn't first-class, discoverable, or
exposed through Config-API/CLI, and is error-prone to maintain per RP.
- Cedarling authorization policies for "allow only these authenticator classes" - a promising complement for
the AAGUID/authenticator-class decision, but doesn't remove the need to store per-RP policy on
RequestedParty.

**Additional context**
- RequestedParty today carries only id + origins (RequestedParty.java); the assurance knobs live globally on
Fido2Configuration (attestationMode defaults to "monitor").
- Touch points for the change: jans-fido2/model, jans-config-api/plugins/fido2-plugin (+ swagger), jans-cli-tui
020_fido, and server-fips parity.
- This is an enabler: once per-RP policy exists, the enforcement pieces (per-RP UV, attestation mode,
AAGUID/cert policy, synced-passkey allowance, account-recovery/disable-password, non-enumerating
authentication errors, and a conformance test profile) can follow as separate issues referencing this one.
- Motivation: phishing-resistant authentication is increasingly expected by modern security guidance; per-RP
assurance lets a single Jans deployment serve both low-friction consumer logins and high-assurance relying
parties from one FIDO2 server.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.