Sessions and user state

The Session Management system provides enterprise-grade session security for mission-critical applications. Maverics sessions are comprehensive containers that hold the complete user context needed for identity orchestration.

A Maverics session encompasses the user’s authentication state, attributes retrieved from multiple identity sources (like Active Directory, databases, or APIs), and any metadata associated with the user’s journey through your applications. Think of it as a secure, ephemeral server-side profile that aggregates everything needed to make intelligent access decisions across your entire infrastructure.

This comprehensive approach enables identity orchestration across hybrid and cloud environments. Organizations can extend cloud identity services like Azure AD to protect legacy on-premises applications, gradually migrate users from outdated identity systems to modern platforms, and create seamless single sign-on experiences that span completely different technologies. Sessions bridge the gap between disparate identity systems while maintaining both security and user experience.

Security Features

Cryptographically Secure Session Identifiers

Session identifiers are generated using a cryptographically secure random number generator (CSPRNG) with 256-bit entropy. This provides:

  • 2256 possible session IDs - making brute force attacks computationally infeasible
  • Exceeds OWASP recommendations - OWASP requires minimum 64-bit entropy; Maverics has 256-bit entropy
  • Zero predictability - each session ID is completely independent and unpredictable

Session Cookie Security

By default, all session cookies are configured with maximum security settings:

  • Session Cookies Only - Cookies are automatically deleted when the browser closes (MaxAge = 0)
  • HTTPS Only (Secure flag) - Cookies are only transmitted over encrypted connections
  • HttpOnly Protection - Prevents client-side JavaScript access to session cookies
  • SameSite=None - Enables secure cross-site authentication flows while maintaining protection

These settings help protect against:

  • Session hijacking via network interception
  • Cross-site scripting (XSS) attacks
  • Cross-site request forgery (CSRF) attacks
  • Session fixation attacks

Default Session Lifetime

Sessions are configured with secure default timeouts:

  • Maximum Session Lifetime: 24 hours
  • Idle Timeout: Disabled by default (can be configured)
  • Automatic Cleanup: Expired sessions are automatically purged from the backing storage service

This balances security with user experience, ensuring sessions don’t persist indefinitely while minimizing authentication friction for legitimate users.

Session Termination

The Orchestrator can explicitly terminate user sessions to ensure immediate security enforcement and compliance requirements.

Immediate Effects

  • All session data is deleted - User attributes, authentication state, and metadata are removed from the session store
  • Session cookie is invalidated - The user’s browser receives an expired cookie that will be automatically discarded
  • User access is revoked - Any subsequent requests using the terminated session will be denied and end-users will send users back through the authentication and authorizations flows.

Common Termination Scenarios

Session termination occurs automatically in several situations:

  • User logout - When users explicitly sign out through your application
  • Timeout expiration - Sessions that exceed maximum lifetime or idle timeout limits

Security Benefits

Explicit session termination provides immediate security enforcement:

  • Rapid response to security incidents - Compromised accounts can be immediately secured
  • Compliance requirements - Meet regulatory standards requiring immediate access revocation
  • Zero-trust enforcement - Ensure users must re-authenticate after privilege changes
  • Clean session state - Prevents stale authentication data from affecting future access decisions

Session Cookie

The Orchestrator uses a non-persistent session cookie to maintain an end-user’s state. The lifetime of the cookie is determined by the configured maximum lifetime and idle timeout values.

The session cookie is an opaque cookie that contains only a session identifier. The session identifier is generated using a cryptographically secure random number generator with 256-bit entropy. All other session state is maintained on the Orchestrator server rather than being stored in the cookie itself.

⚠️
A session cookie should be treated like a secret and not shared. If a malicious actor obtains a session cookie, they could potentially impersonate the authenticated user.

Key characteristics of the Maverics session cookie:

  • Opaque identifier only - No sensitive data stored in the cookie
  • Server-side state management - All user attributes and session data stored securely on the server
  • Cryptographically secure generation - 256-bit entropy ensures unpredictable session identifiers
  • Configurable cookie attributes - Security settings can be customized while maintaining best practices

Configuration options

session declares the set of configuration options for session management.

Cookie

cookie is an optional field used to define settings for the HTTP cookie that is used to tie a user back to their session.

Domain

domain is an optional field that specifies the hosts to which the session cookie will be sent. This should normally be set only when proxying to multiple apps on the same domain. If not set, the cookie domain attribute will be set to the hostname requested by the client.

For example, if domain is set to example.com, the user agent will include the cookie in the Cookie header when making HTTP requests to example.com and all subdomains of *.example.com.

Name

name is an optional field that specifies the name of the session cookie used by the Maverics Orchestrator. The default session cookie name is maverics_session.

Disable HTTP Only

disableHTTPOnly is an optional field that disables the HttpOnly cookie attribute. Defaults to false. If set to true, the session cookie will not have the HttpOnly attribute, allowing the cookie to be accessed via client side scripts.

Disable Secure

disableSecure is an optional field that disables the Secure cookie attribute. Defaults to false. If set to true, the session cookie will not have the Secure attribute, allowing the browser to send the cookie over an unencrypted HTTP request.

Lifetime

lifetime is an optional field that defines the session lifetime.

Max Timeout

maxTimeout is an optional field that represents the maximum amount of time that can elapse post-authentication before a session’s authentication state becomes invalidated. If no value is specified, a default of 24 hours will be used.

Idle Timeout

