Sealed session-cookie management for AuthKit.
A sealed session is an encrypted (AES-256-GCM) cookie value holding the access token, refresh token, and user returned by an authentication flow.
session = WorkOS.Session.new(client, sealed_cookie, cookie_password)
result = WorkOS.Session.authenticate(session)
result.authenticated
#=> true
{:ok, refreshed} = WorkOS.Session.refresh(session)
refreshed.sealed_sessionConvenience entry points that skip building the struct:
authenticate/2— one-shot authentication from a sealed valuerefresh_session/4— one-shot refresh from a sealed valueseal_session_from_auth_response/2— seal anWorkOS.AuthenticateResponseseal_data/2/unseal_data/2— raw seal/unseal for arbitrary data
The cookie password should be a hex-encoded 32-byte key (64 hex characters); any other non-empty value is hashed with SHA-256 to derive the key.
Summary
Types
Result of authenticate/1. When authenticated is false, reason is one
of "no_session_cookie_provided", "invalid_session_cookie",
"invalid_jwt", or "session_expired". needs_refresh is true when the
cookie was valid but the access token has expired — refresh the session
before treating the user as unauthenticated.
Failed result of refresh/2. reason is one of
"no_session_cookie_provided", "invalid_session_cookie",
"no_refresh_token", "refresh_token_revoked", or "refresh_failed";
error carries the underlying API error when the refresh call itself failed.
Successful result of refresh/2.
Session payload carried inside the sealed cookie.
Functions
Validates the sealed session: unseals the cookie, checks the access token,
and extracts its JWT claims. See auth_result/0.
One-shot session authentication from a sealed value and cookie password. No client is required.
Builds the logout URL for the session.
Builds a session helper from a sealed cookie value.
Refreshes the session using its refresh token and reseals it.
One-shot session refresh from a sealed value and cookie password.
Seals any JSON-serializable term with AES-256-GCM under the given password.
Returns a base64-encoded string (nonce || ciphertext || tag).
Seals a session_data/0 map into a cookie value.
Seals session data (or any auth artifact) from a WorkOS.AuthenticateResponse,
producing a sealed cookie value directly from a successful auth exchange.
Unseals a value produced by seal_data/2 back into the original term.
Types
@type auth_result() :: %{ authenticated: boolean(), session_id: String.t() | nil, organization_id: String.t() | nil, role: String.t() | nil, permissions: [String.t()] | nil, entitlements: [String.t()] | nil, user: WorkOS.User.t() | map() | nil, impersonator: WorkOS.AuthenticateResponseImpersonator.t() | map() | nil, needs_refresh: boolean(), reason: String.t() | nil }
Result of authenticate/1. When authenticated is false, reason is one
of "no_session_cookie_provided", "invalid_session_cookie",
"invalid_jwt", or "session_expired". needs_refresh is true when the
cookie was valid but the access token has expired — refresh the session
before treating the user as unauthenticated.
@type refresh_error() :: %{ authenticated: false, reason: String.t(), error: WorkOS.Error.error() | nil }
Failed result of refresh/2. reason is one of
"no_session_cookie_provided", "invalid_session_cookie",
"no_refresh_token", "refresh_token_revoked", or "refresh_failed";
error carries the underlying API error when the refresh call itself failed.
@type refresh_result() :: %{ authenticated: true, sealed_session: String.t(), session: session_data() }
Successful result of refresh/2.
@type session_data() :: %{ access_token: String.t() | nil, refresh_token: String.t() | nil, user: WorkOS.User.t() | map() | nil, impersonator: WorkOS.AuthenticateResponseImpersonator.t() | map() | nil }
Session payload carried inside the sealed cookie.
@type t() :: %WorkOS.Session{ client: WorkOS.Client.t() | nil, cookie_password: String.t(), sealed_session: String.t() | nil }
Functions
@spec authenticate(t()) :: auth_result()
Validates the sealed session: unseals the cookie, checks the access token,
and extracts its JWT claims. See auth_result/0.
authenticate/2 is the one-shot variant taking the sealed value and cookie
password directly.
@spec authenticate(String.t() | nil, String.t()) :: auth_result()
One-shot session authentication from a sealed value and cookie password. No client is required.
Builds the logout URL for the session.
The session ID is read from the access token's claims — an expired access token still yields a usable logout URL. Options:
:return_to— URL to redirect to after logout
@spec new(WorkOS.Client.t() | nil, String.t() | nil, String.t()) :: t()
Builds a session helper from a sealed cookie value.
client may be nil for authenticate-only usage; refresh/2 requires it.
@spec refresh( t(), keyword() ) :: {:ok, refresh_result()} | {:error, refresh_error()}
Refreshes the session using its refresh token and reseals it.
Returns {:ok, refresh_result} with the new sealed session, or
{:error, refresh_error} — see refresh_error/0 for the reasons.
@spec refresh_session(WorkOS.Client.t(), String.t() | nil, String.t(), keyword()) :: {:ok, refresh_result()} | {:error, refresh_error()}
One-shot session refresh from a sealed value and cookie password.
Seals any JSON-serializable term with AES-256-GCM under the given password.
Returns a base64-encoded string (nonce || ciphertext || tag).
@spec seal_session(session_data(), String.t()) :: {:ok, String.t()} | {:error, term()}
Seals a session_data/0 map into a cookie value.
@spec seal_session_from_auth_response(WorkOS.AuthenticateResponse.t(), String.t()) :: {:ok, String.t()} | {:error, term()}
Seals session data (or any auth artifact) from a WorkOS.AuthenticateResponse,
producing a sealed cookie value directly from a successful auth exchange.
Unseals a value produced by seal_data/2 back into the original term.