devise-rownd 1.0.3 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 +26 -11
- data/lib/devise/rownd/strategies/rownd_authenticatable.rb +33 -66
- data/lib/devise/rownd/token.rb +39 -0
- data/lib/devise/rownd/user.rb +61 -4
- 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: 965501f9c7bd20e9f907772de92d1718011e48c035e10fc2d936b797a201e434
|
4
|
+
data.tar.gz: 9365b48fe108cde601e190bbbdd182ed8b65928f0b904c9429af78aceb4a3980
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c33282e8619f37a4e2c28e6c2b4967e0c88a6f9c204eeeecd19a407e8e9f97f9c343c4581ca995256113443a78f8f946b7ad58d12d1c9a6c78fa34e2639d92dd
|
7
|
+
data.tar.gz: b4a53ed34ccdc5769837fc8d4dfcdd6edf67c9f73acdf5bc48b4b7a90141aa633019e5ed01d638f07846dba16ed8580a20d570c80ffaedf2154ae183cdb2f022
|
data/README.md
CHANGED
@@ -2,13 +2,13 @@
|
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/devise-rownd.svg)](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.0'
|
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:
|
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
|
@@ -8,21 +9,35 @@ module Devise
|
|
8
9
|
# TODO: What if we don't interact with the database at all?
|
9
10
|
class_methods do
|
10
11
|
def find_or_create_with_authentication_profile(profile)
|
11
|
-
|
12
|
-
result
|
12
|
+
where(user_id: profile['user_id']).first_or_create({ email: profile['email'] })
|
13
13
|
end
|
14
14
|
|
15
|
-
def serialize_from_session(
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
19
35
|
end
|
20
36
|
|
21
|
-
def serialize_into_session(
|
22
|
-
#
|
23
|
-
|
24
|
-
|
25
|
-
result
|
37
|
+
def serialize_into_session(user)
|
38
|
+
Devise::Rownd::Log.debug("serialize_into_session: #{user}")
|
39
|
+
|
40
|
+
user.access_token
|
26
41
|
end
|
27
42
|
|
28
43
|
# def find_by_user_id_or_email(user_id, email)
|
@@ -1,44 +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
|
-
rownd_user = Devise::Rownd::User.new(
|
51
|
+
rownd_user = Devise::Rownd::User.new(profile, access_token)
|
37
52
|
|
38
|
-
|
53
|
+
unless rownd_user
|
54
|
+
Devise::Rownd::Log.error('authenticate! failed: failed to initialize user')
|
55
|
+
return fail!('Failed to initialize user')
|
56
|
+
end
|
39
57
|
|
40
58
|
success!(rownd_user)
|
41
59
|
rescue StandardError => e
|
60
|
+
Devise::Rownd::Log.error("authenticate! failed #{e.message}")
|
42
61
|
fail!("Unable to authenticate: #{e.message}")
|
43
62
|
end
|
44
63
|
end
|
@@ -46,58 +65,6 @@ module Devise
|
|
46
65
|
def return_to_after_sign_out
|
47
66
|
'/'
|
48
67
|
end
|
49
|
-
|
50
|
-
def fetch_user
|
51
|
-
cache_key = "rownd_user_#{@decoded_jwt['jti']}"
|
52
|
-
if session[:rownd_stale_data] == true
|
53
|
-
data = fetch_user_from_api
|
54
|
-
return nil unless data
|
55
|
-
|
56
|
-
Rails.cache.write(cache_key, data, expires_in: 1.minute)
|
57
|
-
session.delete(:rownd_stale_data) if session[:rownd_stale_data]
|
58
|
-
return data
|
59
|
-
end
|
60
|
-
|
61
|
-
Devise::Rownd::Caching.fetch(cache_key, 1.minute) { fetch_user_from_api }
|
62
|
-
end
|
63
|
-
|
64
|
-
def fetch_user_from_api
|
65
|
-
response = ::Devise::Rownd::API.make_api_call(
|
66
|
-
"/me/applications/#{@app_id}/data",
|
67
|
-
{
|
68
|
-
method: 'GET',
|
69
|
-
headers: { 'Authorization' => "Bearer #{@access_token}" }
|
70
|
-
}
|
71
|
-
)
|
72
|
-
return response.body['data'] if response.success?
|
73
|
-
|
74
|
-
Rails.logger.error("Failed to fetch user: #{response.body['message']}")
|
75
|
-
nil
|
76
|
-
end
|
77
|
-
|
78
|
-
def verify_token(access_token)
|
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
|
86
|
-
end
|
87
|
-
raise StandardError, 'Failed to verify JWT. No matching JWKs'
|
88
|
-
end
|
89
|
-
|
90
|
-
def jwks
|
91
|
-
Devise::Rownd::Caching.fetch('rownd_jwks', 15.minutes) { fetch_jwks_from_api }
|
92
|
-
end
|
93
|
-
|
94
|
-
def fetch_jwks_from_api
|
95
|
-
response = ::Devise::Rownd::API.make_api_call('/hub/auth/keys')
|
96
|
-
return response.body['keys'] if response.success?
|
97
|
-
|
98
|
-
Rails.logger.error("Failed to fetch JWKs: #{response.body['message']}")
|
99
|
-
nil
|
100
|
-
end
|
101
68
|
end
|
102
69
|
end
|
103
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,15 +1,72 @@
|
|
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
|
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
|
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')
|
28
|
+
end
|
29
|
+
|
30
|
+
def verified?
|
31
|
+
@is_verified_user
|
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
|
13
70
|
end
|
14
71
|
end
|
15
72
|
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.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:
|
11
|
+
date: 2024-06-17 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
|