workos 5.28.0 → 5.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/workos/session.rb +38 -32
- data/lib/workos/version.rb +1 -1
- data/spec/lib/workos/session_spec.rb +38 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 65fed812ccb7c97df25793369c07af5024b6cb7e1a12675c125bbdf4f3fd5730
|
|
4
|
+
data.tar.gz: b38903b53ed0bad99605ba619453f7fab5653d67baefa0313b6768a81faf0cd6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3a06ceb94077a433ac395d1f979209df0a3473f201843c09dc622ebbf389817fc05377556a84ce363d5d9eecf69a8dba9182581ff1b78450cff22cdef4aaf520
|
|
7
|
+
data.tar.gz: 7a746ec3b9930327ad6961da2132be517735f204cc548c4c8c8a36f88db1b85d177daf6225ee947cb90a6b27cc6a0121ba37dd1fea4976f28ad84d11cda84f16
|
data/Gemfile.lock
CHANGED
data/lib/workos/session.rb
CHANGED
|
@@ -29,9 +29,10 @@ module WorkOS
|
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
# Authenticates the user based on the session data
|
|
32
|
+
# @param include_expired [Boolean] If true, returns decoded token data even when expired (default: false)
|
|
32
33
|
# @return [Hash] A hash containing the authentication response and a reason if the authentication failed
|
|
33
|
-
# rubocop:disable Metrics/AbcSize
|
|
34
|
-
def authenticate
|
|
34
|
+
# rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity
|
|
35
|
+
def authenticate(include_expired: false)
|
|
35
36
|
return { authenticated: false, reason: 'NO_SESSION_COOKIE_PROVIDED' } if @session_data.nil?
|
|
36
37
|
|
|
37
38
|
begin
|
|
@@ -41,23 +42,41 @@ module WorkOS
|
|
|
41
42
|
end
|
|
42
43
|
|
|
43
44
|
return { authenticated: false, reason: 'INVALID_SESSION_COOKIE' } unless session[:access_token]
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
45
|
+
|
|
46
|
+
begin
|
|
47
|
+
decoded = JWT.decode(
|
|
48
|
+
session[:access_token],
|
|
49
|
+
nil,
|
|
50
|
+
true,
|
|
51
|
+
algorithms: @jwks_algorithms,
|
|
52
|
+
jwks: @jwks,
|
|
53
|
+
verify_expiration: false,
|
|
54
|
+
).first
|
|
55
|
+
|
|
56
|
+
expired = decoded['exp'] && decoded['exp'] < Time.now.to_i
|
|
57
|
+
|
|
58
|
+
# Early return for expired tokens when not including expired data (backward compatible)
|
|
59
|
+
return { authenticated: false, reason: 'INVALID_JWT' } if expired && !include_expired
|
|
60
|
+
|
|
61
|
+
# Return full data for valid tokens or when include_expired is true
|
|
62
|
+
{
|
|
63
|
+
authenticated: !expired,
|
|
64
|
+
session_id: decoded['sid'],
|
|
65
|
+
organization_id: decoded['org_id'],
|
|
66
|
+
role: decoded['role'],
|
|
67
|
+
roles: decoded['roles'],
|
|
68
|
+
permissions: decoded['permissions'],
|
|
69
|
+
entitlements: decoded['entitlements'],
|
|
70
|
+
feature_flags: decoded['feature_flags'],
|
|
71
|
+
user: session[:user],
|
|
72
|
+
impersonator: session[:impersonator],
|
|
73
|
+
reason: expired ? 'INVALID_JWT' : nil,
|
|
74
|
+
}
|
|
75
|
+
rescue JWT::DecodeError
|
|
76
|
+
{ authenticated: false, reason: 'INVALID_JWT' }
|
|
77
|
+
rescue StandardError => e
|
|
78
|
+
{ authenticated: false, reason: e.message }
|
|
79
|
+
end
|
|
61
80
|
end
|
|
62
81
|
|
|
63
82
|
# Refreshes the session data using the refresh token stored in the session data
|
|
@@ -66,7 +85,6 @@ module WorkOS
|
|
|
66
85
|
# @option options [String] :organization_id The organization ID to use for refreshing the session
|
|
67
86
|
# @return [Hash] A hash containing a new sealed session, the authentication response,
|
|
68
87
|
# and a reason if the refresh failed
|
|
69
|
-
# rubocop:disable Metrics/PerceivedComplexity
|
|
70
88
|
def refresh(options = nil)
|
|
71
89
|
cookie_password = options.nil? || options[:cookie_password].nil? ? @cookie_password : options[:cookie_password]
|
|
72
90
|
|
|
@@ -168,17 +186,5 @@ module WorkOS
|
|
|
168
186
|
|
|
169
187
|
jwks
|
|
170
188
|
end
|
|
171
|
-
|
|
172
|
-
# Validates a JWT token using the JWKS set
|
|
173
|
-
# @param token [String] The JWT token to validate
|
|
174
|
-
# @return [Boolean] True if the token is valid, false otherwise
|
|
175
|
-
# rubocop:disable Naming/PredicateName
|
|
176
|
-
def is_valid_jwt(token)
|
|
177
|
-
JWT.decode(token, nil, true, algorithms: @jwks_algorithms, jwks: @jwks)
|
|
178
|
-
true
|
|
179
|
-
rescue StandardError
|
|
180
|
-
false
|
|
181
|
-
end
|
|
182
|
-
# rubocop:enable Naming/PredicateName
|
|
183
189
|
end
|
|
184
190
|
end
|
data/lib/workos/version.rb
CHANGED
|
@@ -160,6 +160,44 @@ describe WorkOS::Session do
|
|
|
160
160
|
expect(result).to eq({ authenticated: false, reason: 'INVALID_JWT' })
|
|
161
161
|
end
|
|
162
162
|
|
|
163
|
+
it 'returns INVALID_JWT without token data when session is expired' do
|
|
164
|
+
session = WorkOS::Session.new(
|
|
165
|
+
user_management: user_management,
|
|
166
|
+
client_id: client_id,
|
|
167
|
+
session_data: session_data,
|
|
168
|
+
cookie_password: cookie_password,
|
|
169
|
+
)
|
|
170
|
+
allow_any_instance_of(JWT::Decode).to receive(:verify_signature).and_return(true)
|
|
171
|
+
allow(Time).to receive(:now).and_return(Time.at(9_999_999_999))
|
|
172
|
+
result = session.authenticate
|
|
173
|
+
expect(result).to eq({ authenticated: false, reason: 'INVALID_JWT' })
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
it 'returns INVALID_JWT with full token data when session is expired and include_expired is true' do
|
|
177
|
+
session = WorkOS::Session.new(
|
|
178
|
+
user_management: user_management,
|
|
179
|
+
client_id: client_id,
|
|
180
|
+
session_data: session_data,
|
|
181
|
+
cookie_password: cookie_password,
|
|
182
|
+
)
|
|
183
|
+
allow_any_instance_of(JWT::Decode).to receive(:verify_signature).and_return(true)
|
|
184
|
+
allow(Time).to receive(:now).and_return(Time.at(9_999_999_999))
|
|
185
|
+
result = session.authenticate(include_expired: true)
|
|
186
|
+
expect(result).to eq({
|
|
187
|
+
authenticated: false,
|
|
188
|
+
session_id: 'session_id',
|
|
189
|
+
organization_id: 'org_id',
|
|
190
|
+
role: 'role',
|
|
191
|
+
roles: ['role'],
|
|
192
|
+
permissions: ['read'],
|
|
193
|
+
feature_flags: nil,
|
|
194
|
+
entitlements: nil,
|
|
195
|
+
user: 'user',
|
|
196
|
+
impersonator: 'impersonator',
|
|
197
|
+
reason: 'INVALID_JWT',
|
|
198
|
+
})
|
|
199
|
+
end
|
|
200
|
+
|
|
163
201
|
it 'authenticates successfully with valid session_data' do
|
|
164
202
|
session = WorkOS::Session.new(
|
|
165
203
|
user_management: user_management,
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: workos
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 5.
|
|
4
|
+
version: 5.29.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- WorkOS
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-11-
|
|
11
|
+
date: 2025-11-21 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: encryptor
|