idleTimeout is an optional field that represents the amount of time a session may remain idle before timing out. If no value is set, or the idle timeout is set to 0, then the session idle timeout is disabled.

Eval Session Max Lifetime

evalMaxLifetimeSE is an optional field to define a Service Extension that determines how sessions reaching their max lifetime are handled. maxLifetimeSeconds is still used for individually expiring attributes.

Eval Session Idle Timeout

evalIdleTimeoutSE is an optional field to define a Service Extension that determines how session idle timeouts are handled. If this Service Extension is defined, then the idleTimeout value is ignored.

Store

store is an optional field that defines the session storage backend.

Type

Specifies the session storage backend. Currently, the only available store is "local". Other stores will be added in the future.

Local

local defines the configuration for the local session store type.

Capacity

capacity is an optional field that limits the number of sessions maintained in memory. When the session cache has reached its maximum capacity, and a new session is requested, the session management removes the least recently used session from the cache to make room for the new one. If capacity is not set, a default value of 50,000 user sessions will be used.

Examples

Base Configuration

This configuration will trigger a session expiration after the user is idle for 30 minutes and after a maximum period of one hour. On session expiration, the user will be required to reauthenticate with the IDPs associated with the defined policy.

ℹ️
It is worth noting that a federated IDP may still hold an active session for the user during re-authentication which may result in the user not being prompted for their credentials. To completely log a user out of all IDPs, follow the single logout example below.
session:
  cookie:
    domain: example.com
    disableHTTPOnly: false
    disableSecure: false
  lifetime:
    maxTimeout: 1hs
    idleTimeout: 30m

Session Expiration via Service Extension

Service extensions allow complete flexibility over the process of controlling a user’s session lifespan. The example below triggers single logout on a session expiry event. The max session timeout and idle session timeout are determined dynamically depending on the user’s employee type (full-time employee vs contractor).

/etc/maverics/maverics.yaml

session:
  cookie:
    domain: example.com
  lifetime:
    evalMaxLifetimeSE:
      funcName: EvalMaxLifetime
      file: /etc/maverics/extensions/session.go
    evalIdleTimeoutSE:
      funcName: EvalIdleTimeout
      file: /etc/maverics/extensions/session.go

singleLogout:
  logoutURL: https://example.com/single-logout
  postLogout:
    redirectURL: https://example.com/index.html

/etc/maverics/extensions/session.go

package main

import (
	"net/http"
	"time"

	"github.com/strata-io/service-extension/orchestrator"
)

const (
	sloEndpoint = "https://example.com/single-logout"

	contractorIdleTimeoutSeconds = 300
	contractorMaxTimeoutSeconds  = 3600

	fteIdleTimeoutSeconds = 3600
	fteMaxTimeoutSeconds  = 43200
)

// EvalMaxLifetime determines whether a session has reached its max lifetime. The
// expiration check is informed by a whether a user is a full-time employee or
// contractor.
func EvalMaxLifetime(
	api orchestrator.Orchestrator,
	rw http.ResponseWriter,
	req *http.Request,
	createdAt time.Time,
) bool {
	logger := api.Logger()

	sess, err := api.Session()
	if err != nil {
		logger.Error(
			"se", "failed to retrieve session",
			"err", err,
		)
		return false
	}

	employeeType, err := sess.GetString("okta.employeeType")
	if err != nil {
		logger.Error(
			"se", "failed to retrieve 'employeeType'",
			"err", err,
		)
		return false
	}

	maxTimeout := contractorMaxTimeoutSeconds
	if employeeType == "full_time" {
		maxTimeout = fteMaxTimeoutSeconds
	}

	if sessionExpired(createdAt, maxTimeout) {
		logger.Info(
			"se", "user has reached max session lifetime: redirecting to SLO endpoint")
		http.Redirect(rw, req, sloEndpoint, http.StatusFound)
		// False is returned here so that the SLO endpoint is aware which IDPs to log
		// the user out of. If true is returned, all session attributes including the
		// list of authenticated IDPs will be cleared.
		return false
	}

	return false
}

// EvalIdleTimeout determines whether a session has reached its idle timeout. The
// expiration check is informed by a whether a user is a full-time employee or
// contractor.
func EvalIdleTimeout(
	api orchestrator.Orchestrator,
	rw http.ResponseWriter,
	req *http.Request,
	lastAccess time.Time,
) bool {
	logger := api.Logger()

	sess, err := api.Session()
	if err != nil {
		logger.Error(
			"se", "failed to retrieve session",
			"err", err,
		)
		return false
	}

	employeeType, err := sess.GetString("okta.employeeType")
	if err != nil {
		logger.Error(
			"se", "failed to retrieve 'employeeType'",
			"err", err,
		)
		return false
	}

	idleTimeout := contractorIdleTimeoutSeconds
	if employeeType == "full_time" {
		idleTimeout = fteIdleTimeoutSeconds
	}

	if sessionExpired(lastAccess, idleTimeout) {
		logger.Info("se", "user has reached idle session lifetime: redirecting to SLO endpoint")
		http.Redirect(rw, req, sloEndpoint, http.StatusFound)
		// False is returned here so that the SLO endpoint is aware which IDPs to log
		// the user out of. If true is returned, all session attributes including the
		// list of authenticated IDPs will be cleared.
		return false
	}

	return false
}

func sessionExpired(startPoint time.Time, timeout int) bool {
	return startPoint.Before(time.Now().Add(-time.Duration(timeout) * time.Second))
}