devise-rownd 1.0.1 → 1.1.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: 3317512e4c6ead0a28dddb83bcd70a07d66a118ded1898382c0ce90cf6f789c3
4
- data.tar.gz: 2de19260f908ff6f2544c1a8bcb4b3257c67c969fe8e5d52db102edd07384886
3
+ metadata.gz: 66fb0808a220fb26f13eeeaad657dfeb8a5f402b4ff8eb93ea4e78ca9d2a6dad
4
+ data.tar.gz: 21c796b17298e08ca8eb350ebc9564933c99e78dc9b471e09c7010b6e4477fc1
5
5
  SHA512:
6
- metadata.gz: 29bcc368a05051514753c79cdd176ef97f338ba9f467460a9a86df4e85cc7dadd62d81f188df5349473fbd102b98a89315f808288197fb6e07d7a5b174064990
7
- data.tar.gz: 03b017507234b0c520ac96e9c0a9a1fa939074e79e3f765376f68e09fba141c0c55b3b54524fac0adf21b60f25b42b0a5e8619c84b1bd2e9df210292f4c30653
6
+ metadata.gz: 9c4bc7a3fd3014d49f74a330c5af548be40349e266be90bf39b8d5599ac603e9c704e447b13b48310f5857df45a82d03e1767f5c978d00eaa2e80697589ed4c8
7
+ data.tar.gz: 1115a0a1e51d5650c4bd6c4aff8cc313d83a1c954307ae39cb73e67af166f07dcdc43feb9dbcee291e01af5d4ea0306b00bf6f31a3026a5996bc0faad6026a98
@@ -20,9 +20,11 @@ module Devise::Rownd
20
20
  warden.authenticate!(scope: :user)
21
21
  end
22
22
 
23
+ warden.authenticate!(scope: :user)
24
+
23
25
  render json: {
24
26
  message: 'Successfully authenticated user',
25
- should_refresh_page: new_access_token || session[:rownd_stale_data] == true,
27
+ should_refresh_page: new_access_token || session[:rownd_stale_data] == true
26
28
  }, status: :ok
27
29
  end
28
30
 
@@ -1,19 +1,25 @@
1
1
  require 'devise/rownd/api'
2
+ require 'devise/rownd/caching'
2
3
 
3
4
  module Devise
4
5
  module Rownd
5
6
  include API
6
7
 
7
8
  def app_config
8
- fetch_app_config
9
+ config = Devise::Rownd::Caching.fetch('rownd_app_config', 15.minutes) { fetch_app_config }
10
+
11
+ raise 'Failed to fetch app config' unless config
12
+
13
+ config
9
14
  end
10
15
 
11
16
  def self.fetch_app_config
12
- Rails.cache.fetch("rownd_app_config", expires_in: 15.minutes) do
13
- response = API.make_api_call('/hub/app-config', { method: 'GET',
14
- headers: { 'x-rownd-app-key' => app_key } })
15
- response.body['app'] if response.success?
16
- end
17
+ response = API.make_api_call('/hub/app-config', { method: 'GET',
18
+ headers: { 'x-rownd-app-key' => app_key } })
19
+ return response.body['app'] if response.success?
20
+
21
+ Rails.logger.error("Failed to fetch app config from Rownd: #{response.body['message']}")
22
+ nil
17
23
  end
18
24
 
19
25
  module_function :app_config
@@ -0,0 +1,30 @@
1
+ require 'async'
2
+
3
+ module Devise::Rownd
4
+ module Caching
5
+ def fetch(cache_key, ttl)
6
+ cache_val = Rails.cache.read(cache_key)
7
+
8
+ # If there's nothing in the cache, yield the value and write it to cache
9
+ if cache_val.nil?
10
+ return_value = yield
11
+ Rails.cache.write(cache_key, [return_value, Time.now]) if return_value
12
+ else
13
+ return_value = cache_val[0]
14
+ last_fetch_time = cache_val[1]
15
+
16
+ # Start a new thread to update the cached value if the TTL is exceeded
17
+ Async do
18
+ if Time.now - last_fetch_time > ttl
19
+ new_value = yield
20
+ Rails.cache.write(cache_key, [new_value, Time.now]) if new_value
21
+ end
22
+ end
23
+ end
24
+
25
+ return_value
26
+ end
27
+
28
+ module_function :fetch
29
+ end
30
+ end
@@ -8,21 +8,15 @@ module Devise
8
8
  # TODO: What if we don't interact with the database at all?
