devise-rownd 1.1.0 → 2.0.2
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/README.md +6 -7
- data/app/controllers/devise/rownd/auth_controller.rb +37 -13
- data/config/initializers/app_config.rb +2 -1
- data/lib/devise/rownd/caching.rb +15 -4
- data/lib/devise/rownd/log.rb +17 -0
- data/lib/devise/rownd/models/rownd_authenticatable.rb +25 -4
- data/lib/devise/rownd/strategies/rownd_authenticatable.rb +33 -68
- data/lib/devise/rownd/token.rb +39 -0
- data/lib/devise/rownd/user.rb +57 -5
- data/lib/devise/rownd/version.rb +1 -1
- data/lib/devise/rownd.rb +5 -5
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4f7ee7e95256bfe7248ca432b6e12f692687c9e33069d9247e0b2b3c8cd7992f
|
4
|
+
data.tar.gz: 69f8bc39f7202ca660f1290bc76404be3d4f4cc0954c2de5641a052891537208
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5c34d1f38d22df9ad37ee898a11710510f75d46384bd8142c0d123733797252f574e50a1b63a11625c05e1c2c7c8e38f87f367d070ce61725ec89be253bd3268
|
7
|
+
data.tar.gz: 0af0e09cb34a97e6d7d9a9eda7c63f11765359fb60a86e70d32317714718ffc2147b9a6899fe2d1bae97c131e1dbc383bd13d25d3d71c5d42859ee02fec82487
|
data/README.md
CHANGED
@@ -2,13 +2,13 @@
|
|
2
2
|
|
3
3
|
[](https://badge.fury.io/rb/devise-jwt)
|
4
4
|
|
5
|
-
`devise-rownd` is a [devise](https://github.com/heartcombo/devise) extension that
|
5
|
+
`devise-rownd` is a [devise](https://github.com/heartcombo/devise) extension that authenticates users with Rownd's passwordless authentication strategies. It works in-tandem with the Rownd Hub, a javascript snippet embedded in your website. With this Gem installed, Rownd handles all aspects of user authentication and gives you the tools to customize the user experience on your site.
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
Add this line to your application's Gemfile:
|
9
9
|
|
10
10
|
```ruby
|
11
|
-
gem 'devise-rownd'
|
11
|
+
gem 'devise-rownd', '~> 2.0.2'
|
12
12
|
```
|
13
13
|
|
14
14
|
And then execute:
|
@@ -32,7 +32,7 @@ mount Devise::Rownd::Engine, at: '/api/auth/rownd'
|
|
32
32
|
### Rownd Hub
|
33
33
|
Follow [these instructions](https://docs.rownd.io/rownd/sdk-reference/web/javascript-browser) to install the Rownd Hub. You'll want to ensure it runs on every page of your application, so be sure to add it as a common in your Rails JS packs. Here's the easiest way to do that:
|
34
34
|
|
35
|
-
1. Create a new file in your JS packs
|
35
|
+
1. Create a new file in your JS packs directory called `rph.js` and paste the JS snippet that you obtained from the instructions listed above.
|
36
36
|
|
37
37
|
3. Add the following API callbacks to your Javascript:
|
38
38
|
```javascript
|
@@ -62,7 +62,7 @@ _rphConfig.push(['setPostUserDataUpdateApi', {
|
|
62
62
|
<%= javascript_pack_tag 'rph', 'data-turbolinks-track': 'reload' %>
|
63
63
|
</body>
|
64
64
|
```
|
65
|
-
There are two key pieces that you
|
65
|
+
There are two key pieces that you must include in the layout:
|
66
66
|
|
67
67
|
`<%= show_rownd_signin_if_required %>`
|
68
68
|
This renders the Rownd sign in modal to prompt the user for authentication when your app explicitly requires it in a controller
|
@@ -74,7 +74,6 @@ Tells Rails to include the rph Javascript pack. We also tell Turbolinks to inclu
|
|
74
74
|
|
75
75
|
For this to work, you need to define these key environment variables:
|
76
76
|
|
77
|
-
* `ROWND_APP_ID` - This is the ID of your Rownd application
|
78
77
|
* `ROWND_APP_KEY` - Your Rownd application key
|
79
78
|
* `ROWND_APP_SECRET` - Your Rownd application secret
|
80
79
|
|
@@ -130,9 +129,9 @@ The `current_user` object has all of the fields specified in your Rownd applicat
|
|
130
129
|
|
131
130
|
### Extending the `current_user` model
|
132
131
|
|
133
|
-
You can extend the `current_user` object by modifying the `Devise::Rownd::User` class. This can be very helpful if you want to have
|
132
|
+
You can extend the `current_user` object by modifying the `Devise::Rownd::User` class. This can be very helpful if you want to have additional functions that aggregate data accross multiple fields, or perform some logic and return the result.
|
134
133
|
|
135
|
-
For instance, you might want a function called `admin?` that will return if the current user
|
134
|
+
For instance, you might want a function called `admin?` that will return if the current user has an `'admin'` role. To extend the `current_user` object, add a new initializer in `config/initializers` called `devise_rownd.rb`. In there you can modify the `Devise::Rownd::User` like this:
|
136
135
|
|
137
136
|
```ruby
|
138
137
|
Devise::Rownd::User.class_eval do
|
@@ -3,34 +3,42 @@
|
|
3
3
|
# # ONLY NEEDED IN `classic` MODE.
|
4
4
|
# require_dependency 'devise/rownd/application_controller'
|
5
5
|
|
6
|
+
require 'devise/rownd/log'
|
7
|
+
|
6
8
|
module Devise::Rownd
|
7
9
|
class AuthController < ApplicationController
|
8
10
|
# Skip authenticity token verification
|
9
|
-
skip_before_action :verify_authenticity_token
|
11
|
+
skip_before_action :verify_authenticity_token, raise: false
|
10
12
|
|
11
13
|
def authenticate
|
12
|
-
|
13
|
-
|
14
|
-
|
14
|
+
Devise::Rownd::Log.debug('handle /authenticate')
|
15
|
+
access_token = params[:access_token]
|
16
|
+
session_token = session['warden.user.user.key']
|
17
|
+
new_access_token = session_token != access_token
|
15
18
|
|
16
|
-
|
19
|
+
Devise::Rownd::Log.debug("/authenticate: new_access_token = #{new_access_token}")
|
17
20
|
|
18
|
-
if
|
21
|
+
if !session_token.nil? && new_access_token
|
22
|
+
# We have to log the user out otherwise warden will just serialize the user from session,
|
23
|
+
# which currently holds the old access token
|
19
24
|
warden.logout(:user)
|
20
|
-
warden.authenticate!(scope: :user)
|
21
25
|
end
|
22
26
|
|
23
27
|
warden.authenticate!(scope: :user)
|
24
28
|
|
29
|
+
should_refresh_page = new_access_token
|
30
|
+
Devise::Rownd::Log.debug("/authenticate: success, refresh = #{should_refresh_page}")
|
31
|
+
|
25
32
|
render json: {
|
26
33
|
message: 'Successfully authenticated user',
|
27
|
-
should_refresh_page:
|
34
|
+
should_refresh_page: should_refresh_page
|
28
35
|
}, status: :ok
|
29
36
|
end
|
30
37
|
|
31
38
|
def sign_out
|
32
|
-
|
39
|
+
Devise::Rownd::Log.debug('handling /sign_out')
|
33
40
|
warden.logout(:user)
|
41
|
+
Devise::Rownd::Log.debug('/sign_out: success')
|
34
42
|
render json: {
|
35
43
|
message: 'Successfully signed out user',
|
36
44
|
return_to: return_to_after_sign_out
|
@@ -38,10 +46,26 @@ module Devise::Rownd
|
|
38
46
|
end
|
39
47
|
|
40
48
|
def update_data
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
49
|
+
Devise::Rownd::Log.debug('handling /update_data')
|
50
|
+
|
51
|
+
request_body = JSON.parse request.body.read
|
52
|
+
profile = {
|
53
|
+
'data' => request_body['user_data']
|
54
|
+
}
|
55
|
+
new_user = Devise::Rownd::User.new(profile, session['warden.user.user.key'])
|
56
|
+
|
57
|
+
Devise::Rownd::Log.debug("/update_data: instantiated user: #{new_user}")
|
58
|
+
|
59
|
+
warden.set_user(new_user)
|
60
|
+
|
61
|
+
Devise::Rownd::Log.debug('/update_data: set user in warden')
|
62
|
+
|
63
|
+
# Remove the cached user profile data so that the next next time its accessed, it will be
|
64
|
+
# fetched from the API Server
|
65
|
+
cache_key = "rownd_user_#{new_user.data['user_id']}"
|
66
|
+
Rails.cache.delete(cache_key)
|
67
|
+
Devise::Rownd::Log.debug("/update_data: removed cache key: #{cache_key}")
|
68
|
+
|
45
69
|
render json: {
|
46
70
|
# should_refresh_page: true
|
47
71
|
}, status: :ok
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'devise/rownd/api'
|
2
2
|
require 'devise/rownd/caching'
|
3
|
+
require 'devise/rownd/log'
|
3
4
|
|
4
5
|
module Devise
|
5
6
|
module Rownd
|
@@ -18,7 +19,7 @@ module Devise
|
|
18
19
|
headers: { 'x-rownd-app-key' => app_key } })
|
19
20
|
return response.body['app'] if response.success?
|
20
21
|
|
21
|
-
|
22
|
+
Devise::Rownd::Log.error("Failed to fetch app config from Rownd: #{response.body['message']}")
|
22
23
|
nil
|
23
24
|
end
|
24
25
|
|
data/lib/devise/rownd/caching.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'async'
|
2
|
+
require 'devise/rownd/log'
|
2
3
|
|
3
4
|
module Devise::Rownd
|
4
5
|
module Caching
|
@@ -7,17 +8,27 @@ module Devise::Rownd
|
|
7
8
|
|
8
9
|
# If there's nothing in the cache, yield the value and write it to cache
|
9
10
|
if cache_val.nil?
|
11
|
+
Devise::Rownd::Log.debug("cache: key not found '#{cache_key}'")
|
10
12
|
return_value = yield
|
11
|
-
|
13
|
+
if return_value
|
14
|
+
Devise::Rownd::Log.debug("cache: updating cache. '#{cache_key}' value: #{return_value}")
|
15
|
+
Rails.cache.write(cache_key, [return_value, Time.now]) if return_value
|
16
|
+
end
|
12
17
|
else
|
18
|
+
Devise::Rownd::Log.debug("cache: key found: '#{cache_key}'")
|
13
19
|
return_value = cache_val[0]
|
14
20
|
last_fetch_time = cache_val[1]
|
15
21
|
|
16
22
|
# Start a new thread to update the cached value if the TTL is exceeded
|
17
23
|
Async do
|
18
|
-
|
19
|
-
|
20
|
-
|
24
|
+
begin
|
25
|
+
if Time.now - last_fetch_time > ttl
|
26
|
+
new_value = yield
|
27
|
+
Devise::Rownd::Log.debug("cache: updating cache. '#{cache_key}' value: #{new_value}")
|
28
|
+
Rails.cache.write(cache_key, [new_value, Time.now]) if new_value
|
29
|
+
end
|
30
|
+
rescue StandardError => e
|
31
|
+
Devise::Rownd::Log.error("cache: failed updating cache: #{e.message}")
|
21
32
|
end
|
22
33
|
end
|
23
34
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Devise::Rownd
|
2
|
+
module Log
|
3
|
+
@logger ||= ActiveSupport::TaggedLogging.new(Logger.new(($stdout))) if (ENV['rownd_debug'] || ENV['ROWND_DEBUG']) == 'true'
|
4
|
+
|
5
|
+
def self.debug(message)
|
6
|
+
return unless @logger
|
7
|
+
|
8
|
+
@logger.tagged('Rownd') { @logger.debug(message) }
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.error(message)
|
12
|
+
return unless @logger
|
13
|
+
|
14
|
+
@logger.tagged('Rownd') { @logger.error(message) }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'active_support/concern'
|
2
|
+
require 'devise/rownd/log'
|
2
3
|
|
3
4
|
module Devise
|
4
5
|
module Models
|
@@ -11,12 +12,32 @@ module Devise
|
|
11
12
|
where(user_id: profile['user_id']).first_or_create({ email: profile['email'] })
|
12
13
|
end
|
13
14
|
|
14
|
-
def serialize_from_session(
|
15
|
-
Devise::Rownd::
|
15
|
+
def serialize_from_session(access_token)
|
16
|
+
Devise::Rownd::Log.debug("serialize_from_session: #{access_token}")
|
17
|
+
return nil if access_token.nil?
|
18
|
+
|
19
|
+
begin
|
20
|
+
profile = Devise::Rownd::User.fetch_user(access_token)
|
21
|
+
rescue StandardError => e
|
22
|
+
Devise::Rownd::Log.debug("serialize_from_session: session has invalid access token #{e.message}")
|
23
|
+
return nil
|
24
|
+
end
|
25
|
+
|
26
|
+
if profile.nil?
|
27
|
+
Devise::Rownd::Log.debug('serialize_from_session: could not fetch user profile')
|
28
|
+
return nil
|
29
|
+
end
|
30
|
+
|
31
|
+
# initialize user with fetched data
|
32
|
+
user = Devise::Rownd::User.new(profile, access_token)
|
33
|
+
Devise::Rownd::Log.debug("serialize_from_session result: #{user}")
|
34
|
+
user
|
16
35
|
end
|
17
36
|
|
18
|
-
def serialize_into_session(
|
19
|
-
|
37
|
+
def serialize_into_session(user)
|
38
|
+
Devise::Rownd::Log.debug("serialize_into_session: #{user}")
|
39
|
+
|
40
|
+
user.access_token
|
20
41
|
end
|
21
42
|
|
22
43
|
# def find_by_user_id_or_email(user_id, email)
|
@@ -1,46 +1,63 @@
|
|
1
1
|
require 'devise'
|
2
2
|
require 'devise/strategies/authenticatable'
|
3
3
|
require 'devise/rownd/user'
|
4
|
-
require 'devise/rownd/
|
5
|
-
require 'devise/rownd/
|
6
|
-
require 'jose'
|
4
|
+
require 'devise/rownd/token'
|
5
|
+
require 'devise/rownd/log'
|
7
6
|
|
8
7
|
require_relative '../../../../config/initializers/app_creds'
|
9
8
|
|
9
|
+
|
10
|
+
# jose prefers to use libsodium for EdDSA to work. This next line tells jose to fallback to the ruby
|
11
|
+
# crypto library in the event that libsodium is not installed
|
12
|
+
JOSE.crypto_fallback = '1'
|
13
|
+
|
10
14
|
module Devise
|
11
15
|
module Strategies
|
12
|
-
include
|
16
|
+
include Devise::Rownd::Token
|
13
17
|
|
14
18
|
class RowndAuthenticatable < Authenticatable
|
15
19
|
def valid?
|
16
|
-
|
20
|
+
valid_for_auth = params[:access_token].present?
|
21
|
+
Devise::Rownd::Log.debug("valid for authentication?: #{valid_for_auth}")
|
22
|
+
valid_for_auth
|
17
23
|
end
|
18
24
|
|
19
25
|
# All Strategies must define this method.
|
20
26
|
def authenticate!
|
21
|
-
|
22
|
-
|
27
|
+
Devise::Rownd::Log.debug('authenticate!')
|
28
|
+
access_token = params[:access_token]
|
29
|
+
|
30
|
+
Devise::Rownd::Log.error('authenticate! could not proceed. no access token') unless access_token
|
31
|
+
return fail!('No Access Token') unless access_token
|
23
32
|
|
24
33
|
begin
|
25
|
-
|
34
|
+
decoded_jwt = ::Devise::Rownd::Token.verify_token(access_token)
|
26
35
|
|
27
|
-
@app_id =
|
36
|
+
@app_id = decoded_jwt['aud'].find(/^app:.+/).first.split(':').last
|
28
37
|
|
29
38
|
configured_app_id = Devise::Rownd.app_id
|
30
39
|
ok = @app_id == configured_app_id
|
31
|
-
|
40
|
+
unless ok
|
41
|
+
Devise::Rownd::Log.error('authenticate! failed: JWT not authorized for app')
|
42
|
+
return fail!('JWT not authorized for app')
|
43
|
+
end
|
32
44
|
|
33
|
-
|
34
|
-
|
45
|
+
profile = Devise::Rownd::User.fetch_user(access_token)
|
46
|
+
unless profile
|
47
|
+
Devise::Rownd::Log.error('authenticate! failed: Failed to fetch user')
|
48
|
+
fail!('Failed to fetch user')
|
49
|
+
end
|
35
50
|
|
36
|
-
|
51
|
+
rownd_user = Devise::Rownd::User.new(profile, access_token)
|
37
52
|
|
38
|
-
rownd_user
|
39
|
-
|
40
|
-
|
53
|
+
unless rownd_user
|
54
|
+
Devise::Rownd::Log.error('authenticate! failed: failed to initialize user')
|
55
|
+
return fail!('Failed to initialize user')
|
56
|
+
end
|
41
57
|
|
42
58
|
success!(rownd_user)
|
43
59
|
rescue StandardError => e
|
60
|
+
Devise::Rownd::Log.error("authenticate! failed #{e.message}")
|
44
61
|
fail!("Unable to authenticate: #{e.message}")
|
45
62
|
end
|
46
63
|
end
|
@@ -48,58 +65,6 @@ module Devise
|
|
48
65
|
def return_to_after_sign_out
|
49
66
|
'/'
|
50
67
|
end
|
51
|
-
|
52
|
-
def fetch_user
|
53
|
-
cache_key = "rownd_user_#{@decoded_jwt['jti']}"
|
54
|
-
if session[:rownd_stale_data] == true
|
55
|
-
data = fetch_user_from_api
|
56
|
-
return nil unless data
|
57
|
-
|
58
|
-
Rails.cache.write(cache_key, data, expires_in: 1.minute)
|
59
|
-
session.delete(:rownd_stale_data) if session[:rownd_stale_data]
|
60
|
-
return data
|
61
|
-
end
|
62
|
-
|
63
|
-
Devise::Rownd::Caching.fetch(cache_key, 1.minute) { fetch_user_from_api }
|
64
|
-
end
|
65
|
-
|
66
|
-
def fetch_user_from_api
|
67
|
-
response = ::Devise::Rownd::API.make_api_call(
|
68
|
-
"/me/applications/#{@app_id}/data",
|
69
|
-
{
|
70
|
-
method: 'GET',
|
71
|
-
headers: { 'Authorization' => "Bearer #{@access_token}" }
|
72
|
-
}
|
73
|
-
)
|
74
|
-
return response.body['data'] if response.success?
|
75
|
-
|
76
|
-
Rails.logger.error("Failed to fetch user: #{response.body['message']}")
|
77
|
-
nil
|
78
|
-
end
|
79
|
-
|
80
|
-
def verify_token(access_token)
|
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
|
88
|
-
end
|
89
|
-
raise StandardError, 'Failed to verify JWT. No matching JWKs'
|
90
|
-
end
|
91
|
-
|
92
|
-
def jwks
|
93
|
-
Devise::Rownd::Caching.fetch('rownd_jwks', 15.minutes) { fetch_jwks_from_api }
|
94
|
-
end
|
95
|
-
|
96
|
-
def fetch_jwks_from_api
|
97
|
-
response = ::Devise::Rownd::API.make_api_call('/hub/auth/keys')
|
98
|
-
return response.body['keys'] if response.success?
|
99
|
-
|
100
|
-
Rails.logger.error("Failed to fetch JWKs: #{response.body['message']}")
|
101
|
-
nil
|
102
|
-
end
|
103
68
|
end
|
104
69
|
end
|
105
70
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'devise/rownd/api'
|
2
|
+
require 'devise/rownd/caching'
|
3
|
+
require 'devise/rownd/log'
|
4
|
+
require 'jose'
|
5
|
+
|
6
|
+
# jose prefers to use libsodium for EdDSA to work. This next line tells jose to fallback to the ruby
|
7
|
+
# crypto library in the event that libsodium is not installed
|
8
|
+
JOSE.crypto_fallback = '1'
|
9
|
+
|
10
|
+
module Devise::Rownd
|
11
|
+
module Token
|
12
|
+
def verify_token(access_token)
|
13
|
+
raise StandardError, 'No JWKs' unless jwks
|
14
|
+
|
15
|
+
jwks.each do |jwk|
|
16
|
+
response = JOSE::JWT.verify_strict(jwk, ['EdDSA'], access_token)
|
17
|
+
return response[1].fields if response[0]
|
18
|
+
rescue StandardError => e
|
19
|
+
Devise::Rownd::Log.debug("jwt not validated: #{e.message}")
|
20
|
+
next
|
21
|
+
end
|
22
|
+
raise StandardError, 'Failed to verify JWT. No matching JWKs'
|
23
|
+
end
|
24
|
+
|
25
|
+
def jwks
|
26
|
+
Devise::Rownd::Caching.fetch('rownd_jwks', 15.minutes) { fetch_jwks_from_api }
|
27
|
+
end
|
28
|
+
|
29
|
+
def fetch_jwks_from_api
|
30
|
+
response = ::Devise::Rownd::API.make_api_call('/hub/auth/keys')
|
31
|
+
return response.body['keys'] if response.success?
|
32
|
+
|
33
|
+
Devise::Rownd::Log.error("Failed to fetch JWKs: #{response.body['message']}")
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
|
37
|
+
module_function :jwks, :fetch_jwks_from_api, :verify_token
|
38
|
+
end
|
39
|
+
end
|
data/lib/devise/rownd/user.rb
CHANGED
@@ -1,21 +1,73 @@
|
|
1
|
+
require 'devise/rownd/api'
|
2
|
+
require 'devise/rownd/caching'
|
3
|
+
require 'devise/rownd/token'
|
4
|
+
require 'devise/rownd/log'
|
5
|
+
|
1
6
|
module Devise
|
2
7
|
module Rownd
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
3
10
|
class User
|
4
|
-
attr_reader :data, :is_verified_user
|
11
|
+
attr_reader :user_id, :auth_level, :data, :is_verified_user, :access_token
|
5
12
|
|
6
|
-
def initialize(
|
7
|
-
|
13
|
+
def initialize(profile, access_token)
|
14
|
+
Devise::Rownd::Log.debug("initialize user: #{profile} - #{access_token}")
|
15
|
+
@user_id = profile['data']['user_id']
|
16
|
+
@data = profile
|
8
17
|
Devise::Rownd.app_schema.each do |key, _value|
|
9
18
|
self.class.send :attr_accessor, key
|
10
|
-
instance_variable_value = data.is_a?(Hash) && data.key?(key) ? data[key] : nil
|
19
|
+
instance_variable_value = profile['data'].is_a?(Hash) && profile['data'].key?(key) ? profile['data'][key] : nil
|
11
20
|
instance_variable_set("@#{key}", instance_variable_value)
|
12
21
|
end
|
13
|
-
|
22
|
+
|
23
|
+
@access_token = access_token
|
24
|
+
@auth_level = profile['auth_level']
|
25
|
+
@is_verified_user = profile['auth_level'] == 'verified'
|
26
|
+
|
27
|
+
Devise::Rownd::Log.debug('successfully initialized user')
|
14
28
|
end
|
15
29
|
|
16
30
|
def verified?
|
17
31
|
@is_verified_user
|
18
32
|
end
|
33
|
+
|
34
|
+
def self.fetch_user(access_token, bypass_cache = false)
|
35
|
+
Devise::Rownd::Log.debug("fetch_user: #{self}")
|
36
|
+
begin
|
37
|
+
decoded_jwt = ::Devise::Rownd::Token.verify_token(access_token)
|
38
|
+
app_id = decoded_jwt['aud'].find(/^app:.+/).first.split(':').last
|
39
|
+
|
40
|
+
cache_key = "rownd_user_#{decoded_jwt['https://auth.rownd.io/app_user_id']}"
|
41
|
+
if bypass_cache == true
|
42
|
+
Devise::Rownd::Log.debug('fetch_user bypassing cache')
|
43
|
+
profile = fetch_user_from_api(access_token, app_id)
|
44
|
+
return nil unless profile
|
45
|
+
|
46
|
+
Rails.cache.write(cache_key, profile, expires_in: 1.minute)
|
47
|
+
return profile
|
48
|
+
end
|
49
|
+
|
50
|
+
Devise::Rownd::Log.debug('fetch_user from cache if possible')
|
51
|
+
Devise::Rownd::Caching.fetch(cache_key, 1.minute) { fetch_user_from_api(access_token, app_id) }
|
52
|
+
rescue StandardError => e
|
53
|
+
Devise::Rownd::Log.error("fetch_user failed: #{e.message}")
|
54
|
+
nil
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.fetch_user_from_api(access_token, app_id)
|
59
|
+
response = ::Devise::Rownd::API.make_api_call(
|
60
|
+
"/me/applications/#{app_id}/data",
|
61
|
+
{
|
62
|
+
method: 'GET',
|
63
|
+
headers: { 'Authorization' => "Bearer #{access_token}" }
|
64
|
+
}
|
65
|
+
)
|
66
|
+
return response.body if response.success?
|
67
|
+
|
68
|
+
Devise::Rownd::Log.error("Failed to fetch user: #{response.body}")
|
69
|
+
nil
|
70
|
+
end
|
19
71
|
end
|
20
72
|
end
|
21
73
|
end
|
data/lib/devise/rownd/version.rb
CHANGED
data/lib/devise/rownd.rb
CHANGED
@@ -6,12 +6,12 @@ require 'devise/rownd/api'
|
|
6
6
|
require 'devise/rownd/user'
|
7
7
|
require 'devise/rownd/caching'
|
8
8
|
|
9
|
-
module Devise
|
10
|
-
module Rownd
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
9
|
require_relative '../../config/config'
|
15
10
|
require_relative '../../config/initializers/app_creds'
|
16
11
|
require_relative '../../config/initializers/app_config'
|
17
12
|
# require_relative '../../config/initializers/devise'
|
13
|
+
|
14
|
+
module Devise
|
15
|
+
module Rownd
|
16
|
+
end
|
17
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: devise-rownd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bobby Radford
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-02-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: async
|
@@ -208,10 +208,12 @@ files:
|
|
208
208
|
- lib/devise/rownd/caching.rb
|
209
209
|
- lib/devise/rownd/custom_failure.rb
|
210
210
|
- lib/devise/rownd/engine.rb
|
211
|
+
- lib/devise/rownd/log.rb
|
211
212
|
- lib/devise/rownd/models.rb
|
212
213
|
- lib/devise/rownd/models/rownd_authenticatable.rb
|
213
214
|
- lib/devise/rownd/strategies.rb
|
214
215
|
- lib/devise/rownd/strategies/rownd_authenticatable.rb
|
216
|
+
- lib/devise/rownd/token.rb
|
215
217
|
- lib/devise/rownd/user.rb
|
216
218
|
- lib/devise/rownd/version.rb
|
217
219
|
- lib/tasks/devise/rownd_tasks.rake
|