devise_jwt_auth 0.1.1 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +3 -3
- data/app/controllers/devise_jwt_auth/application_controller.rb +15 -13
- data/app/controllers/devise_jwt_auth/concerns/resource_finder.rb +2 -6
- data/app/controllers/devise_jwt_auth/concerns/{set_user_by_jwt_token.rb → set_user_by_token.rb} +23 -19
- data/app/controllers/devise_jwt_auth/confirmations_controller.rb +10 -19
- data/app/controllers/devise_jwt_auth/omniauth_callbacks_controller.rb +32 -33
- data/app/controllers/devise_jwt_auth/passwords_controller.rb +29 -19
- data/app/controllers/devise_jwt_auth/refresh_token_controller.rb +4 -1
- data/app/controllers/devise_jwt_auth/registrations_controller.rb +40 -21
- data/app/controllers/devise_jwt_auth/sessions_controller.rb +21 -21
- data/app/controllers/devise_jwt_auth/unlocks_controller.rb +5 -4
- data/app/models/devise_jwt_auth/concerns/active_record_support.rb +3 -0
- data/app/models/devise_jwt_auth/concerns/confirmable_support.rb +7 -4
- data/app/models/devise_jwt_auth/concerns/mongoid_support.rb +3 -0
- data/app/models/devise_jwt_auth/concerns/tokens_serialization.rb +4 -1
- data/app/models/devise_jwt_auth/concerns/user.rb +18 -9
- data/app/models/devise_jwt_auth/concerns/user_omniauth_callbacks.rb +11 -3
- data/app/validators/devise_jwt_auth_email_validator.rb +5 -4
- data/lib/devise_jwt_auth/blacklist.rb +2 -0
- data/lib/devise_jwt_auth/controllers/url_helpers.rb +1 -2
- data/lib/devise_jwt_auth/engine.rb +4 -4
- data/lib/devise_jwt_auth/rails/routes.rb +35 -24
- data/lib/devise_jwt_auth/token_factory.rb +3 -2
- data/lib/devise_jwt_auth/url.rb +2 -4
- data/lib/devise_jwt_auth/version.rb +1 -1
- data/lib/generators/devise_jwt_auth/install_generator.rb +7 -6
- data/lib/generators/devise_jwt_auth/install_generator_helpers.rb +27 -6
- data/lib/generators/devise_jwt_auth/install_mongoid_generator.rb +3 -2
- data/lib/generators/devise_jwt_auth/templates/devise_jwt_auth.rb +15 -16
- data/lib/generators/devise_jwt_auth/templates/devise_jwt_auth_create_users.rb.erb +15 -11
- data/lib/generators/devise_jwt_auth/templates/user.rb.erb +2 -2
- data/test/controllers/custom/custom_confirmations_controller_test.rb +2 -2
- data/test/controllers/custom/custom_passwords_controller_test.rb +4 -4
- data/test/controllers/custom/custom_refresh_token_controller_test.rb +2 -3
- data/test/controllers/custom/custom_registrations_controller_test.rb +2 -2
- data/test/controllers/demo_mang_controller_test.rb +206 -210
- data/test/controllers/demo_user_controller_test.rb +358 -374
- data/test/controllers/devise_jwt_auth/confirmations_controller_test.rb +5 -5
- data/test/controllers/devise_jwt_auth/omniauth_callbacks_controller_test.rb +6 -7
- data/test/controllers/devise_jwt_auth/passwords_controller_test.rb +11 -13
- data/test/controllers/devise_jwt_auth/refresh_token_controller_test.rb +8 -12
- data/test/controllers/devise_jwt_auth/registrations_controller_test.rb +23 -25
- data/test/controllers/devise_jwt_auth/sessions_controller_test.rb +32 -34
- data/test/controllers/devise_jwt_auth/unlocks_controller_test.rb +2 -2
- data/test/controllers/overrides/confirmations_controller_test.rb +1 -1
- data/test/controllers/overrides/passwords_controller_test.rb +1 -1
- data/test/controllers/overrides/refresh_token_controller_test.rb +1 -2
- data/test/controllers/overrides/registrations_controller_test.rb +1 -1
- data/test/dummy/app/controllers/application_controller.rb +1 -1
- data/test/dummy/app/controllers/custom/refresh_token_controller.rb +2 -1
- data/test/dummy/app/controllers/custom/registrations_controller.rb +1 -1
- data/test/dummy/app/controllers/overrides/confirmations_controller.rb +4 -4
- data/test/dummy/app/controllers/overrides/omniauth_callbacks_controller.rb +4 -4
- data/test/dummy/app/controllers/overrides/passwords_controller.rb +4 -4
- data/test/dummy/app/controllers/overrides/refresh_token_controller.rb +1 -1
- data/test/dummy/app/controllers/overrides/registrations_controller.rb +2 -2
- data/test/dummy/app/controllers/overrides/sessions_controller.rb +2 -2
- data/test/dummy/app/models/concerns/favorite_color.rb +11 -9
- data/test/dummy/config.ru +2 -2
- data/test/dummy/config/application.rb +1 -0
- data/test/dummy/config/boot.rb +1 -1
- data/test/dummy/config/environments/test.rb +11 -7
- data/test/dummy/config/initializers/figaro.rb +1 -1
- data/test/dummy/config/initializers/omniauth.rb +2 -2
- data/test/dummy/config/routes.rb +8 -8
- data/test/dummy/db/migrate/{20140715061447_devise_token_auth_create_users.rb → 20140715061447_devise_jwt_auth_create_users.rb} +0 -0
- data/test/dummy/db/migrate/{20140715061805_devise_token_auth_create_mangs.rb → 20140715061805_devise_jwt_auth_create_mangs.rb} +0 -0
- data/test/dummy/db/migrate/{20141222035835_devise_token_auth_create_only_email_users.rb → 20141222035835_devise_jwt_auth_create_only_email_users.rb} +9 -9
- data/test/dummy/db/migrate/{20141222053502_devise_token_auth_create_unregisterable_users.rb → 20141222053502_devise_jwt_auth_create_unregisterable_users.rb} +0 -0
- data/test/dummy/db/migrate/{20150708104536_devise_token_auth_create_unconfirmable_users.rb → 20150708104536_devise_jwt_auth_create_unconfirmable_users.rb} +0 -0
- data/test/dummy/db/migrate/{20160103235141_devise_token_auth_create_scoped_users.rb → 20160103235141_devise_jwt_auth_create_scoped_users.rb} +0 -0
- data/test/dummy/db/migrate/{20160629184441_devise_token_auth_create_lockable_users.rb → 20160629184441_devise_jwt_auth_create_lockable_users.rb} +0 -0
- data/test/dummy/db/migrate/{20190924101113_devise_token_auth_create_confirmable_users.rb → 20190924101113_devise_jwt_auth_create_confirmable_users.rb} +6 -5
- data/test/dummy/db/schema.rb +170 -170
- data/test/dummy/tmp/generators/app/controllers/application_controller.rb +6 -0
- data/test/dummy/tmp/generators/app/models/user.rb +9 -0
- data/test/dummy/tmp/generators/config/initializers/devise_jwt_auth.rb +73 -0
- data/test/dummy/tmp/generators/db/migrate/20201006030349_devise_jwt_auth_create_users.rb +54 -0
- data/test/factories/users.rb +5 -3
- data/test/lib/devise_jwt_auth/token_factory_test.rb +6 -6
- data/test/lib/generators/devise_jwt_auth/install_generator_test.rb +3 -20
- data/test/lib/generators/devise_jwt_auth/install_generator_with_namespace_test.rb +4 -21
- data/test/models/concerns/tokens_serialization_test.rb +68 -68
- data/test/models/user_test.rb +35 -37
- data/test/support/controllers/routes.rb +7 -5
- data/test/test_helper.rb +1 -1
- metadata +70 -76
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9c1a405bebeaa7813dc0b99465db4530d29bf458fe392dd968f11b8abc5b11ab
|
4
|
+
data.tar.gz: d1c81c134b4031df4ef862041a4dfc4a0bc021f2cd538c020c23aaccc485e298
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 06141ad295c58d63e8f4e87bc26be3af1b223b52ac2a865329c0ea438bfb7409e7e0466ad2fb1a70b156ba773346dca676d04b6f3fe00e1297b900a3cc482bdd
|
7
|
+
data.tar.gz: b7de2ecb350212b5fc8e91b0066bd5cb5050ca1e5c1c344a116b8d2ce77273b5f8066dc654a26ab0412bb4d8e5b679f4852a16c022cee60a04b0408e2f0a1a12
|
data/README.md
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
A JWT-based port of [Devise Token Auth](https://github.com/lynndylanhurley/devise_token_auth) with silent refresh support.
|
4
4
|
|
5
|
-
If you're building SPA or a mobile app, this library takes an JWT
|
5
|
+
If you're building SPA or a mobile app, this library takes an JWT approach to authentication. If you're new to how JWTs (pronounced 'jot') work, you can read up on them [here](https://jwt.io/introduction/). This library is designed with an access/refresh token authentication model in mind.
|
6
6
|
|
7
7
|
## How does silent refresh authentication work?
|
8
8
|
|
9
|
-
When a user is authenticated, an access token is sent in the response and usually in the body in the form of JSON data. These tokens are designed to last a "short" time - only about 15 minutes. What you do with these tokens is up to you, but the best practice is to keep these tokens in memory and NOT to store them as cookies or in local storage. That way they cannot be used in XSS or CSRF attacks. The access tokens are then sent as headers in requests when an authenticated user is required to access protected resources.
|
9
|
+
When a user is authenticated, an access token is sent in the response and usually in the body in the form of JSON data. These tokens are designed to last a "short" time - only about 15 minutes. What you do with these tokens is up to you, but the best practice is to keep these tokens in memory and NOT to store them as cookies or in local storage. That way they cannot be used in [XSS](https://en.wikipedia.org/wiki/Cross-site_scripting) or [CSRF](https://en.wikipedia.org/wiki/Cross-site_request_forgery) attacks. The access tokens are then sent as headers in requests when an authenticated user is required to access protected resources.
|
10
10
|
|
11
11
|
The downside here is that the user will need to reauthenticate themselves frequently and if the user reloads their browser, the access token disappears and the user is no longer authenticated. This is where refresh tokens come into play.
|
12
12
|
|
@@ -57,7 +57,7 @@ See our [Contribution Guidelines](https://github.com/aarona/devise_jwt_auth/blob
|
|
57
57
|
|
58
58
|
## Live Demos
|
59
59
|
|
60
|
-
Live demos will hopefully be added in the future.
|
60
|
+
Live demos will hopefully be added in the future. Currently, I have a [repository](https://github.com/aarona/dja_example) available that is a proof of concept for DJA that uses React as the client. However, the example application only supports sigining up, sigining in and singing out. It doesn't provide a way to reset a user's password for example and other things that DJA supports. Those will be added in the near future.
|
61
61
|
|
62
62
|
## License
|
63
63
|
|
@@ -2,8 +2,7 @@
|
|
2
2
|
|
3
3
|
module DeviseJwtAuth
|
4
4
|
class ApplicationController < DeviseController
|
5
|
-
|
6
|
-
include DeviseJwtAuth::Concerns::SetUserByJwtToken
|
5
|
+
include DeviseJwtAuth::Concerns::SetUserByToken
|
7
6
|
|
8
7
|
def resource_data(opts = {})
|
9
8
|
response_data = opts[:resource_json] || @resource.as_json
|
@@ -21,17 +20,17 @@ module DeviseJwtAuth
|
|
21
20
|
DeviseJwtAuth.redirect_whitelist && !DeviseJwtAuth::Url.whitelisted?(redirect_url)
|
22
21
|
end
|
23
22
|
|
24
|
-
def build_redirect_headers(access_token,
|
23
|
+
def build_redirect_headers(access_token, _client, redirect_header_options = {})
|
25
24
|
{
|
26
25
|
# DeviseJwtAuth.headers_names[:"access-token"] => access_token,
|
27
26
|
# DeviseJwtAuth.headers_names[:"client"] => client,
|
28
|
-
:
|
27
|
+
config: params[:config],
|
29
28
|
|
30
29
|
# Legacy parameters which may be removed in a future release.
|
31
30
|
# Consider using "client" and "access-token" in client code.
|
32
31
|
# See: github.com/lynndylanhurley/devise_jwt_auth/issues/993
|
33
32
|
# :client_id => client,
|
34
|
-
:
|
33
|
+
token: access_token
|
35
34
|
}.merge(redirect_header_options)
|
36
35
|
end
|
37
36
|
|
@@ -43,20 +42,23 @@ module DeviseJwtAuth
|
|
43
42
|
end
|
44
43
|
|
45
44
|
def resource_class(m = nil)
|
46
|
-
if m
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
45
|
+
mapping = if m
|
46
|
+
Devise.mappings[m]
|
47
|
+
else
|
48
|
+
Devise.mappings[resource_name] || Devise.mappings.values.first
|
49
|
+
end
|
51
50
|
|
52
51
|
mapping.to
|
53
52
|
end
|
54
53
|
|
55
54
|
def json_api?
|
56
55
|
return false unless defined?(ActiveModel::Serializer)
|
57
|
-
|
58
|
-
|
59
|
-
|
56
|
+
|
57
|
+
if ActiveModel::Serializer.respond_to?(:setup)
|
58
|
+
return ActiveModel::Serializer.setup do |config|
|
59
|
+
config.adapter == :json_api
|
60
|
+
end
|
61
|
+
end
|
60
62
|
ActiveModelSerializers.config.adapter == :json_api
|
61
63
|
end
|
62
64
|
|
@@ -8,13 +8,9 @@ module DeviseJwtAuth::Concerns::ResourceFinder
|
|
8
8
|
# honor Devise configuration for case_insensitive keys
|
9
9
|
q_value = resource_params[field.to_sym]
|
10
10
|
|
11
|
-
if resource_class.case_insensitive_keys.include?(field.to_sym)
|
12
|
-
q_value.downcase!
|
13
|
-
end
|
11
|
+
q_value.downcase! if resource_class.case_insensitive_keys.include?(field.to_sym)
|
14
12
|
|
15
|
-
if resource_class.strip_whitespace_keys.include?(field.to_sym)
|
16
|
-
q_value.strip!
|
17
|
-
end
|
13
|
+
q_value.strip! if resource_class.strip_whitespace_keys.include?(field.to_sym)
|
18
14
|
|
19
15
|
q_value
|
20
16
|
end
|
data/app/controllers/devise_jwt_auth/concerns/{set_user_by_jwt_token.rb → set_user_by_token.rb}
RENAMED
@@ -1,11 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module DeviseJwtAuth::Concerns::
|
3
|
+
module DeviseJwtAuth::Concerns::SetUserByToken
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
include DeviseJwtAuth::Concerns::ResourceFinder
|
6
6
|
|
7
7
|
included do
|
8
|
-
|
9
8
|
end
|
10
9
|
|
11
10
|
protected
|
@@ -22,10 +21,10 @@ module DeviseJwtAuth::Concerns::SetUserByJwtToken
|
|
22
21
|
devise_warden_user = warden.user(rc.to_s.underscore.to_sym)
|
23
22
|
@resource = devise_warden_user if devise_warden_user
|
24
23
|
end
|
25
|
-
|
24
|
+
|
26
25
|
# user has already been found and authenticated
|
27
|
-
return @resource if @resource
|
28
|
-
|
26
|
+
return @resource if @resource&.is_a?(rc)
|
27
|
+
|
29
28
|
# TODO: Look for the access token in an 'Authentication' header
|
30
29
|
token = request.headers[DeviseJwtAuth.access_token_name]
|
31
30
|
return unless token
|
@@ -33,8 +32,9 @@ module DeviseJwtAuth::Concerns::SetUserByJwtToken
|
|
33
32
|
payload = DeviseJwtAuth::TokenFactory.decode_access_token(token)
|
34
33
|
return if payload.empty?
|
35
34
|
return if payload && payload['sub'].blank?
|
35
|
+
|
36
36
|
uid = payload['sub']
|
37
|
-
|
37
|
+
|
38
38
|
# mitigate timing attacks by finding by uid instead of auth token
|
39
39
|
user = uid && rc.dta_find_by(uid: uid)
|
40
40
|
scope = rc.to_s.underscore.to_sym
|
@@ -46,10 +46,10 @@ module DeviseJwtAuth::Concerns::SetUserByJwtToken
|
|
46
46
|
else
|
47
47
|
sign_in(scope, user, store: false, event: :fetch, bypass: DeviseJwtAuth.bypass_sign_in)
|
48
48
|
end
|
49
|
-
|
49
|
+
@resource = user
|
50
50
|
else
|
51
51
|
# zero all values previously set values
|
52
|
-
|
52
|
+
@resource = nil
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
@@ -65,10 +65,10 @@ module DeviseJwtAuth::Concerns::SetUserByJwtToken
|
|
65
65
|
devise_warden_user = warden.user(rc.to_s.underscore.to_sym)
|
66
66
|
@resource = devise_warden_user if devise_warden_user
|
67
67
|
end
|
68
|
-
|
68
|
+
|
69
69
|
# user has already been found and authenticated
|
70
|
-
return @resource if @resource
|
71
|
-
|
70
|
+
return @resource if @resource&.is_a?(rc)
|
71
|
+
|
72
72
|
token = request.cookies[DeviseJwtAuth.refresh_token_name]
|
73
73
|
|
74
74
|
return unless token
|
@@ -76,6 +76,7 @@ module DeviseJwtAuth::Concerns::SetUserByJwtToken
|
|
76
76
|
payload = DeviseJwtAuth::TokenFactory.decode_refresh_token(token)
|
77
77
|
return if payload.empty?
|
78
78
|
return if payload && payload['sub'].blank?
|
79
|
+
|
79
80
|
uid = payload['sub']
|
80
81
|
|
81
82
|
# mitigate timing attacks by finding by uid instead of auth token
|
@@ -89,13 +90,12 @@ module DeviseJwtAuth::Concerns::SetUserByJwtToken
|
|
89
90
|
else
|
90
91
|
sign_in(scope, user, store: false, event: :fetch, bypass: DeviseJwtAuth.bypass_sign_in)
|
91
92
|
end
|
92
|
-
|
93
|
+
@resource = user
|
93
94
|
else
|
94
95
|
# zero all values previously set values
|
95
|
-
|
96
|
+
@resource = nil
|
96
97
|
end
|
97
98
|
end
|
98
|
-
|
99
99
|
|
100
100
|
def update_refresh_token_cookie
|
101
101
|
response.set_cookie(DeviseJwtAuth.refresh_token_name,
|
@@ -103,9 +103,13 @@ module DeviseJwtAuth::Concerns::SetUserByJwtToken
|
|
103
103
|
path: '/auth/refresh_token', # TODO: Use configured auth path
|
104
104
|
expires: Time.zone.now + DeviseJwtAuth.refresh_token_lifespan,
|
105
105
|
httponly: true,
|
106
|
-
secure: Rails.env.production?
|
107
|
-
|
106
|
+
secure: Rails.env.production?)
|
107
|
+
end
|
108
|
+
|
109
|
+
def clear_refresh_token_cookie
|
110
|
+
response.set_cookie(DeviseJwtAuth.refresh_token_name,
|
111
|
+
value: '',
|
112
|
+
path: '/auth/refresh_token', # TODO: Use configured auth path
|
113
|
+
expires: Time.zone.now)
|
108
114
|
end
|
109
|
-
|
110
|
-
|
111
|
-
end
|
115
|
+
end
|
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
module DeviseJwtAuth
|
4
4
|
class ConfirmationsController < DeviseJwtAuth::ApplicationController
|
5
|
-
|
6
5
|
def show
|
7
6
|
@resource = resource_class.confirm_by_token(resource_params[:confirmation_token])
|
8
7
|
|
@@ -12,19 +11,12 @@ module DeviseJwtAuth
|
|
12
11
|
redirect_header_options = { account_confirmation_success: true }
|
13
12
|
|
14
13
|
if signed_in?(resource_name)
|
15
|
-
|
16
|
-
|
17
|
-
# redirect_headers = build_redirect_headers(token.token,
|
18
|
-
# token.client,
|
19
|
-
# redirect_header_options)
|
20
|
-
|
21
|
-
redirect_headers = signed_in_resource.create_named_token_pair.
|
22
|
-
merge(redirect_header_options)
|
14
|
+
redirect_headers = signed_in_resource.create_named_token_pair
|
15
|
+
.merge(redirect_header_options)
|
23
16
|
|
24
|
-
# TODO: add a refresh token cookie in the response.
|
25
17
|
update_refresh_token_cookie
|
26
|
-
|
27
|
-
#redirect_to_link = signed_in_resource.build_auth_url(redirect_url, redirect_headers)
|
18
|
+
|
19
|
+
# redirect_to_link = signed_in_resource.build_auth_url(redirect_url, redirect_headers)
|
28
20
|
redirect_to_link = DeviseJwtAuth::Url.generate(redirect_url, redirect_headers)
|
29
21
|
else
|
30
22
|
redirect_to_link = DeviseJwtAuth::Url.generate(redirect_url, redirect_header_options)
|
@@ -46,11 +38,11 @@ module DeviseJwtAuth
|
|
46
38
|
return render_not_found_error unless @resource
|
47
39
|
|
48
40
|
@resource.send_confirmation_instructions({
|
49
|
-
|
50
|
-
|
51
|
-
|
41
|
+
redirect_url: redirect_url,
|
42
|
+
client_config: resource_params[:config_name]
|
43
|
+
})
|
52
44
|
|
53
|
-
|
45
|
+
render_create_success
|
54
46
|
end
|
55
47
|
|
56
48
|
protected
|
@@ -61,8 +53,8 @@ module DeviseJwtAuth
|
|
61
53
|
|
62
54
|
def render_create_success
|
63
55
|
render json: {
|
64
|
-
|
65
|
-
|
56
|
+
success: true,
|
57
|
+
message: I18n.t('devise_jwt_auth.confirmations.sended', email: @email)
|
66
58
|
}
|
67
59
|
end
|
68
60
|
|
@@ -83,6 +75,5 @@ module DeviseJwtAuth
|
|
83
75
|
DeviseJwtAuth.default_confirm_success_url
|
84
76
|
)
|
85
77
|
end
|
86
|
-
|
87
78
|
end
|
88
79
|
end
|
@@ -7,12 +7,10 @@ module DeviseJwtAuth
|
|
7
7
|
before_action :validate_auth_origin_url_param
|
8
8
|
|
9
9
|
skip_before_action :set_user_by_jwt_token, raise: false
|
10
|
-
# skip_after_action :update_auth_header
|
11
10
|
|
12
11
|
# intermediary route for successful omniauth authentication. omniauth does
|
13
12
|
# not support multiple models, so we must resort to this terrible hack.
|
14
13
|
def redirect_callbacks
|
15
|
-
|
16
14
|
# derive target redirect route from 'resource_class' param, which was set
|
17
15
|
# before authentication.
|
18
16
|
devise_mapping = get_devise_mapping
|
@@ -29,15 +27,17 @@ module DeviseJwtAuth
|
|
29
27
|
def get_redirect_route(devise_mapping)
|
30
28
|
path = "#{Devise.mappings[devise_mapping.to_sym].fullpath}/#{params[:provider]}/callback"
|
31
29
|
klass = request.scheme == 'https' ? URI::HTTPS : URI::HTTP
|
32
|
-
|
30
|
+
klass.build(host: request.host, port: request.port, path: path).to_s
|
33
31
|
end
|
34
32
|
|
35
33
|
def get_devise_mapping
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
34
|
+
# derive target redirect route from 'resource_class' param, which was set
|
35
|
+
# before authentication.
|
36
|
+
[
|
37
|
+
request.env['omniauth.params']['namespace_name'],
|
38
|
+
request.env['omniauth.params']['resource_class'].underscore.gsub('/', '_')
|
39
|
+
].compact.join('_')
|
40
|
+
rescue NoMethodError
|
41
41
|
default_devise_mapping
|
42
42
|
end
|
43
43
|
|
@@ -45,13 +45,13 @@ module DeviseJwtAuth
|
|
45
45
|
# find the mapping in `omniauth.params`.
|
46
46
|
#
|
47
47
|
# One example use-case here is for IDP-initiated SAML login. In that
|
48
|
-
# case, there will have been no initial request in which to save
|
48
|
+
# case, there will have been no initial request in which to save
|
49
49
|
# the devise mapping. If you are in a situation like that, and
|
50
50
|
# your app allows for you to determine somehow what the devise
|
51
51
|
# mapping should be (because, for example, it is always the same),
|
52
52
|
# then you can handle it by overriding this method.
|
53
53
|
def default_devise_mapping
|
54
|
-
raise NotImplementedError
|
54
|
+
raise NotImplementedError, 'no default_devise_mapping set'
|
55
55
|
end
|
56
56
|
|
57
57
|
def omniauth_success
|
@@ -78,10 +78,11 @@ module DeviseJwtAuth
|
|
78
78
|
render_data_or_redirect('authFailure', error: @error)
|
79
79
|
end
|
80
80
|
|
81
|
-
def validate_auth_origin_url_param
|
82
|
-
return
|
81
|
+
def validate_auth_origin_url_param
|
82
|
+
return unless auth_origin_url && blacklisted_redirect_url?(auth_origin_url)
|
83
|
+
|
84
|
+
render_error_not_allowed_auth_origin_url
|
83
85
|
end
|
84
|
-
|
85
86
|
|
86
87
|
protected
|
87
88
|
|
@@ -95,19 +96,19 @@ module DeviseJwtAuth
|
|
95
96
|
# are added as query params in our monkey patch to OmniAuth in engine.rb
|
96
97
|
def omniauth_params
|
97
98
|
unless defined?(@_omniauth_params)
|
98
|
-
if request.env['omniauth.params']
|
99
|
+
if request.env['omniauth.params']&.any?
|
99
100
|
@_omniauth_params = request.env['omniauth.params']
|
100
|
-
elsif session['dta.omniauth.params']
|
101
|
+
elsif session['dta.omniauth.params']&.any?
|
101
102
|
@_omniauth_params ||= session.delete('dta.omniauth.params')
|
102
103
|
@_omniauth_params
|
103
104
|
elsif params['omniauth_window_type']
|
104
|
-
@_omniauth_params =
|
105
|
+
@_omniauth_params =
|
106
|
+
params.slice('omniauth_window_type', 'auth_origin_url', 'resource_class', 'origin')
|
105
107
|
else
|
106
108
|
@_omniauth_params = {}
|
107
109
|
end
|
108
110
|
end
|
109
111
|
@_omniauth_params
|
110
|
-
|
111
112
|
end
|
112
113
|
|
113
114
|
# break out provider attribute assignment for easy method extension
|
@@ -120,14 +121,13 @@ module DeviseJwtAuth
|
|
120
121
|
def whitelisted_params
|
121
122
|
whitelist = params_for_resource(:sign_up)
|
122
123
|
|
123
|
-
whitelist.
|
124
|
+
whitelist.each_with_object({}) do |key, coll|
|
124
125
|
param = omniauth_params[key.to_s]
|
125
126
|
coll[key] = param if param
|
126
|
-
coll
|
127
127
|
end
|
128
128
|
end
|
129
129
|
|
130
|
-
def resource_class(
|
130
|
+
def resource_class(_mapping = nil)
|
131
131
|
if omniauth_params['resource_class']
|
132
132
|
omniauth_params['resource_class'].constantize
|
133
133
|
elsif params['resource_class']
|
@@ -149,18 +149,18 @@ module DeviseJwtAuth
|
|
149
149
|
omniauth_params['auth_origin_url'] || omniauth_params['origin']
|
150
150
|
end
|
151
151
|
|
152
|
-
|
153
152
|
def auth_origin_url
|
154
|
-
if unsafe_auth_origin_url && blacklisted_redirect_url?(unsafe_auth_origin_url)
|
155
|
-
|
156
|
-
|
157
|
-
return unsafe_auth_origin_url
|
153
|
+
return nil if unsafe_auth_origin_url && blacklisted_redirect_url?(unsafe_auth_origin_url)
|
154
|
+
|
155
|
+
unsafe_auth_origin_url
|
158
156
|
end
|
159
157
|
|
160
158
|
# in the success case, omniauth_window_type is in the omniauth_params.
|
161
159
|
# in the failure case, it is in a query param. See monkey patch above
|
162
160
|
def omniauth_window_type
|
163
|
-
|
161
|
+
return params['omniauth_window_type'] if omniauth_params.nil?
|
162
|
+
|
163
|
+
omniauth_params['omniauth_window_type']
|
164
164
|
end
|
165
165
|
|
166
166
|
# this sesison value is set by the redirect_callbacks method. its purpose
|
@@ -208,7 +208,10 @@ module DeviseJwtAuth
|
|
208
208
|
end
|
209
209
|
|
210
210
|
def render_error_not_allowed_auth_origin_url
|
211
|
-
message =
|
211
|
+
message =
|
212
|
+
I18n.t('devise_jwt_auth.omniauth.not_allowed_redirect_url',
|
213
|
+
redirect_url: unsafe_auth_origin_url)
|
214
|
+
|
212
215
|
render_data_or_redirect('authFailure', error: message)
|
213
216
|
end
|
214
217
|
|
@@ -218,7 +221,6 @@ module DeviseJwtAuth
|
|
218
221
|
end
|
219
222
|
|
220
223
|
def render_data_or_redirect(message, data, user_data = {})
|
221
|
-
|
222
224
|
# We handle inAppBrowser and newWindow the same, but it is nice
|
223
225
|
# to support values in case people need custom implementations for each case
|
224
226
|
# (For example, nbrustein does not allow new users to be created if logging in with
|
@@ -245,7 +247,7 @@ module DeviseJwtAuth
|
|
245
247
|
end
|
246
248
|
|
247
249
|
def fallback_render(text)
|
248
|
-
|
250
|
+
render inline: %(
|
249
251
|
|
250
252
|
<html>
|
251
253
|
<head></head>
|
@@ -271,9 +273,7 @@ module DeviseJwtAuth
|
|
271
273
|
provider: auth_hash['provider']
|
272
274
|
).first_or_initialize
|
273
275
|
|
274
|
-
if @resource.new_record?
|
275
|
-
handle_new_resource
|
276
|
-
end
|
276
|
+
handle_new_resource if @resource.new_record?
|
277
277
|
|
278
278
|
# sync user info with provider, update/generate auth token
|
279
279
|
assign_provider_attrs(@resource, auth_hash)
|
@@ -287,5 +287,4 @@ module DeviseJwtAuth
|
|
287
287
|
@resource
|
288
288
|
end
|
289
289
|
end
|
290
|
-
|
291
290
|
end
|