workos 5.31.1 → 6.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a5e37c10b9ae34685d2545d670ca866dbda73c22df75fc1a2e8d79c159d3a2c7
4
- data.tar.gz: a6f6e36847db549930e7a18ae58e9e95a9c249eb7a93e4466f14109e50e7fddd
3
+ metadata.gz: 6f0ac87a768fc79fa7ffbc77d0bf4a1ba30cbf6c1f5b96f8574c40bd2b61d296
4
+ data.tar.gz: eb05af387d9c1c40e5de4fb830e4ce83e7baf94a2d9bcb428d97032208688780
5
5
  SHA512:
6
- metadata.gz: 37ce63e77ccf9dd05b0d85837c5e1334ae155cd9beb0500d9b3faa3dd985c9638f54f77ff5cd1f350e3d283db23ac16f7a08bd972f308852a6f5eb4c63ebfa79
7
- data.tar.gz: 77b058f1b59efe3a390817173d8a4b45557d41f95385196af8c999e4130ddc83a7a306b68714a7c5c2f7cc695db2e21192599792bce156918bce435a0b2d9b7f
6
+ metadata.gz: 5f82d97362d7063dcc970313794671ca7f8c2c8892ae9728179e3c22a980b1d7e3d238959eb875d4a20629f13c00a56053347a70dfcb2214cf769979fc704151
7
+ data.tar.gz: 5954446fc2d3c6fbad2542c7d377bb7eb8361e514d1d099f01c052085aebc6952277fd15efe7e3cf9683fc2a9dbf4976240098d48e9305607ab3233978b23f21
@@ -67,7 +67,7 @@ jobs:
67
67
  sed -i "s/VERSION = '.*'/VERSION = '${{ steps.bump-version.outputs.new_version }}'/" lib/workos/version.rb
68
68
 
69
69
  - name: Create Pull Request
70
- uses: peter-evans/create-pull-request@v7
70
+ uses: peter-evans/create-pull-request@v8
71
71
  with:
72
72
  token: ${{ steps.generate-token.outputs.token }}
73
73
  commit-message: "v${{ steps.bump-version.outputs.new_version }}"
data/Gemfile.lock CHANGED
@@ -1,9 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- workos (5.31.1)
4
+ workos (6.0.0)
5
5
  encryptor (~> 3.0)
6
- jwt (~> 2.8)
6
+ jwt (~> 3.1)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
@@ -11,7 +11,7 @@ GEM
11
11
  addressable (2.8.6)
12
12
  public_suffix (>= 2.0.2, < 6.0)
13
13
  ast (2.4.2)
14
- base64 (0.2.0)
14
+ base64 (0.3.0)
15
15
  bigdecimal (3.1.7)
16
16
  crack (1.0.0)
17
17
  bigdecimal
@@ -20,7 +20,7 @@ GEM
20
20
  encryptor (3.0.0)
21
21
  hashdiff (1.1.0)
22
22
  json (2.9.1)
23
- jwt (2.10.2)
23
+ jwt (3.1.2)
24
24
  base64
25
25
  language_server-protocol (3.17.0.3)
26
26
  parallel (1.26.3)
@@ -31,13 +31,17 @@ module WorkOS
31
31
  @oauth_tokens = json[:oauth_tokens] ? WorkOS::OAuthTokens.new(json[:oauth_tokens].to_json) : nil
32
32
  @sealed_session =
33
33
  if session && session[:seal_session]
34
- WorkOS::Session.seal_data({
35
- access_token: access_token,
36
- refresh_token: refresh_token,
37
- user: user.to_json,
38
- organization_id: organization_id,
39
- impersonator: impersonator.to_json,
40
- }, session[:cookie_password],)
34
+ WorkOS::Session.seal_data(
35
+ {
36
+ access_token: access_token,
37
+ refresh_token: refresh_token,
38
+ user: user.to_json,
39
+ organization_id: organization_id,
40
+ impersonator: impersonator.to_json,
41
+ },
42
+ session[:cookie_password],
43
+ encryptor: session[:encryptor],
44
+ )
41
45
  end
