Class: WorkOS::SessionManager

Inherits:
Object
  • Object
show all
Defined in:
lib/workos/session_manager.rb

Overview

Manages sealed-session lifecycle: loading, authenticating, refreshing, and sealing sessions from authentication responses.

Examples:

Load and authenticate a session

session = client.session_manager.load(
  seal_data: cookies["wos-session"],
  cookie_password: ENV["COOKIE_PASSWORD"]
)
result = session.authenticate

Seal a session from an auth response

sealed = client.session_manager.seal_session_from_auth_response(
  access_token: response.access_token,
  refresh_token: response.refresh_token,
  cookie_password: ENV["COOKIE_PASSWORD"]
)

Defined Under Namespace

Classes: AuthError, AuthSuccess, RefreshError, RefreshSuccess

Constant Summary collapse

JWK_ALGORITHMS =
["RS256"].freeze
"no_session_cookie_provided"
"invalid_session_cookie"
INVALID_JWT =
"invalid_jwt"
INVALID_JWT_ALGORITHM =
"invalid_jwt_algorithm"
INVALID_JWT_SIGNATURE =
"invalid_jwt_signature"
EXPIRED_JWT =
"expired_jwt"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(client, encryptor: nil) ⇒ SessionManager

Returns a new instance of SessionManager.

Parameters:

  • client (WorkOS::Client)
  • encryptor (#seal, #unseal) (defaults to: nil)

    Optional custom encryptor. Defaults to Encryptors::AesGcm. A custom encryptor must respond to seal(data, key) -> String and unseal(sealed_string, key) -> Hash.



124
125
126
127
128
129
130
# File 'lib/workos/session_manager.rb', line 124

def initialize(client, encryptor: nil)
  @client = client
  @encryptor = encryptor || Encryptors::AesGcm.new
  @jwks_cache = nil
  @jwks_cache_at = nil
  @jwks_mutex = Mutex.new
end

Instance Attribute Details

#clientObject (readonly)

Returns the value of attribute client.



132
133
134
# File 'lib/workos/session_manager.rb', line 132

def client
  @client
end

Instance Method Details

#authenticate(seal_data:, cookie_password:, include_expired: false, &claim_extractor) ⇒ Object

H05 — Inline convenience: authenticate without manual Session construction.



140
141
142
# File 'lib/workos/session_manager.rb', line 140

def authenticate(seal_data:, cookie_password:, include_expired: false, &claim_extractor)
  load(seal_data: seal_data, cookie_password: cookie_password).authenticate(include_expired: include_expired, &claim_extractor)
end

#decode_jwt(access_token, verify_expiration: true) ⇒ Object

Verify an access-token JWT against the WorkOS JWKS for this client. Used by Session#authenticate; exposed publicly for advanced cases.

NOTE on iss/aud/required_claims: this method intentionally does not enforce iss, aud, or required_claims. workos-node's jose call and workos-php's isset($exp) && $exp < time() accept exp-less tokens, and cross-SDK parity is required for the planned coordinated hardening of these claims. See commit 9ce069f for the rationale behind dropping the required_claims: ['exp'] tightening that was considered here.



183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/workos/session_manager.rb', line 183

def decode_jwt(access_token, verify_expiration: true)
  jwks = fetch_jwks
  JWT.decode(
    access_token,
    nil,
    true,
    algorithms: JWK_ALGORITHMS,
    jwks: jwks,
    verify_aud: false,
    verify_expiration: verify_expiration
  ).first
end

#load(seal_data:, cookie_password:) ⇒ Object

H04 — Load a Session object from a sealed cookie.



135
136
137
# File 'lib/workos/session_manager.rb', line 135

def load(seal_data:, cookie_password:)
  Session.new(self, seal_data: seal_data, cookie_password: cookie_password)
end

#refresh(seal_data:, cookie_password:, organization_id: nil) ⇒ Object

H05 — Inline convenience: refresh without manual Session construction.



145
146
147
148
# File 'lib/workos/session_manager.rb', line 145

def refresh(seal_data:, cookie_password:, organization_id: nil)
  load(seal_data: seal_data, cookie_password: cookie_password)
    .refresh(organization_id: organization_id)
end

#seal_data(data, key) ⇒ Object

H06 — Raw seal: encrypt arbitrary data with a key string. Delegates to the configured encryptor (default: AES-256-GCM).



152
153
154
155
# File 'lib/workos/session_manager.rb', line 152

def seal_data(data, key)
  validate_cookie_password!(key)
  @encryptor.seal(data, key)
end

#seal_session_from_auth_response(access_token:, refresh_token:, cookie_password:, user: nil, impersonator: nil) ⇒ Object

H07 — Build a sealed session string directly from auth-response fields.



165
166
167
168
169
170
171
172
# File 'lib/workos/session_manager.rb', line 165

def seal_session_from_auth_response(access_token:, refresh_token:, cookie_password:, user: nil, impersonator: nil)
  payload = {"access_token" => access_token, "refresh_token" => refresh_token}
  payload["user"] = user if user
  payload["impersonator"] = impersonator if impersonator
  # Delegates to seal_data, which calls validate_cookie_password!; no need
  # to validate here too.
  seal_data(payload, cookie_password)
end

#unseal_data(sealed, key) ⇒ Object

H06 — Raw unseal: returns parsed JSON (Hash) or raw string if not JSON. Delegates to the configured encryptor (default: AES-256-GCM).



159
160
161
162
# File 'lib/workos/session_manager.rb', line 159

def unseal_data(sealed, key)
  validate_cookie_password!(key)
  @encryptor.unseal(sealed, key)
end