Skip to main content
Sessions in the Maverics Orchestrator give every authenticated user a persistent, secure identity context — their authentication state, tokens, and attributes travel with them across requests and applications without re-authenticating. Once a user logs in, the Orchestrator maintains their session server-side, making identity data available across many Orchestrator modes for as long as the session is valid. This page covers how sessions work, how to configure session lifetime and security, and how to set up store-agnostic features like dynamic expiration.
Production support status:
  • Local sessions — Supported for production. Sessions are stored in-memory on each Orchestrator instance with LRU eviction. For single-node deployments, no additional configuration is needed. For multi-node deployments, configure sticky sessions (session affinity) on your load balancer. See Local Sessions for details.
  • Cluster sessions — Experimental. Requires the experimental.clusters feature flag. Cluster sessions allow sessions to be shared across Orchestrator instances. When combined with cluster routing, this removes the need for load balancer affinity. Not yet supported for production workloads. This feature may be changed or removed without notice.
Console terminology: In the Maverics Console, Orchestrator instances and configuration delivery are managed through Deployments. When working directly with YAML, configuration is managed as files delivered via the -config flag or MAVERICS_CONFIG environment variable.

How Sessions Work

The Orchestrator maintains server-side session state for each authenticated user. When a user authenticates, the Orchestrator creates a session containing their authentication state, tokens, and user attributes, then returns an opaque session cookie to the browser. On subsequent requests, the cookie identifies the session — all sensitive data stays server-side, never in the cookie itself.

Sessions and the Authentication Lifecycle

Sessions are created as part of the authentication flow and directly affect how users experience subsequent requests across all Orchestrator modes.

When Sessions Are Created

A session is created after successful authentication in any Orchestrator mode. The Orchestrator stores the user’s authentication state (which IdP authenticated them, when the authentication occurred), tokens received from upstream providers, and enriched attributes loaded from attribute providers. This all happens server-side — only an opaque session cookie is sent to the client.

How Sessions Affect Subsequent Requests

On subsequent requests, the Orchestrator checks for a valid session cookie. If a valid, non-expired session exists, the user is not redirected to the IdP again — the Orchestrator uses the stored session data to fulfill the request (inject headers, issue tokens, serve LDAP entries). This is why session lifetime and idle timeout directly affect how often users must re-authenticate.

Per-Mode Session Behavior

Each Orchestrator mode interacts with sessions differently:
  • HTTP Proxy — The session cookie is set on the proxy domain. Every proxied request checks the session. If the session is expired, the user is redirected to the IdP for re-authentication.
  • OIDC Provider — The session manages authorization server state. Token refresh can extend the effective session without requiring user interaction, as long as the session itself has not expired.
  • SAML Provider — The session manages IdP state. New SAML AuthnRequests check the existing session before redirecting to the upstream IdP. If a valid session exists, the Orchestrator can issue a SAML assertion without re-authenticating the user.
  • LDAP Provider — Sessions are per-connection bind state, not cookie-based. Each LDAP connection maintains its own authenticated context that lasts for the duration of the connection.
  • AI Identity Gateway — Sessions are token-based (OAuth), not cookie-based. Token expiry drives re-authentication rather than session cookie expiry.

Session Expiration and Re-Authentication

When a session expires (either maximum lifetime reached or idle timeout exceeded), the next request triggers re-authentication. The user is redirected to the upstream IdP. If the IdP has its own active session (SSO), re-authentication may be transparent to the user — they are redirected to the IdP and back without seeing a login prompt. If the IdP session has also expired, the user sees a login prompt. For a complete overview of how authentication flows across all Orchestrator modes, see How Authentication Works.

Session Security

Maverics sessions are designed for zero-trust environments:
  • 256-bit session IDs — Generated using cryptographically secure random number generators (CSPRNG), providing 2256 possible session IDs. Exceeds OWASP’s minimum 64-bit entropy requirement with zero predictability between sessions.
  • Secure cookies by defaultHttpOnly (no JavaScript access), Secure (HTTPS only), and SameSite=None (cross-site auth flows) are all enabled by default. These protect against session hijacking, XSS, and CSRF attacks.
  • Server-side storage — The session cookie is an opaque identifier only. User attributes, authentication state, and metadata are stored on the server, not in the cookie.
  • Automatic expiration — Sessions expire based on configurable maximum lifetime and idle timeout. Expired sessions are automatically purged from storage.
Session cookies should be treated as secrets. If a malicious actor obtains a session cookie, they could impersonate the authenticated user for the duration of the session.

Session Lifetime

Sessions support both maximum lifetime and idle timeout controls:
  • Maximum lifetime — The total time a session can exist after authentication, regardless of activity. Default: 12 hours.
  • Idle timeout — Time a session can remain inactive before expiring. Disabled by default.
  • Dynamic expiration — Service Extensions can evaluate session lifetime and idle timeout dynamically, enabling role-based or context-aware timeout policies (e.g., shorter timeouts for contractors, longer for employees).
  • Single logout — When a session expires or is explicitly terminated, all session data is deleted and the cookie is invalidated. Users must re-authenticate through the full authentication flow.