42
46
  end
43
47
  # rubocop:enable Metrics/AbcSize
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'encryptor'
4
+ require 'securerandom'
5
+ require 'json'
6
+ require 'base64'
7
+
8
+ module WorkOS
9
+ module Encryptors
10
+ # Default encryptor using AES-256-GCM.
11
+ # Implements the encryptor interface: #seal(data, key) and #unseal(sealed_data, key)
12
+ class AesGcm
13
+ # Encrypts and seals data using AES-256-GCM
14
+ # @param data [Hash] The data to seal
15
+ # @param key [String] The encryption key
16
+ # @return [String] Base64-encoded sealed data
17
+ def seal(data, key)
18
+ iv = SecureRandom.random_bytes(12)
19
+
20
+ encrypted_data = Encryptor.encrypt(
21
+ value: JSON.generate(data),
22
+ key: key,
23
+ iv: iv,
24
+ algorithm: 'aes-256-gcm',
25
+ )
26
+ Base64.encode64(iv + encrypted_data)
27
+ end
28
+
29
+ # Decrypts and unseals data using AES-256-GCM
30
+ # @param sealed_data [String] The sealed data to unseal
31
+ # @param key [String] The decryption key
32
+ # @return [Hash] The unsealed data with symbolized keys
33
+ def unseal(sealed_data, key)
34
+ decoded_data = Base64.decode64(sealed_data)
35
+ iv = decoded_data[0..11]
36
+ encrypted_data = decoded_data[12..]
37
+
38
+ decrypted_data = Encryptor.decrypt(
39
+ value: encrypted_data,
40
+ key: key,
41
+ iv: iv,
42
+ algorithm: 'aes-256-gcm',
43
+ )
44
+
45
+ JSON.parse(decrypted_data, symbolize_names: true)
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WorkOS
4
+ # Encryptors module provides pluggable encryption implementations for session data.
5
+ # The default encryptor is AesGcm, which uses AES-256-GCM encryption.
6
+ module Encryptors
7
+ autoload :AesGcm, 'workos/encryptors/aes_gcm'
8
+ end
9
+ end
@@ -22,13 +22,17 @@ module WorkOS
22
22
  end
23
23
  @sealed_session =
24
24
  if session && session[:seal_session]
25
- WorkOS::Session.seal_data({
26
- access_token: access_token,
27
- refresh_token: refresh_token,
28
- user: user.to_json,
29
- organization_id: organization_id,
30
- impersonator: impersonator.to_json,
31
- }, session[:cookie_password],)
25
+ WorkOS::Session.seal_data(
26
+ {
27
+ access_token: access_token,
28
+ refresh_token: refresh_token,
29
+ user: user.to_json,
30
+ organization_id: organization_id,
31
+ impersonator: impersonator.to_json,
32
+ },
33
+ session[:cookie_password],
34
+ encryptor: session[:encryptor],
35
+ )
32
36
  end
33
37
  end
34
38
  # rubocop:enable Metrics/AbcSize
@@ -12,11 +12,14 @@ module WorkOS
12
12
  # The Session class provides helper methods for working with WorkOS sessions
13
13
  # This class is not meant to be instantiated in a user space, and is instantiated internally but exposed.
14
14
  class Session
15
- attr_accessor :jwks, :jwks_algorithms, :user_management, :cookie_password, :session_data, :client_id
15
+ attr_accessor :jwks, :jwks_algorithms, :user_management, :cookie_password, :session_data, :client_id, :encryptor
16
16
 
17
- def initialize(user_management:, client_id:, session_data:, cookie_password:)
17
+ def initialize(user_management:, client_id:, session_data:, cookie_password:, encryptor: nil)
18
18
  raise ArgumentError, 'cookiePassword is required' if cookie_password.nil? || cookie_password.empty?
19
19
 
20
+ @encryptor = encryptor || WorkOS::Encryptors::AesGcm.new
21
+ validate_encryptor!(@encryptor)
22
+
20
23
  @user_management = user_management
21
24
  @cookie_password = cookie_password
22
25
  @session_data = session_data
