devise-rownd 1.0.0 → 1.0.3

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: 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