Dynamic Session Expiration

Service Extensions allow dynamic, context-aware session expiration that applies to all session store types. Instead of static timeout values, you can evaluate session lifetime and idle timeout based on user attributes, roles, or request context.
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
  store:
    type: local
    local:
      capacity: 50000
Session expiration SE hooks have unique function signatures compared to other hooks. Instead of the standard (api, rw, req) signature, these hooks receive an additional time.Time parameter — createdAt for EvalMaxLifetime (when the session was created) and lastAccess for EvalIdleTimeout (when the session was last accessed). They also return a bool instead of returning nothing. These differences reflect the hooks’ role in session lifecycle evaluation rather than request processing.

Example: Role-Based Dynamic Expiration

In this example, contractors receive shorter sessions (5 minutes idle, 1 hour max) while full-time employees receive longer sessions (60 minutes idle, 12 hours max). When a session expires, the SE redirects the user to the single logout endpoint.
session.go
package main

import (
	"net/http"
	"time"

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

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

	contractorMaxLifetime = 1 * time.Hour
	contractorIdleTimeout = 5 * time.Minute

	fteMaxLifetime = 12 * time.Hour
	fteIdleTimeout = 60 * time.Minute
)

func EvalMaxLifetime(
	api orchestrator.Orchestrator,
	rw http.ResponseWriter,
	req *http.Request,
	createdAt time.Time,
) bool {
	log := api.Logger()

	employeeType, err := api.Session().GetString("okta.employeeType")
	if err != nil {
		log.Error("se", "failed to get employee type", "error", err.Error())
		return false
	}

	maxLifetime := fteMaxLifetime
	if employeeType == "contractor" {
		maxLifetime = contractorMaxLifetime
	}

	if sessionExpired(createdAt, maxLifetime) {
		log.Info("se", "max lifetime exceeded, redirecting to SLO",
			"employeeType", employeeType,
		)
		http.Redirect(rw, req, sloEndpoint, http.StatusFound)
		return false
	}

	return false
}

func EvalIdleTimeout(
	api orchestrator.Orchestrator,
	rw http.ResponseWriter,
	req *http.Request,
	lastAccess time.Time,
) bool {
	log := api.Logger()

	employeeType, err := api.Session().GetString("okta.employeeType")
	if err != nil {
		log.Error("se", "failed to get employee type", "error", err.Error())
		return false
	}

	idleTimeout := fteIdleTimeout
	if employeeType == "contractor" {
		idleTimeout = contractorIdleTimeout
	}

	if sessionExpired(lastAccess, idleTimeout) {
		log.Info("se", "idle timeout exceeded, redirecting to SLO",
			"employeeType", employeeType,
		)
		http.Redirect(rw, req, sloEndpoint, http.StatusFound)
		return false
	}

	return false
}

func sessionExpired(reference time.Time, timeout time.Duration) bool {
	return time.Now().After(reference.Add(timeout))
}
The bool return value controls whether the Orchestrator continues its default timeout evaluation. Returning true means the session is valid and the Orchestrator should continue processing normally. Returning false means the SE has handled the evaluation — either because the session expired and a redirect was issued, or because the SE has completed its check and is deferring to the Orchestrator’s default timeout behavior. In this example, both branches return false: the expired branch because a redirect was issued, and the non-expired branch because the SE has finished its evaluation.

Single Logout Configuration

The SE example above redirects expired sessions to the singleLogout endpoint. Configure singleLogout at the top level of the Orchestrator configuration (not nested under session):
maverics.yaml
singleLogout:
  logoutURL: https://example.com/single-logout
  postLogout:
    redirectURL: https://example.com/index.html
Set logoutURL to match the sloEndpoint constant in the Go code. After logout completes, the Orchestrator redirects the user to postLogout.redirectURL. You can also add a postLogoutSE Service Extension hook under postLogout to run custom logic after the logout flow completes. Use cases for dynamic expiration include:
  • Role-based timeouts — Contractors receive shorter sessions (e.g., 5 minutes idle, 1 hour max) while employees receive longer ones (e.g., 60 minutes idle, 12 hours max)
  • Risk-based session length — Reduce session lifetime when authentication originates from an unfamiliar device or location
  • Compliance enforcement — Force re-authentication for access to sensitive resources regardless of session state

Setup

Session and cookie settings are configured per deployment under Orchestrator Settings.
1

Open session settings

Navigate to Deployments, select a deployment, and click Edit Session and Cookie in the Session and Cookie section.
2

Configure session lifetime

Set Max Lifetime Seconds to control how long a session remains valid after authentication (default: 86400 seconds / 24 hours). Set Idle Timeout to expire sessions after a period of inactivity (0 disables idle timeout).
3

Configure capacity

Set Cache Size to limit the number of sessions stored in memory (default: 50,000). When this limit is reached, the oldest sessions are evicted.
4

Configure cookie settings

Under the Cookie heading, optionally set a Domain to scope the cookie to a parent domain (e.g., .example.com) and a Name to customize the session cookie name. Use the Disable HttpOnly Attribute and Disable Secure Cookie Attribute toggles only if your deployment specifically requires it — both protections are enabled by default.
5

