Skip to content

feat: Support IPSIE session_expiry claim - #245

Merged
tanya732 merged 8 commits into
v2from
feat/add-ipsie-support
Jul 28, 2026
Merged

feat: Support IPSIE session_expiry claim#245
tanya732 merged 8 commits into
v2from
feat/add-ipsie-support

Conversation

@tanya732

@tanya732 tanya732 commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR adds support for the IPSIE SL1 session_expiry ID token claim, which represents an absolute upper bound (Unix timestamp in seconds) on a session's lifetime.

The claim is asserted by the upstream IdP and emitted by Auth0 when the enterprise connection has id_token_session_expiry_supported: true.

Since this library is a stateless core (it does not own or manage application sessions), it provides the primitives required to enforce the session ceiling while leaving session persistence and redirect behavior to the application.

Specifically, this PR:

  • Reads and validates the session_expiry claim during the Authorization Code flow.
  • Stores the validated value on Tokens.
  • Exposes:
    • Tokens.getSessionExpiresAt()
    • Tokens.isSessionExpired()
    • Tokens.isSessionExpired(long leeway)
  • Allows applications to persist the value and check isSessionExpired() whenever a session is read, integrating with their existing redirect-to-login flow.

Changes

Tokens

  • Added an optional sessionExpiresAt field.
  • Added a new 8-argument constructor.
  • Added:
    • getSessionExpiresAt()
    • isSessionExpired()
    • isSessionExpired(long leeway)
  • Introduced a default 30-second clock-skew tolerance via DEFAULT_SESSION_EXPIRY_LEEWAY.
  • serialVersionUID remains unchanged, so previously serialized sessions deserialize with sessionExpiresAt == null, preserving backward compatibility.

RequestProcessor

Reads session_expiry from the verified ID token after token merge and validates it before stamping it onto Tokens.

Validation rules:

  • Non-numeric values are ignored ("no ceiling").
  • Millisecond-scale values (>= 10_000_000_000) are ignored to prevent a Post-Login Action that accidentally emits milliseconds from silently disabling enforcement.
  • If session_expiry <= iat, login fails instead of creating an already-expired session.

IdentityVerificationException

Added:

  • a0.session_expiry_in_past error code
  • isSessionExpiryError() helper

Documentation

Updated EXAMPLES.md with an IPSIE session_expiry section covering:

  • Persisting the value at login
  • Enforcing it on session reads
  • Default leeway behavior

Tests

Added coverage for:

  • RequestProcessorTest
    • Claim is stamped correctly
    • Missing claim
    • Past-iat validation failure
    • Millisecond guard
  • TokensTest

Semantics

  • null means no session ceiling and is never considered expired, making rollout backward compatible.
  • All comparisons use integer Unix seconds.
  • session_expiry is independent of both:
    • the token exp claim
    • application-defined idle or absolute session timeouts

Out of Scope / Follow-up

Refresh token enforcement

This library does not currently expose a refresh-token API, so the session ceiling is enforced only:

  • during login, and
  • when reading an existing session.

A TODO has been added to AuthenticationController documenting the intended behavior once the MRRT renewal flow is implemented:

  1. Reject grant_type=refresh_token requests once the session ceiling has passed, returning session_expired.
  2. Preserve the original login-time session_expiry across refreshes (write once; never re-derive it from refresh responses).

Documentation

Cross-linking from the session management documentation is not included in this PR.

@tanya732
tanya732 marked this pull request as ready for review July 3, 2026 10:35
@tanya732
tanya732 requested a review from a team as a code owner July 3, 2026 10:35
Comment thread src/main/java/com/auth0/Tokens.java
Comment thread src/main/java/com/auth0/Tokens.java Outdated
Comment thread EXAMPLES.md Outdated
Comment thread src/test/java/com/auth0/RequestProcessorTest.java
Comment thread src/main/java/com/auth0/RequestProcessor.java Outdated
Comment thread EXAMPLES.md
Comment thread EXAMPLES.md Outdated
Comment thread src/main/java/com/auth0/RenewAuthRequest.java Outdated
Comment thread src/main/java/com/auth0/RenewAuthRequest.java Outdated
Comment thread src/test/java/com/auth0/RenewAuthRequestTest.java
Comment thread src/main/java/com/auth0/RequestProcessor.java Outdated
return tokens;
}

// Lockout guard: a session that would already be expired on its first read must not be

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This runs six lines and re-explains most of what the code just below already shows (the iat anchor, the wall-clock fallback). The one non-obvious part is why the leeway is applied here, so a ceiling that just clears login isn't bounced on the very first read.

Could we cut it to that one line and let the code carry the rest?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, leeway is applied, hence ceiling that just clears login isn't bounced on the very first read.

Comment thread src/main/java/com/auth0/RequestProcessor.java Outdated
if (sessionExpiresAt <= 0) {
return null;
}
// Range guard: reject milliseconds-since-epoch (or any absurdly large value). A value

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, the three lines partly restate the check. The non-obvious why is the whole point and fits on one line: a milliseconds value reads as a far future date and silently turns enforcement off.

Comment thread src/main/java/com/auth0/RequestProcessor.java Outdated
Comment thread src/main/java/com/auth0/RequestProcessor.java Outdated

@kishore7snehil kishore7snehil left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@tanya732
tanya732 merged commit f873ef2 into v2 Jul 28, 2026
6 checks passed
@tanya732
tanya732 deleted the feat/add-ipsie-support branch July 28, 2026 17:31
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.

2 participants