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.



172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/workos/session_manager.rb', line 172

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

#fetch_jwks(now: Time.now) ⇒ Object

Cached JWKS fetch (5-minute TTL, thread-safe).



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

def fetch_jwks(now: Time.now)
  @jwks_mutex.synchronize do
    return @jwks_cache if @jwks_cache && @jwks_cache_at && (now - @jwks_cache_at) < 300
    response = @client.user_management.get_jwks(client_id: @client.client_id)
    @jwks_cache = {"keys" => response.keys.map(&:to_h)}
    @jwks_cache_at = now
    @jwks_cache
  end
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
# File 'lib/workos/session_manager.rb', line 152

def seal_data(data, 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.



163
164
165
166
167
168
# File 'lib/workos/session_manager.rb', line 163

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
  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).



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

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