Optionally attach dynamic expiration Service Extensions

If you have Service Extensions uploaded, select them from the Evaluate Session Maximum Lifetime Service Extension and Evaluate Session Idle Timeout Service Extension dropdowns to enable dynamic, context-aware session expiration.
6

Save

Click Save to apply the settings.
The Console UI does not yet cover all session configuration options. Store type selection and duration-based lifetime values (e.g., 24h, 15m) are only available through configuration. See the Configuration tab for the full set of options.

Configuration Reference

KeyTypeDefaultRequiredDescription
session.cookie.namestring"maverics_session"NoSession cookie name
session.cookie.domainstringNoCookie domain scope (defaults to the request host). Setting this to a parent domain (e.g., .example.com) exposes the session cookie to all subdomains.
session.cookie.disableHTTPOnlybooleanfalseNoAllow client-side script access to the session cookie
session.cookie.disableSecurebooleanfalseNoAllow the session cookie to be sent over unencrypted HTTP
Cookie fields use inverted booleans: disableHTTPOnly and disableSecure rather than httpOnly and secure. The defaults keep both protections enabled. There is no sameSite field.

Session Lifetime

KeyTypeDefaultRequiredDescription
session.lifetime.maxTimeoutstring"12h"NoMaximum session duration (duration format, e.g., "12h", "30m")
session.lifetime.idleTimeoutstringNoIdle timeout before session expires (duration format)
session.lifetime.evalIdleTimeoutSEobjectNoService Extension for dynamic idle timeout evaluation
session.lifetime.evalMaxLifetimeSEobjectNoService Extension for dynamic max lifetime evaluation

Session Store

KeyTypeDefaultRequiredDescription
session.store.typestring"local"NoStore type: "local" for single-node or "cluster" for distributed
Store-specific fields are documented on each detail page: Local Sessions and Cluster Sessions.
Deprecated fields — the following top-level session fields are still accepted but should be migrated to their new locations:
  • session.cacheSize — use session.store.local.capacity
  • session.maxLifetimeSeconds — use session.lifetime.maxTimeout
  • session.idleTimeout — use session.lifetime.idleTimeout
  • session.evalIdleTimeoutSE — use session.lifetime.evalIdleTimeoutSE
  • session.evalMaxLifetimeSE — use session.lifetime.evalMaxLifetimeSE

Store Types

TypeDescriptionUse Case
LocalSingle-node LRU session storeProduction single-node and multi-node deployments with cookie-based sticky sessions (default)
ClusterDistributed session storeMulti-node deployments requiring shared sessions via Orchestrator clustering

Examples

A standard session configuration with a local store, 24-hour maximum lifetime, and 15-minute idle timeout. This is appropriate for most production deployments where users should re-authenticate after a day or after 15 minutes of inactivity.
maverics.yaml
session:
  store:
    type: local
    local:
      capacity: 50000
  lifetime:
    maxTimeout: 24h
    idleTimeout: 15m
  cookie:
    name: maverics_session
For environments subject to PCI DSS, HIPAA, or similar compliance frameworks that require aggressive session timeouts. This configuration enforces a 15-minute idle timeout and a 1-hour maximum lifetime, ensuring users re-authenticate frequently when accessing sensitive resources.
maverics.yaml
session:
  store:
    type: local
    local:
      capacity: 50000
  lifetime:
    maxTimeout: 1h
    idleTimeout: 15m
  cookie:
    name: maverics_session
Use Service Extensions to apply different session timeouts based on user attributes. Contractors receive shorter sessions (5 minutes idle, 1 hour max) while full-time employees receive longer sessions (60 minutes idle, 12 hours max). See Dynamic Session Expiration above for the full Go code example.
maverics.yaml
session:
  lifetime:
    evalMaxLifetimeSE:
      funcName: EvalMaxLifetime
      file: /etc/maverics/extensions/session.go
    evalIdleTimeoutSE:
      funcName: EvalIdleTimeout
      file: /etc/maverics/extensions/session.go
  store:
    type: local
    local:
      capacity: 50000

singleLogout:
  logoutURL: https://example.com/single-logout
  postLogout:
    redirectURL: https://example.com/index.html
When users navigate between applications on different subdomains (e.g., app.example.com and portal.example.com), set the cookie domain to the parent domain so the session cookie is sent to all subdomains. This enables single sign-on across subdomains without requiring each application to initiate its own authentication flow.
maverics.yaml
session:
  store:
    type: local
    local:
      capacity: 50000
  lifetime:
    maxTimeout: 12h
    idleTimeout: 30m
  cookie:
    name: maverics_session
    domain: ".example.com"
Setting the cookie domain to a parent domain makes the session cookie accessible to all subdomains, including staging environments and third-party tools. If any subdomain is compromised, an attacker can hijack user sessions. Only use parent domain scoping when cross-subdomain sharing is explicitly required, and audit all subdomains to ensure they are trusted.

Session Detail Pages