devise-rownd 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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