@@ -30,13 +33,14 @@ module WorkOS
30
33
 
31
34
  # Authenticates the user based on the session data
32
35
  # @param include_expired [Boolean] If true, returns decoded token data even when expired (default: false)
36
+ # @param block [Proc] Optional block to call to extract additional claims from the decoded JWT
33
37
  # @return [Hash] A hash containing the authentication response and a reason if the authentication failed
34
38
  # rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity
35
- def authenticate(include_expired: false)
39
+ def authenticate(include_expired: false, &claim_extractor)
36
40
  return { authenticated: false, reason: 'NO_SESSION_COOKIE_PROVIDED' } if @session_data.nil?
37
41
 
38
42
  begin
39
- session = Session.unseal_data(@session_data, @cookie_password)
43
+ session = Session.unseal_data(@session_data, @cookie_password, encryptor: @encryptor)
40
44
  rescue StandardError
41
45
  return { authenticated: false, reason: 'INVALID_SESSION_COOKIE' }
42
46
  end
@@ -59,7 +63,7 @@ module WorkOS
59
63
  return { authenticated: false, reason: 'INVALID_JWT' } if expired && !include_expired
60
64
 
61
65
  # Return full data for valid tokens or when include_expired is true
62
- {
66
+ result = {
63
67
  authenticated: !expired,
64
68
  session_id: decoded['sid'],
65
69
  organization_id: decoded['org_id'],
@@ -72,6 +76,8 @@ module WorkOS
72
76
  impersonator: session[:impersonator],
73
77
  reason: expired ? 'INVALID_JWT' : nil,
74
78
  }
79
+ result.merge!(claim_extractor.call(decoded)) if block_given?
80
+ result
75
81
  rescue JWT::DecodeError
76
82
  { authenticated: false, reason: 'INVALID_JWT' }
77
83
  rescue StandardError => e
@@ -89,7 +95,7 @@ module WorkOS
89
95
  cookie_password = options.nil? || options[:cookie_password].nil? ? @cookie_password : options[:cookie_password]
90
96
 
91
97
  begin
92
- session = Session.unseal_data(@session_data, cookie_password)
98
+ session = Session.unseal_data(@session_data, cookie_password, encryptor: @encryptor)
93
99
  rescue StandardError
94
100
  return { authenticated: false, reason: 'INVALID_SESSION_COOKIE' }
95
101
  end
@@ -101,7 +107,7 @@ module WorkOS
101
107
  client_id: @client_id,
102
108
  refresh_token: session[:refresh_token],
103
109
  organization_id: options.nil? || options[:organization_id].nil? ? nil : options[:organization_id],
104
- session: { seal_session: true, cookie_password: cookie_password },
110
+ session: { seal_session: true, cookie_password: cookie_password, encryptor: @encryptor },
105
111
  )
106
112
 
107
113
  @session_data = auth_response.sealed_session
@@ -134,43 +140,34 @@ module WorkOS
134
140
  @user_management.get_logout_url(session_id: auth_response[:session_id], return_to: return_to)
135
141
  end
136
142
 
137
- # Encrypts and seals data using AES-256-GCM
143
+ # Encrypts and seals data using the provided encryptor (defaults to AES-256-GCM)
138
144
  # @param data [Hash] The data to seal
139
145
  # @param key [String] The key to use for encryption
146
+ # @param encryptor [Object] Optional encryptor that responds to #seal(data, key)
140
147
  # @return [String] The sealed data
141
- def self.seal_data(data, key)
142
- iv = SecureRandom.random_bytes(12)
143
-
144
- encrypted_data = Encryptor.encrypt(
145
- value: JSON.generate(data),
146
- key: key,
147
- iv: iv,
148
- algorithm: 'aes-256-gcm',
149
- )
150
- Base64.encode64(iv + encrypted_data) # Combine IV with encrypted data and encode as base64
148
+ def self.seal_data(data, key, encryptor: nil)
149
+ enc = encryptor || WorkOS::Encryptors::AesGcm.new
150
+ enc.seal(data, key)
151
151
  end
152
152
 
153
- # Decrypts and unseals data using AES-256-GCM
153
+ # Decrypts and unseals data using the provided encryptor (defaults to AES-256-GCM)
154
154
  # @param sealed_data [String] The sealed data to unseal
155
155
  # @param key [String] The key to use for decryption
156
+ # @param encryptor [Object] Optional encryptor that responds to #unseal(sealed_data, key)
156
157
  # @return [Hash] The unsealed data
157
- def self.unseal_data(sealed_data, key)
158
- decoded_data = Base64.decode64(sealed_data)
159
- iv = decoded_data[0..11] # Extract the IV (first 12 bytes)
160
- encrypted_data = decoded_data[12..-1] # Extract the encrypted data
161
-
162
- decrypted_data = Encryptor.decrypt(
163
- value: encrypted_data,
164
- key: key,
165
- iv: iv,
166
- algorithm: 'aes-256-gcm',
167
- )
168
-
169
- JSON.parse(decrypted_data, symbolize_names: true) # Parse the decrypted JSON string back to original data
158
+ def self.unseal_data(sealed_data, key, encryptor: nil)
159
+ enc = encryptor || WorkOS::Encryptors::AesGcm.new
160
+ enc.unseal(sealed_data, key)
170
161
  end
171
162
 
172
163
  private
173
164
 
165
+ def validate_encryptor!(enc)
166
+ return if enc.respond_to?(:seal) && enc.respond_to?(:unseal)
167
+
168
+ raise ArgumentError, 'encryptor must respond to #seal(data, key) and #unseal(sealed_data, key)'
169
+ end
170
+
174
171
  # Creates a JWKS set from a remote JWKS URL
175
172
  # @param uri [URI] The URI of the JWKS
176
173
  # @return [JWT::JWK::Set] The JWKS set
@@ -42,14 +42,16 @@ module WorkOS
42
42
  # @param [String] client_id The WorkOS client ID for the environment
43
43
  # @param [String] session_data The sealed session data
44
44
  # @param [String] cookie_password The password used to seal the session
45
+ # @param [Object] encryptor Optional custom encryptor that responds to #seal and #unseal
45
46
  #
46
47
  # @return WorkOS::Session
47
- def load_sealed_session(client_id:, session_data:, cookie_password:)
48
+ def load_sealed_session(client_id:, session_data:, cookie_password:, encryptor: nil)
48
49
  WorkOS::Session.new(
49
50
  user_management: self,
50
51
  client_id: client_id,
51
52
  session_data: session_data,
52
53
  cookie_password: cookie_password,
54
+ encryptor: encryptor,
53
55
  )
54
56
  end
55
57
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module WorkOS
4
- VERSION = '5.31.1'
4
+ VERSION = '6.0.0'
5
5
  end
data/lib/workos.rb CHANGED
@@ -56,6 +56,7 @@ module WorkOS
56
56
  autoload :DirectorySync, 'workos/directory_sync'
57
57
  autoload :DirectoryUser, 'workos/directory_user'
58
58
  autoload :EmailVerification, 'workos/email_verification'
59
+ autoload :Encryptors, 'workos/encryptors'
59
60
  autoload :Event, 'workos/event'
60
61
  autoload :Events, 'workos/events'
61
62
  autoload :Factor, 'workos/factor'
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe WorkOS::Encryptors::AesGcm do
4
+ subject(:encryptor) { described_class.new }
5
+
6
+ let(:key) { 'a' * 32 }
7
+ let(:data) { { access_token: 'tok_123', user: { id: 'user_01' } } }
8
+
9
+ describe '#seal' do
10
+ it 'returns a base64-encoded string' do
11
+ sealed = encryptor.seal(data, key)
12
+ expect(sealed).to be_a(String)
13
+ expect { Base64.decode64(sealed) }.not_to raise_error
14
+ end
15
+
16
+ it 'produces different output each time (random IV)' do
17
+ sealed1 = encryptor.seal(data, key)
18
+ sealed2 = encryptor.seal(data, key)
19
+ expect(sealed1).not_to eq(sealed2)
20
+ end
21
+ end
22
+
23
+ describe '#unseal' do
24
+ it 'round-trips data correctly' do
25
+ sealed = encryptor.seal(data, key)
26
+ unsealed = encryptor.unseal(sealed, key)
27
+ expect(unsealed).to eq(data)
28
+ end
29
+
30
+ it 'returns hash with symbolized keys' do
31
+ sealed = encryptor.seal({ 'string_key' => 'value' }, key)
32
+ unsealed = encryptor.unseal(sealed, key)
33
+ expect(unsealed.keys.first).to be_a(Symbol)
34
+ end
35
+
36
+ it 'raises error with wrong key' do
37
+ sealed = encryptor.seal(data, key)
38
+ expect { encryptor.unseal(sealed, 'b' * 32) }.to raise_error(OpenSSL::Cipher::CipherError)
39
+ end
40
+ end
41
+ end
@@ -5,8 +5,8 @@ describe WorkOS::Session do
5
5
  let(:cookie_password) { 'test_very_long_cookie_password__' }
6
6
  let(:session_data) { 'test_session_data' }
7
7
  let(:jwks_url) { 'https://api.workos.com/sso/jwks/client_123' }
8
- let(:jwks_hash) { '{"keys":[{"alg":"RS256","kty":"RSA","use":"sig","n":"test_n","e":"AQAB","kid":"sso_oidc_key_pair_123","x5c":["test"],"x5t#S256":"test"}]}' } # rubocop:disable all
9
8
  let(:jwk) { JWT::JWK.new(OpenSSL::PKey::RSA.new(2048), { kid: 'sso_oidc_key_pair_123', use: 'sig', alg: 'RS256' }) }
9
+ let(:jwks_hash) { { keys: [jwk.export] }.to_json }
10
10
 
11
11
  before do
12
12
  allow(Net::HTTP).to receive(:get).and_return(jwks_hash)
@@ -222,6 +222,29 @@ describe WorkOS::Session do
222
222
  })
223
223
  end
224
224
 
225
+ it 'merges custom claims from claim_extractor block' do
226
+ custom_payload = payload.merge(custom_claim: 'custom_value', another_claim: 123)
227
+ custom_access_token = JWT.encode(custom_payload, jwk.signing_key, jwk[:alg], { kid: jwk[:kid] })
228
+ custom_session_data = WorkOS::Session.seal_data({
229
+ access_token: custom_access_token,
230
+ user: 'user',
231
+ impersonator: 'impersonator',
232
+ }, cookie_password,)
233
+ session = WorkOS::Session.new(
234
+ user_management: user_management,
235
+ client_id: client_id,
236
+ session_data: custom_session_data,
237
+ cookie_password: cookie_password,
238
+ )
239
+ allow_any_instance_of(JWT::Decode).to receive(:verify_signature).and_return(true)
240
+ result = session.authenticate do |jwt|
241
+ { my_custom_claim: jwt['custom_claim'], my_other_claim: jwt['another_claim'] }
242
+ end
243
+ expect(result[:authenticated]).to be true
244
+ expect(result[:my_custom_claim]).to eq('custom_value')
245
+ expect(result[:my_other_claim]).to eq(123)
246
+ end
247
+
225
248
  describe 'with entitlements' do
226
249
  let(:payload) do
