Skip to content

REF-97 Bind the login to the SAML session and enforce a maximum session lifetime - #108

Merged
thomasnymand merged 1 commit into
mainfrom
feature/REF-97-session-binding-and-lifetime
Oct 31, 2026
Merged

thomasnymand merged 1 commit into
mainfrom
feature/REF-97-session-binding-and-lifetime

Conversation

@thomasnymand

Copy link
Copy Markdown
Collaborator

A login now belongs to the OIOSAML session it was made in and has a maximum length, as NemLog-in's technical requirements for service providers ask.

Changes

  • Maximum session length: a login ends MaximumSessionLength minutes after the authentication at the IdP (new Federation element, default 480), or at the IdP's SessionNotOnOrAfter if that is earlier, however active the user is. The end is stored with the login (Saml20AssertionLite.ValidUntil) and checked on every read.
  • Expired sessions stay expired: the in-process and SQL Server session stores no longer read or extend a session past its idle timeout, and writing to an expired session starts it afresh. Before, an expired session could be read and revived until the cleanup ran (or forever with DisableCleanup).
  • Saml20Identity.IsInitialized() is true only when the session holds a completed login that has not ended. Before, any value in the session, such as a pending AuthnRequest, made it true.
  • Forms ticket bound to the session: the default SetSamlPrincipal action issues the Forms ticket itself, with a hash of the OIOSAML session id in its UserData and an expiry no later than the login. A ticket presented with a different OIOSAML session doesn't count as logged in, so the documented Global.asax check signs it out. Tickets an application issues itself are left alone.
  • readme.md: new "Session lifetime" section.

Upgrade notes

  • Sessions stored by 3.0.4 have no ValidUntil and keep working until they time out.
  • Logins end after at most 8 hours by default; set <MaximumSessionLength> in the Federation section to change it.
  • IsInitialized() is false between sending the AuthnRequest and receiving the response.
  • The Forms ticket's UserData is now set by the library; an application that needs its own UserData should issue its own ticket in its own login action.

Tests

SessionLifetimeTest (length calculation, expired in-process sessions) and SessionStoreTest (pre-login session, ended login, Forms tickets from this and other sessions).

…ssion length

- A login ends MaximumSessionLength minutes (default 480) after the
  authentication at the IdP, or at the IdP's SessionNotOnOrAfter if earlier,
  whatever the activity; it is checked on every read.
- The in-process and SQL Server session stores neither read nor extend an
  expired session, and writing to one starts it afresh.
- Saml20Identity.IsInitialized() requires a completed login that has not
  ended, not just any value in the session.
- The Forms ticket issued at login carries a hash of the OIOSAML session id and
  ends no later than the login; presented with another session it doesn't
  count as logged in.
@thomasnymand
thomasnymand merged commit f0ed8cc into main Oct 31, 2026
2 checks passed
@thomasnymand
thomasnymand deleted the feature/REF-97-session-binding-and-lifetime branch October 31, 2026 14:30
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