9
9
  class_methods do
10
10
  def find_or_create_with_authentication_profile(profile)
11
- result = where(user_id: profile['user_id']).first_or_create({ email: profile['email'] })
12
- result
11
+ where(user_id: profile['user_id']).first_or_create({ email: profile['email'] })
13
12
  end
14
13
 
15
14
  def serialize_from_session(data)
16
- result = Devise::Rownd::User.new(data)
17
- # result = find_by_user_id_or_email(user_id, email)
18
- result
15
+ Devise::Rownd::User.new(data)
19
16
  end
20
17
 
21
18
  def serialize_into_session(resource)
22
- # result = [resource.data]
23
- result = [resource]
24
- # result = [resource['user_id'], resource['email']]
25
- result
19
+ [resource]
26
20
  end
27
21
 
28
22
  # def find_by_user_id_or_email(user_id, email)
@@ -2,6 +2,7 @@ require 'devise'
2
2
  require 'devise/strategies/authenticatable'
3
3
  require 'devise/rownd/user'
4
4
  require 'devise/rownd/api'
5
+ require 'devise/rownd/caching'
5
6
  require 'jose'
6
7
 
7
8
  require_relative '../../../../config/initializers/app_creds'
@@ -20,18 +21,28 @@ module Devise
20
21
  @access_token = session[:rownd_user_access_token]
21
22
  return fail!('No Access Token') unless @access_token
22
23
 
23
- decoded_jwt = verify_token(@access_token)
24
- @app_id = decoded_jwt['aud'].find(/^app:.+/).first.split(':').last
24
+ begin
25
+ @decoded_jwt = verify_token(@access_token)
25
26
 
26
- configured_app_id = Devise::Rownd.app_id
27
- ok = @app_id == configured_app_id
28
- return fail!('JWT not authorized for app') unless ok
27
+ @app_id = @decoded_jwt['aud'].find(/^app:.+/).first.split(':').last
29
28
 
30
- rownd_user = Devise::Rownd::User.new(fetch_user)
29
+ configured_app_id = Devise::Rownd.app_id
30
+ ok = @app_id == configured_app_id
31
+ return fail!('JWT not authorized for app') unless ok
31
32
 
32
- return fail!(:unable_to_authenticate) unless rownd_user
33
+ user_data = fetch_user
34
+ return fail!('Failed to fetch user') unless user_data
33
35
 
34
- success!(rownd_user)
36
+ user_data['is_verified_user'] = @decoded_jwt['https://auth.rownd.io/is_verified_user']
37
+
38
+ rownd_user = Devise::Rownd::User.new(user_data)
39
+
40
+ return fail!('Failed to initialize user') unless rownd_user
41
+
42
+ success!(rownd_user)
43
+ rescue StandardError => e
44
+ fail!("Unable to authenticate: #{e.message}")
45
+ end
35
46
  end
36
47
 
37
48
  def return_to_after_sign_out
@@ -39,16 +50,17 @@ module Devise
39
50
  end
40
51
 
41
52
  def fetch_user
53
+ cache_key = "rownd_user_#{@decoded_jwt['jti']}"
42
54
  if session[:rownd_stale_data] == true
43
55
  data = fetch_user_from_api
44
- Rails.cache.write('rownd_user', data, expires_in: 1.minute)
56
+ return nil unless data
57
+
58
+ Rails.cache.write(cache_key, data, expires_in: 1.minute)
45
59
  session.delete(:rownd_stale_data) if session[:rownd_stale_data]
46
60
  return data
47
61
  end
48
62
 
49
- Rails.cache.fetch('rownd_user', expires_in: 1.minute) do
50
- fetch_user_from_api
51
- end
63
+ Devise::Rownd::Caching.fetch(cache_key, 1.minute) { fetch_user_from_api }
52
64
  end
53
65
 
54
66
  def fetch_user_from_api
@@ -61,31 +73,32 @@ module Devise
61
73
  )
62
74
  return response.body['data'] if response.success?
63
75
 
64
- raise StandardError, response.body['message']
76
+ Rails.logger.error("Failed to fetch user: #{response.body['message']}")
77
+ nil
65
78
  end
66
79
 
67
80
  def verify_token(access_token)
68
- for jwk in jwks
69
- begin
70
- response = JOSE::JWT.verify_strict(jwk, ['EdDSA'], access_token)
71
- return response[1].fields if response[0]
72
- rescue StandardError => e
73
- puts "Error: #{e}"
74
- next
75
- end
76
- raise StandardError
81
+ raise StandardError, 'No JWKs' unless jwks
82
+
83
+ jwks.each do |jwk|
84
+ response = JOSE::JWT.verify_strict(jwk, ['EdDSA'], access_token)
85
+ return response[1].fields if response[0]
86
+ rescue StandardError
87
+ next
77
88
  end
89
+ raise StandardError, 'Failed to verify JWT. No matching JWKs'
78
90
  end
79
91
 
80
92
  def jwks
81
- Rails.cache.fetch('rownd_jwks', expires_in: 15.minutes) do
82
- fetch_jwks
83
- end
93
+ Devise::Rownd::Caching.fetch('rownd_jwks', 15.minutes) { fetch_jwks_from_api }
84
94
  end
85
95
 
86
- def fetch_jwks
96
+ def fetch_jwks_from_api
87
97
  response = ::Devise::Rownd::API.make_api_call('/hub/auth/keys')
88
- response.body['keys']
98
+ return response.body['keys'] if response.success?
99
+
100
+ Rails.logger.error("Failed to fetch JWKs: #{response.body['message']}")
101
+ nil
89
102
  end
90
103
  end
91
104
  end
@@ -1,7 +1,7 @@
1
1
  module Devise
2
2
  module Rownd
3
3
  class User
4
- attr_reader :data
4
+ attr_reader :data, :is_verified_user
5
5
 
6
6
  def initialize(data)
7
7
  @data = data
@@ -10,6 +10,11 @@ module Devise
10
10
  instance_variable_value = data.is_a?(Hash) && data.key?(key) ? data[key] : nil
11
11
  instance_variable_set("@#{key}", instance_variable_value)
12
12
  end
13
+ @is_verified_user = data.key?('is_verified_user') ? data['is_verified_user'] : false
14
+ end
15
+
16
+ def verified?
17
+ @is_verified_user
13
18
  end
14
19
  end
15
20
  end
@@ -1,5 +1,5 @@
1
1
  module Devise
2
2
  module Rownd
3
- VERSION = '1.0.1'
3
+ VERSION = '1.1.0'
4
4
  end
5
5
  end
data/lib/devise/rownd.rb CHANGED
@@ -4,6 +4,7 @@ require 'devise/rownd/strategies'
4
4
  require 'devise/rownd/models'
5
5
  require 'devise/rownd/api'
6
6
  require 'devise/rownd/user'
7
+ require 'devise/rownd/caching'
7
8
 
8
9
  module Devise
9
10
  module Rownd
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devise-rownd
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bobby Radford
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-04-27 00:00:00.000000000 Z
11
+ date: 2022-06-03 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: async
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.30.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.30.2
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: devise
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -191,6 +205,7 @@ files:
191
205
  - config/routes.rb
192
206
  - lib/devise/rownd.rb
193
207
  - lib/devise/rownd/api.rb
208
+ - lib/devise/rownd/caching.rb
194
209
  - lib/devise/rownd/custom_failure.rb
195
210
  - lib/devise/rownd/engine.rb
196
211
  - lib/devise/rownd/models.rb