227
250
  {
@@ -385,4 +408,68 @@ describe WorkOS::Session do
385
408
  end
386
409
  end
387
410
  end
411
+
412
+ describe 'custom encryptor' do
413
+ let(:user_management) { instance_double('UserManagement') }
414
+ let(:custom_encryptor) do
415
+ Class.new do
416
+ def seal(data, _key)
417
+ "CUSTOM:#{JSON.generate(data)}"
418
+ end
419
+
420
+ def unseal(sealed_data, _key)
421
+ json = sealed_data.sub('CUSTOM:', '')
422
+ JSON.parse(json, symbolize_names: true)
423
+ end
424
+ end.new
425
+ end
426
+
427
+ before do
428
+ allow(user_management).to receive(:get_jwks_url).with(client_id).and_return(jwks_url)
429
+ end
430
+
431
+ it 'uses custom encryptor for seal_data' do
432
+ sealed = WorkOS::Session.seal_data({ foo: 'bar' }, 'key', encryptor: custom_encryptor)
433
+ expect(sealed).to start_with('CUSTOM:')
434
+ end
435
+
436
+ it 'uses custom encryptor for unseal_data' do
437
+ sealed = 'CUSTOM:{"foo":"bar"}'
438
+ unsealed = WorkOS::Session.unseal_data(sealed, 'key', encryptor: custom_encryptor)
439
+ expect(unsealed).to eq({ foo: 'bar' })
440
+ end
441
+
442
+ it 'accepts custom encryptor in initialize' do
443
+ session = WorkOS::Session.new(
444
+ user_management: user_management,
445
+ client_id: client_id,
446
+ session_data: session_data,
447
+ cookie_password: cookie_password,
448
+ encryptor: custom_encryptor,
449
+ )
450
+ expect(session.encryptor).to eq(custom_encryptor)
451
+ end
452
+
453
+ it 'defaults to AesGcm encryptor when none provided' do
454
+ session = WorkOS::Session.new(
455
+ user_management: user_management,
456
+ client_id: client_id,
457
+ session_data: session_data,
458
+ cookie_password: cookie_password,
459
+ )
460
+ expect(session.encryptor).to be_a(WorkOS::Encryptors::AesGcm)
461
+ end
462
+
463
+ it 'raises ArgumentError for invalid encryptor' do
464
+ expect do
465
+ WorkOS::Session.new(
466
+ user_management: user_management,
467
+ client_id: client_id,
468
+ session_data: session_data,
469
+ cookie_password: cookie_password,
470
+ encryptor: Object.new,
471
+ )
472
+ end.to raise_error(ArgumentError, /must respond to/)
473
+ end
474
+ end
388
475
  end
data/workos.gemspec CHANGED
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
22
22
  spec.require_paths = ['lib']
23
23
 
24
24
  spec.add_dependency 'encryptor', '~> 3.0'
25
- spec.add_dependency 'jwt', '~> 2.8'
25
+ spec.add_dependency 'jwt', '~> 3.1'
26
26
 
27
27
  spec.add_development_dependency 'bundler', '>= 2.0.1'
28
28
  spec.add_development_dependency 'rake'
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.31.1
4
+ version: 6.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - WorkOS
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-02-03 00:00:00.000000000 Z
11
+ date: 2026-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: encryptor
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '2.8'
33
+ version: '3.1'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '2.8'
40
+ version: '3.1'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -166,6 +166,8 @@ files:
166
166
  - lib/workos/directory_sync.rb
167
167
  - lib/workos/directory_user.rb
168
168
  - lib/workos/email_verification.rb
169
+ - lib/workos/encryptors.rb
170
+ - lib/workos/encryptors/aes_gcm.rb
169
171
  - lib/workos/errors.rb
170
172
  - lib/workos/event.rb
171
173
  - lib/workos/events.rb
@@ -211,6 +213,7 @@ files:
211
213
  - spec/lib/workos/configuration_spec.rb
212
214
  - spec/lib/workos/directory_sync_spec.rb
213
215
  - spec/lib/workos/directory_user_spec.rb
216
+ - spec/lib/workos/encryptors/aes_gcm_spec.rb
214
217
  - spec/lib/workos/event_spec.rb
215
218
  - spec/lib/workos/mfa_spec.rb
216
219
  - spec/lib/workos/organizations_spec.rb
@@ -451,6 +454,7 @@ test_files:
451
454
  - spec/lib/workos/configuration_spec.rb
452
455
  - spec/lib/workos/directory_sync_spec.rb
453
456
  - spec/lib/workos/directory_user_spec.rb
457
+ - spec/lib/workos/encryptors/aes_gcm_spec.rb
454
458
  - spec/lib/workos/event_spec.rb
455
459
  - spec/lib/workos/mfa_spec.rb
456
460
  - spec/lib/workos/organizations_spec.rb