Skip to content

CAEP Interop Profile: consider adding Risk Level Change as a qualifying use case #347

Description

@cprakash-zscaler

Context

CAEP Interoperability Profile 1.0 §3 requires conforming implementations to support at
least one of:

  • §3.1 Session Revocation / Logout (session-revoked)
  • §3.2 Credential Change (credential-change)
  • §3.3 Device Compliance Change (device-compliance-change)

CAEP 1.0 Final §3.8 defines risk-level-change, but the Interop Profile does not list it
as a qualifying use case. The profile is therefore narrower than the specification it
profiles, in a way that excludes a common class of integration.

Motivation

The profile's qualifying use cases do not include the event type that carries the primary
interoperability risk for risk-engine-to-policy-engine integrations. In our deployment
(a Zscaler adaptive-access receiver integrating with Silverfort), risk-level-change is
the highest-volume signal and the one our access decisions are actually driven by.

More generally: an implementation whose product function is built on risk-level-change
has no path to certify on that basis. The only route to conformance is to add handling for
one of the three listed events regardless of whether that event drives any behaviour in the
product. That produces certifications describing an interoperable surface broader than what
implementations meaningfully exercise, while leaving the event they do exercise entirely
untested by the profile. Widening the qualifying set would let certifications track real
capability more closely.

risk-level-change also sits squarely inside the profile's stated scope: "the core use
cases to improve security of authenticated sessions". A change in assessed risk driving a
re-evaluation of an existing session is the canonical CAEP flow.

On interoperability

One might object that widening "at least one of N" weakens the guarantee that two
conforming implementations share a use case. That guarantee does not exist today: with
three optional use cases, a transmitter supporting only device-compliance-change and a
receiver supporting only session-revoked are both conformant and cannot exchange any
signal. "At least one of N" is a floor on implementation effort, not an interoperability
guarantee, and adding a fourth option does not change its character.

What does follow from that framing is that the qualifying set should track the event types
implementations actually build on. risk-level-change is one of them.

Proposed §3.4 Risk Level Change

In order to support notifying and responding to changes in a subject's assessed risk,
implementations MUST support the CAEP event type risk-level-change. Implementations MUST
support the following field values:

  • principal — Receivers MUST interpret all allowable values of this field.
    Transmitters MAY generate any allowable value of this field.
    (REQUIRED by CAEP 1.0 §3.8.1.)
  • current_level — Receivers MUST interpret all allowable values of this field
    (LOW, MEDIUM, HIGH). Transmitters MAY generate any allowable value of this field.
    (REQUIRED by CAEP 1.0 §3.8.1.)
  • previous_level — remains OPTIONAL. Receivers MUST interpret all allowable values of
    this field, and MUST treat its absence as the previous risk level being unknown to the
    Transmitter, per CAEP 1.0 §3.8.1.
  • reason_admin — Transmitters MUST populate this value with a non-empty object.

risk_reason is not proposed as a profile requirement; it remains RECOMMENDED as defined
in CAEP 1.0 §3.8.1.

Notes on the above, for the WG's consideration:

  • previous_level is deliberately left OPTIONAL. CAEP 1.0 §3.8.1 assigns meaning to its
    absence ("the Receiver MUST assume that the previous risk level is unknown to the
    Transmitter"), which is a real state — a first assessment, or a Receiver onboarded
    mid-stream. Requiring it would remove the Transmitter's ability to express that, so the
    profile requirement here is on Receiver handling rather than Transmitter generation.
  • reason_admin is proposed as the mandatory causation field, matching §3.1, §3.2 and §3.3,
    each of which promotes this otherwise-OPTIONAL CAEP §2 claim to a Transmitter MUST. The
    promotion is unconditional in the existing use cases — §3.2 and §3.3 require it even
    though credential-change and device-compliance-change both define their own
    event-specific claims — so applying it to a fourth use case is consistent rather than
    novel. It also keeps a single, uniformly shaped audit field across every profiled event,
    which is worth more to a Receiver's logging pipeline than a per-event variant.
  • risk_reason is deliberately left at RECOMMENDED. It overlaps with reason_admin in
    subject matter, but the two differ in role: reason_admin is a localizable BCP47-keyed
    object intended for logging and auditing, whereas risk_reason is a bare string naming
    the contributing risk factor, with no vocabulary defined in CAEP 1.0. We see no benefit in
    mandating both, and of the two reason_admin is the one with defined structure and an
    established precedent in this profile.

(Otherwise mirrors the structure of §3.3.)

Conformance suite impact

Minimal. In the OpenID conformance suite,
net.openid.conformance.openid.ssf.SsfEvents already defines
CAEP_RISK_LEVEL_CHANGE_EVENT_TYPE and includes it in CAEP_EVENT_TYPES, and
AbstractOIDSSFReceiverTestModule.generateSsfEventExample already produces a conformant
example SET for it (event_timestamp, current_level, previous_level,
initiating_entity, principal, risk_reason). Enabling it under the caep_interop
profile is a matter of adding it to CAEP_INTEROP_EVENT_TYPES and mapping a spec reference.
The existing example carries principal, current_level, previous_level and
risk_reason; if reason_admin is adopted above it would need adding there too, as the
three existing Interop use cases already have.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions