devise-rownd 1.0.0 → 1.0.3

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: 472c2fc42ba778e0a7b888b3855a26f625ec83c15b5420cedb6441549f8e9336
4
- data.tar.gz: 81fd0a737715b7be796acb202b7d267a40663128e2fb300d025ccd7f307a09ae
3
+ metadata.gz: d54df50c4a7815d8fe0ee291891134f7e1fbb9f9afebb935b48e6f34ec649467
4
+ data.tar.gz: 24410b4335a8e44ed8d1bb62215ce43ec8215e5d3ef949565c022ce533188f6b
5
5
  SHA512:
6
- metadata.gz: 8aea286cffa63aed1791e8599eb211c9043448dd2ceddf147d489bb09f633dc6c1c134e7ba30220cc52fda5c8eaaeabc650596121dbec73af5d3c750d624147f
7
- data.tar.gz: 59a104ec432e8fbbc4e2814aff6713da1caf2d330c07e565a353f2c61240d5516e2fd7e93a84c00931592376a443445d39d4c7d3f2015d1dcd41ba9fb37b8704
6
+ metadata.gz: 4323c21cdf8ba62dc8d11c4c95016064987ca2d256cef7e525cc635286ad57d2fd40fc2d52708677d5d6a970ad335800cd728326befdfbc34dc9e9d8dbd535d9
7
+ data.tar.gz: c835bc2862a1338fb379c0578a4dc9493a372ff0aadf1ec4f1aebb011a383a595b401b5e1868ea53a0584cf8118c5ff3d543525216ff9d20f1148d958205780a
@@ -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
 
@@ -39,6 +41,7 @@ module Devise::Rownd
39
41
  session[:rownd_stale_data] = true
40
42
  warden.logout(:user)
41
43
  warden.authenticate!(scope: :user)
44
+ session[:rownd_stale_data] = false
42
45
  render json: {
43
46
  # should_refresh_page: true
44
47
  }, status: :ok
@@ -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
@@ -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,26 @@ 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
+ rownd_user = Devise::Rownd::User.new(user_data)
37
+
38
+ return fail!('Failed to initialize user') unless rownd_user
39
+
40
+ success!(rownd_user)
41
+ rescue StandardError => e
42
+ fail!("Unable to authenticate: #{e.message}")
43
+ end
35
44
  end
36
45
 
37
46
  def return_to_after_sign_out
@@ -39,16 +48,17 @@ module Devise
39
48
  end
40
49
 
41
50
  def fetch_user
51
+ cache_key = "rownd_user_#{@decoded_jwt['jti']}"
42
52
  if session[:rownd_stale_data] == true
43
53
  data = fetch_user_from_api
44
- Rails.cache.write('rownd_user', data, expires_in: 1.minute)
54
+ return nil unless data
55
+
56
+ Rails.cache.write(cache_key, data, expires_in: 1.minute)
45
57
  session.delete(:rownd_stale_data) if session[:rownd_stale_data]
46
58
  return data
47
59
  end
48
60
 
49
- Rails.cache.fetch('rownd_user', expires_in: 1.minute) do
50
- fetch_user_from_api
51
- end
61
+ Devise::Rownd::Caching.fetch(cache_key, 1.minute) { fetch_user_from_api }
52
62
  end
53
63
 
54
64
  def fetch_user_from_api
@@ -61,31 +71,32 @@ module Devise
61
71
  )
62
72
  return response.body['data'] if response.success?
63
73
 
64
- raise StandardError, response.body['message']
74
+ Rails.logger.error("Failed to fetch user: #{response.body['message']}")
75
+ nil
65
76
  end
66
77
 
67
78
  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
79
+ raise StandardError, 'No JWKs' unless jwks
80
+
81
+ jwks.each do |jwk|
82
+ response = JOSE::JWT.verify_strict(jwk, ['EdDSA'], access_token)
83
+ return response[1].fields if response[0]
84
+ rescue StandardError
85
+ next
77
86
  end
87
+ raise StandardError, 'Failed to verify JWT. No matching JWKs'
78
88
  end
79
89
 
80
90
  def jwks
81
- Rails.cache.fetch('rownd_jwks', expires_in: 15.minutes) do
82
- fetch_jwks
83
- end
91
+ Devise::Rownd::Caching.fetch('rownd_jwks', 15.minutes) { fetch_jwks_from_api }
84
92
  end
85
93
 
86
- def fetch_jwks
94
+ def fetch_jwks_from_api
87
95
  response = ::Devise::Rownd::API.make_api_call('/hub/auth/keys')
88
- response.body['keys']
96
+ return response.body['keys'] if response.success?
97
+
98
+ Rails.logger.error("Failed to fetch JWKs: #{response.body['message']}")
99
+ nil
89
100
  end
90
101
  end
91
102
  end
@@ -1,5 +1,5 @@
1
1
  module Devise
2
2
  module Rownd
3
- VERSION = '1.0.0'
3
+ VERSION = '1.0.3'
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.0
4
+ version: 1.0.3
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-22 00:00:00.000000000 Z
11
+ date: 2022-05-19 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