devise-rownd 1.0.2 → 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 +4 -4
- data/app/controllers/devise/rownd/auth_controller.rb +3 -1
- data/config/initializers/app_config.rb +12 -6
- data/lib/devise/rownd/caching.rb +30 -0
- data/lib/devise/rownd/strategies/rownd_authenticatable.rb +36 -26
- data/lib/devise/rownd/version.rb +1 -1
- data/lib/devise/rownd.rb +1 -0
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d54df50c4a7815d8fe0ee291891134f7e1fbb9f9afebb935b48e6f34ec649467
|
4
|
+
data.tar.gz: 24410b4335a8e44ed8d1bb62215ce43ec8215e5d3ef949565c022ce533188f6b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
|
@@ -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
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
24
|
-
|
24
|
+
begin
|
25
|
+
@decoded_jwt = verify_token(@access_token)
|
25
26
|
|
26
|
-
|
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
|
-
|
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
|
-
|
33
|
+
user_data = fetch_user
|
34
|
+
return fail!('Failed to fetch user') unless user_data
|
33
35
|
|
34
|
-
|
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
|
@@ -42,14 +51,14 @@ module Devise
|
|
42
51
|
cache_key = "rownd_user_#{@decoded_jwt['jti']}"
|
43
52
|
if session[:rownd_stale_data] == true
|
44
53
|
data = fetch_user_from_api
|
54
|
+
return nil unless data
|
55
|
+
|
45
56
|
Rails.cache.write(cache_key, data, expires_in: 1.minute)
|
46
57
|
session.delete(:rownd_stale_data) if session[:rownd_stale_data]
|
47
58
|
return data
|
48
59
|
end
|
49
60
|
|
50
|
-
|
51
|
-
fetch_user_from_api
|
52
|
-
end
|
61
|
+
Devise::Rownd::Caching.fetch(cache_key, 1.minute) { fetch_user_from_api }
|
53
62
|
end
|
54
63
|
|
55
64
|
def fetch_user_from_api
|
@@ -62,31 +71,32 @@ module Devise
|
|
62
71
|
)
|
63
72
|
return response.body['data'] if response.success?
|
64
73
|
|
65
|
-
|
74
|
+
Rails.logger.error("Failed to fetch user: #{response.body['message']}")
|
75
|
+
nil
|
66
76
|
end
|
67
77
|
|
68
78
|
def verify_token(access_token)
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
end
|
77
|
-
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
|
78
86
|
end
|
87
|
+
raise StandardError, 'Failed to verify JWT. No matching JWKs'
|
79
88
|
end
|
80
89
|
|
81
90
|
def jwks
|
82
|
-
|
83
|
-
fetch_jwks
|
84
|
-
end
|
91
|
+
Devise::Rownd::Caching.fetch('rownd_jwks', 15.minutes) { fetch_jwks_from_api }
|
85
92
|
end
|
86
93
|
|
87
|
-
def
|
94
|
+
def fetch_jwks_from_api
|
88
95
|
response = ::Devise::Rownd::API.make_api_call('/hub/auth/keys')
|
89
|
-
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
|
90
100
|
end
|
91
101
|
end
|
92
102
|
end
|
data/lib/devise/rownd/version.rb
CHANGED
data/lib/devise/rownd.rb
CHANGED
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.
|
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-05-
|
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
|