Class: WorkOS::Session
- Inherits:
-
Object
- Object
- WorkOS::Session
- Defined in:
- lib/workos/session.rb
Overview
The Session class provides helper methods for working with WorkOS sessions This class is not meant to be instantiated in a user space, and is instantiated internally but exposed.
Instance Attribute Summary collapse
-
#client_id ⇒ Object
Returns the value of attribute client_id.
-
#cookie_password ⇒ Object
Returns the value of attribute cookie_password.
-
#jwks ⇒ Object
Returns the value of attribute jwks.
-
#jwks_algorithms ⇒ Object
Returns the value of attribute jwks_algorithms.
-
#session_data ⇒ Object
Returns the value of attribute session_data.
-
#user_management ⇒ Object
Returns the value of attribute user_management.
Class Method Summary collapse
-
.seal_data(data, key) ⇒ String
Encrypts and seals data using AES-256-GCM.
-
.unseal_data(sealed_data, key) ⇒ Hash
Decrypts and unseals data using AES-256-GCM.
Instance Method Summary collapse
-
#authenticate ⇒ Hash
Authenticates the user based on the session data.
-
#get_logout_url(return_to: nil) ⇒ String
Returns a URL to redirect the user to for logging out.
-
#initialize(user_management:, client_id:, session_data:, cookie_password:) ⇒ Session
constructor
A new instance of Session.
-
#refresh(options = nil) ⇒ Hash
Refreshes the session data using the refresh token stored in the session data and a reason if the refresh failed rubocop:disable Metrics/AbcSize rubocop:disable Metrics/CyclomaticComplexity rubocop:disable Metrics/PerceivedComplexity.
Constructor Details
#initialize(user_management:, client_id:, session_data:, cookie_password:) ⇒ Session
Returns a new instance of Session.
17 18 19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/workos/session.rb', line 17 def initialize(user_management:, client_id:, session_data:, cookie_password:) raise ArgumentError, 'cookiePassword is required' if .nil? || .empty? @user_management = user_management @cookie_password = @session_data = session_data @client_id = client_id @jwks = Cache.fetch("jwks_#{client_id}", expires_in: 5 * 60) do create_remote_jwk_set(URI(@user_management.get_jwks_url(client_id))) end @jwks_algorithms = @jwks.map { |key| key[:alg] }.compact.uniq end |
Instance Attribute Details
#client_id ⇒ Object
Returns the value of attribute client_id.
15 16 17 |
# File 'lib/workos/session.rb', line 15 def client_id @client_id end |
#cookie_password ⇒ Object
Returns the value of attribute cookie_password.
15 16 17 |
# File 'lib/workos/session.rb', line 15 def @cookie_password end |
#jwks ⇒ Object
Returns the value of attribute jwks.
15 16 17 |
# File 'lib/workos/session.rb', line 15 def jwks @jwks end |
#jwks_algorithms ⇒ Object
Returns the value of attribute jwks_algorithms.
15 16 17 |
# File 'lib/workos/session.rb', line 15 def jwks_algorithms @jwks_algorithms end |
#session_data ⇒ Object
Returns the value of attribute session_data.
15 16 17 |
# File 'lib/workos/session.rb', line 15 def session_data @session_data end |
#user_management ⇒ Object
Returns the value of attribute user_management.
15 16 17 |
# File 'lib/workos/session.rb', line 15 def user_management @user_management end |
Class Method Details
.seal_data(data, key) ⇒ String
Encrypts and seals data using AES-256-GCM
122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/workos/session.rb', line 122 def self.seal_data(data, key) iv = SecureRandom.random_bytes(12) encrypted_data = Encryptor.encrypt( value: JSON.generate(data), key: key, iv: iv, algorithm: 'aes-256-gcm', ) Base64.encode64(iv + encrypted_data) # Combine IV with encrypted data and encode as base64 end |
.unseal_data(sealed_data, key) ⇒ Hash
Decrypts and unseals data using AES-256-GCM
138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/workos/session.rb', line 138 def self.unseal_data(sealed_data, key) decoded_data = Base64.decode64(sealed_data) iv = decoded_data[0..11] # Extract the IV (first 12 bytes) encrypted_data = decoded_data[12..-1] # Extract the encrypted data decrypted_data = Encryptor.decrypt( value: encrypted_data, key: key, iv: iv, algorithm: 'aes-256-gcm', ) JSON.parse(decrypted_data, symbolize_names: true) # Parse the decrypted JSON string back to original data end |
Instance Method Details
#authenticate ⇒ Hash
Authenticates the user based on the session data
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/workos/session.rb', line 33 def authenticate return { authenticated: false, reason: 'NO_SESSION_COOKIE_PROVIDED' } if @session_data.nil? begin session = Session.unseal_data(@session_data, @cookie_password) rescue StandardError return { authenticated: false, reason: 'INVALID_SESSION_COOKIE' } end return { authenticated: false, reason: 'INVALID_SESSION_COOKIE' } unless session[:access_token] return { authenticated: false, reason: 'INVALID_JWT' } unless is_valid_jwt(session[:access_token]) decoded = JWT.decode(session[:access_token], nil, true, algorithms: @jwks_algorithms, jwks: @jwks).first { authenticated: true, session_id: decoded['sid'], organization_id: decoded['org_id'], role: decoded['role'], permissions: decoded['permissions'], entitlements: decoded['entitlements'], user: session[:user], impersonator: session[:impersonator], reason: nil, } end |
#get_logout_url(return_to: nil) ⇒ String
Returns a URL to redirect the user to for logging out
108 109 110 111 112 113 114 115 116 |
# File 'lib/workos/session.rb', line 108 def get_logout_url(return_to: nil) auth_response = authenticate unless auth_response[:authenticated] raise "Failed to extract session ID for logout URL: #{auth_response[:reason]}" end @user_management.get_logout_url(session_id: auth_response[:session_id], return_to: return_to) end |
#refresh(options = nil) ⇒ Hash
Refreshes the session data using the refresh token stored in the session data and a reason if the refresh failed rubocop:disable Metrics/AbcSize rubocop:disable Metrics/CyclomaticComplexity rubocop:disable Metrics/PerceivedComplexity
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/workos/session.rb', line 69 def refresh( = nil) = .nil? || [:cookie_password].nil? ? @cookie_password : [:cookie_password] begin session = Session.unseal_data(@session_data, ) rescue StandardError return { authenticated: false, reason: 'INVALID_SESSION_COOKIE' } end return { authenticated: false, reason: 'INVALID_SESSION_COOKIE' } unless session[:refresh_token] && session[:user] begin auth_response = @user_management.authenticate_with_refresh_token( client_id: @client_id, refresh_token: session[:refresh_token], organization_id: .nil? || [:organization_id].nil? ? nil : [:organization_id], session: { seal_session: true, cookie_password: }, ) @session_data = auth_response.sealed_session @cookie_password = { authenticated: true, sealed_session: auth_response.sealed_session, session: auth_response, reason: nil, } rescue StandardError => e { authenticated: false, reason: e. } end end |