openid / openid/sharedsignals

Add `UNKNOWN` as a valid value for `current_level` / `previous_level` in `risk-level-change`

Open
#330 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Makefile
Stars
78
Forks
18
PR merge metrics
No merged PRs in 30d

Description

Context

The risk-level-change event, introduced in #200, defines current_level as REQUIRED with values restricted to LOW, MEDIUM, or HIGH. There is no way for a Transmitter to communicate "I do not currently have enough signal to assess this subject's risk."

This conflates two distinct states:

  • HIGH: the Transmitter has high confidence the subject is risky (e.g., suspected non-authorized user, compromised credential, malicious software).
  • No assessment available: the Transmitter previously had a risk level but signal has gone stale, the subject is idle, or upstream data sources are unavailable.

Today, Transmitters facing the second case must choose between three bad options:

  1. Emit HIGH (fail-closed). This is semantically incorrect, it overstates the Transmitter's confidence and can drive unwarranted remediations like forced re-auth or session revocation.
  2. Continue reporting the last known level. The Receiver has no way to know the assessment is stale.
  3. Stop emitting events. The Receiver cannot distinguish "signal lost" from "no change."
Proposal

Add UNKNOWN as a permitted value for current_level and previous_level.

  • current_level: UNKNOWN indicates the Transmitter does not currently have sufficient signal to assess the subject's risk.
  • previous_level: UNKNOWN is semantically equivalent to omission (already defined as "unknown to the Transmitter") but allows explicit transitions, e.g., UNKNOWN -> LOW when signal is re-established.
Example Scenarios
  • Continuous behavioral authentication: A Transmitter assessing a user via behavioral biometrics loses signal when the user goes idle or the agent disconnects. Transitioning to UNKNOWN lets Receivers apply their own policy (e.g., step-up on next sensitive action) without the Transmitter falsely asserting risk.
  • Device posture: A device's compliance agent stops checking in. The Transmitter can emit UNKNOWN rather than guess, letting Receivers decide whether absence of signal warrants remediation.
  • Upstream provider outage: A Transmitter ingesting risk from a third-party provider can communicate signal loss without retracting prior assessments or fabricating a level.
Event-Specific Claims (updated)
  1. current_level - REQUIRED. Value MUST be one of LOW, MEDIUM, HIGH, UNKNOWN.
  2. previous_level - OPTIONAL. Value MUST be one of LOW, MEDIUM, HIGH, UNKNOWN. Omission continues to mean the previous level is unknown to the Transmitter.
Example
{
  "events": {
    "https://schemas.openid.net/secevent/caep/event-type/risk-level-change": {
      "subject": { "user": { "format": "iss_sub", "iss": "...", "sub": "..." } },
      "current_level": "UNKNOWN",
      "previous_level": "LOW",
      "risk_reason": "SIGNAL_UNAVAILABLE",
      "event_timestamp": 1615304991
    }
  }
}
Considerations
  • Receivers MUST NOT treat UNKNOWN as ordered relative to LOW/MEDIUM/HIGH; it is an absence-of-assessment state, not a level on the risk scale.
  • Receivers SHOULD apply local policy to decide how to react to UNKNOWN (ignore, step-up, fall back to last known, etc.).

Disclosure / motivation: This proposal comes from operating a continuous behavioral authentication transmitter (Twosense) where signal availability is inherently intermittent (user idle, agent disconnect, device sleep). The UNKNOWN gap is something we hit in production, not a hypothetical.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the linked risk-level-change specification and the change introduced in issue #200, then compare the current claim definitions with this proposal. Done means the specification consistently permits UNKNOWN for current_level and previous_level and documents its non-ordered, absence-of-assessment semantics.

Written by the indexing model from the issue text.

Assessment

Domain
security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.