Skip to content

PoC: enforce upstream IdP session_expiry ceiling#117

Open
kishore7snehil wants to merge 3 commits into
mainfrom
poc/session-expiry-enforcement
Open

PoC: enforce upstream IdP session_expiry ceiling#117
kishore7snehil wants to merge 3 commits into
mainfrom
poc/session-expiry-enforcement

Conversation

@kishore7snehil

Copy link
Copy Markdown
Contributor

Adds enforcement of the IPSIE session_expiry claim for enterprise connections.
When the connection is configured to honor an upstream IdP session ceiling, Auth0
includes a session_expiry claim (absolute Unix seconds) in the ID token. The SDK
reads it at login, stores it with the session, and enforces it on every session read.

Changes

Enforcement

  • Reads session_expiry from userinfo / verified ID-token claims at
    complete_interactive_login and stamps it onto the internal session state.
  • get_user() and get_session() return None once the ceiling is reached
    (silent — behaves like no session, so existing redirect-to-login fires).
  • get_access_token() raises AccessTokenError with code session_expired
    (loud — checked before serving cache or refreshing; refresh is never attempted).
  • Reaching the ceiling deletes the stored session before returning.
  • 30s negative leeway for clock skew; integer-seconds comparison.
  • Refresh-token grant preserves the original ceiling (not re-emitted on refresh).

Claims access

  • session_expiry is surfaced on UserClaims, so it can be read via
    get_user() without triggering enforcement.

New / changed types & errors

  • UserClaims.session_expiry: Optional[int]
  • InternalStateData.session_expires_at: Optional[int]
  • AccessTokenErrorCode.SESSION_EXPIRED = "session_expired"

@kishore7snehil kishore7snehil requested a review from a team as a code owner June 4, 2026 15:38
…laim extraction

Add a login-time lockout guard to complete_interactive_login: when the upstream
IdP asserts a session_expiry ceiling already in the past at login (compared
against the ID token iat with the same 30s leeway as read-time enforcement),
raise the new flow-agnostic SessionExpiredError instead of persisting an
already-expired session. A missing claim stays a no-op, preserving existing
behavior.

Generalize extract_session_expiry into extract_epoch_claim(claims, name),
reused for both session_expiry and iat, and rename the ceiling predicates to
is_session_ceiling_reached (read-time) and is_session_ceiling_in_past (login).

Document the login rejection in the README, RetrievingData guide, and the
ipsie-webapp example.
…m boundary

The signature-verified, Auth0-issued ID token has already been validated
upstream (the platform refuses to emit a malformed session_expiry), so the
SDK reads it like every other operational claim instead of running a bespoke
validator. Removes State.extract_epoch_claim and reads session_expiry/iat
with a plain .get() at both extraction sites; the None guards in the ceiling
comparison functions still deliver the absent/null "no ceiling" safe default.

Production-reachable inputs (absent/null, clean integer) are unchanged; only
unreachable malformed values change behavior, now failing closed rather than
being silently accepted.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant