devise_jwt_auth 0.1.4 → 0.2.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 +1 -1
- data/app/controllers/devise_jwt_auth/application_controller.rb +11 -22
- data/app/controllers/devise_jwt_auth/concerns/resource_finder.rb +3 -7
- data/app/controllers/devise_jwt_auth/concerns/set_user_by_token.rb +22 -18
- data/app/controllers/devise_jwt_auth/confirmations_controller.rb +10 -19
- data/app/controllers/devise_jwt_auth/omniauth_callbacks_controller.rb +38 -46
- data/app/controllers/devise_jwt_auth/passwords_controller.rb +34 -36
- 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 -14
- 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 -11
- data/app/models/devise_jwt_auth/concerns/user_omniauth_callbacks.rb +11 -3
- data/app/validators/devise_jwt_auth_email_validator.rb +12 -2
- data/app/views/devise/mailer/reset_password_instructions.html.erb +1 -1
- data/lib/devise_jwt_auth/blacklist.rb +3 -1
- 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/USAGE +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 +6 -7
- 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_omniauth_callbacks_controller_test.rb +1 -1
- data/test/controllers/custom/custom_passwords_controller_test.rb +8 -8
- 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_group_controller_test.rb +0 -24
- data/test/controllers/demo_mang_controller_test.rb +4 -224
- data/test/controllers/demo_user_controller_test.rb +6 -432
- data/test/controllers/devise_jwt_auth/confirmations_controller_test.rb +5 -5
- data/test/controllers/devise_jwt_auth/omniauth_callbacks_controller_test.rb +9 -10
- data/test/controllers/devise_jwt_auth/passwords_controller_test.rb +34 -35
- data/test/controllers/devise_jwt_auth/refresh_token_controller_test.rb +8 -12
- data/test/controllers/devise_jwt_auth/registrations_controller_test.rb +12 -26
- 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 -6
- 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/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 +3 -16
- data/test/dummy/app/controllers/overrides/omniauth_callbacks_controller.rb +4 -4
- data/test/dummy/app/controllers/overrides/passwords_controller.rb +4 -16
- 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/application.rb +1 -0
- data/test/dummy/config/boot.rb +1 -1
- data/test/dummy/config/environments/development.rb +2 -2
- data/test/dummy/config/environments/test.rb +11 -7
- data/test/dummy/config/initializers/devise_jwt_auth.rb +1 -0
- data/test/dummy/config/initializers/figaro.rb +1 -1
- data/test/dummy/config/initializers/omniauth.rb +2 -2
- data/test/dummy/config/routes.rb +10 -8
- data/test/dummy/config.ru +2 -2
- data/test/dummy/db/migrate/20141222035835_devise_jwt_auth_create_only_email_users.rb +9 -9
- data/test/dummy/db/migrate/20190924101113_devise_jwt_auth_create_confirmable_users.rb +6 -5
- data/test/dummy/db/schema.rb +170 -170
- data/test/dummy/tmp/generators/app/models/user.rb +8 -0
- data/test/dummy/tmp/generators/config/initializers/devise_jwt_auth.rb +6 -7
- data/test/dummy/tmp/generators/db/migrate/{20200210193225_devise_jwt_auth_create_azpire_v1_human_resource_users.rb → 20220123023137_devise_jwt_auth_create_users.rb} +20 -17
- data/test/factories/users.rb +5 -3
- data/test/lib/devise_jwt_auth/blacklist_test.rb +2 -2
- data/test/lib/devise_jwt_auth/token_factory_test.rb +7 -7
- 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 +0 -38
- data/test/support/controllers/routes.rb +7 -5
- data/test/test_helper.rb +1 -1
- metadata +45 -71
- data/test/dummy/tmp/generators/app/models/azpire/v1/human_resource/user.rb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f4dbb49ae0d62dcc2e5b23374e972178509d1e936c1246d85828631ceb07b65a
|
4
|
+
data.tar.gz: d4d15235f408dce8fd1c2107007ea4fbf2e48e0ab01315cba67b9f4451fffd92
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a46230b6210496f7ee97b54a357aaf6c36625a7083f33440cf02371914a11bb44329da3516df8b0d6d1bd4524b474715577fc430431d001ef9b6b1bf3b70035e
|
7
|
+
data.tar.gz: bbea37a5d6460fefb600d084d387045d9fefbc14196bdfd23d31d0ae2d8cdb89538d1250781d7a69a379b86a3255397e913610a0d18d30e193220b77ebd6e791
|
data/README.md
CHANGED
@@ -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
|
|
@@ -20,20 +20,6 @@ module DeviseJwtAuth
|
|
20
20
|
DeviseJwtAuth.redirect_whitelist && !DeviseJwtAuth::Url.whitelisted?(redirect_url)
|
21
21
|
end
|
22
22
|
|
23
|
-
def build_redirect_headers(access_token, client, redirect_header_options = {})
|
24
|
-
{
|
25
|
-
# DeviseJwtAuth.headers_names[:"access-token"] => access_token,
|
26
|
-
# DeviseJwtAuth.headers_names[:"client"] => client,
|
27
|
-
:config => params[:config],
|
28
|
-
|
29
|
-
# Legacy parameters which may be removed in a future release.
|
30
|
-
# Consider using "client" and "access-token" in client code.
|
31
|
-
# See: github.com/lynndylanhurley/devise_jwt_auth/issues/993
|
32
|
-
# :client_id => client,
|
33
|
-
:token => access_token
|
34
|
-
}.merge(redirect_header_options)
|
35
|
-
end
|
36
|
-
|
37
23
|
def params_for_resource(resource)
|
38
24
|
devise_parameter_sanitizer.instance_values['permitted'][resource].each do |type|
|
39
25
|
params[type.to_s] ||= request.headers[type.to_s] unless request.headers[type.to_s].nil?
|
@@ -42,20 +28,23 @@ module DeviseJwtAuth
|
|
42
28
|
end
|
43
29
|
|
44
30
|
def resource_class(m = nil)
|
45
|
-
if m
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
31
|
+
mapping = if m
|
32
|
+
Devise.mappings[m]
|
33
|
+
else
|
34
|
+
Devise.mappings[resource_name] || Devise.mappings.values.first
|
35
|
+
end
|
50
36
|
|
51
37
|
mapping.to
|
52
38
|
end
|
53
39
|
|
54
40
|
def json_api?
|
55
41
|
return false unless defined?(ActiveModel::Serializer)
|
56
|
-
|
57
|
-
|
58
|
-
|
42
|
+
|
43
|
+
if ActiveModel::Serializer.respond_to?(:setup)
|
44
|
+
return ActiveModel::Serializer.setup do |config|
|
45
|
+
config.adapter == :json_api
|
46
|
+
end
|
47
|
+
end
|
59
48
|
ActiveModelSerializers.config.adapter == :json_api
|
60
49
|
end
|
61
50
|
|
@@ -8,19 +8,15 @@ 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
|
21
17
|
|
22
18
|
def find_resource(field, value)
|
23
|
-
@resource = if resource_class.try(:
|
19
|
+
@resource = if resource_class.try(:connection_db_config).try(:[], :adapter).try(:include?, 'mysql')
|
24
20
|
# fix for mysql default case insensitivity
|
25
21
|
resource_class.where("BINARY #{field} = ? AND provider= ?", value, provider).first
|
26
22
|
else
|
@@ -5,7 +5,6 @@ module DeviseJwtAuth::Concerns::SetUserByToken
|
|
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::SetUserByToken
|
|
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::SetUserByToken
|
|
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::SetUserByToken
|
|
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::SetUserByToken
|
|
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::SetUserByToken
|
|
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::SetUserByToken
|
|
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::SetUserByToken
|
|
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
|
@@ -20,8 +18,8 @@ module DeviseJwtAuth
|
|
20
18
|
|
21
19
|
# preserve omniauth info for success route. ignore 'extra' in twitter
|
22
20
|
# auth response to avoid CookieOverflow.
|
23
|
-
session['
|
24
|
-
session['
|
21
|
+
session['dja.omniauth.auth'] = request.env['omniauth.auth'].except('extra')
|
22
|
+
session['dja.omniauth.params'] = request.env['omniauth.params']
|
25
23
|
|
26
24
|
redirect_to redirect_route
|
27
25
|
end
|
@@ -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
|
|
@@ -89,25 +90,25 @@ module DeviseJwtAuth
|
|
89
90
|
# it. redirect_callbacks is called upon returning from successful omniauth
|
90
91
|
# authentication, and the target params live in an omniauth-specific
|
91
92
|
# request.env variable. this variable is then persisted thru the redirect
|
92
|
-
# using our own
|
93
|
+
# using our own dja.omniauth.params session var. the omniauth_success
|
93
94
|
# method will access that session var and then destroy it immediately
|
94
95
|
# after use. In the failure case, finally, the omniauth params
|
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['
|
101
|
-
@_omniauth_params ||= session.delete('
|
101
|
+
elsif session['dja.omniauth.params']&.any?
|
102
|
+
@_omniauth_params ||= session.delete('dja.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,25 +149,25 @@ 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
|
-
# this
|
166
|
+
# this session value is set by the redirect_callbacks method. its purpose
|
167
167
|
# is to persist the omniauth auth hash value thru a redirect. the value
|
168
168
|
# must be destroyed immediatly after it is accessed by omniauth_success
|
169
169
|
def auth_hash
|
170
|
-
@_auth_hash ||= session.delete('
|
170
|
+
@_auth_hash ||= session.delete('dja.omniauth.auth')
|
171
171
|
@_auth_hash
|
172
172
|
end
|
173
173
|
|
@@ -190,13 +190,6 @@ module DeviseJwtAuth
|
|
190
190
|
config: @config,
|
191
191
|
uid: @resource.uid
|
192
192
|
)
|
193
|
-
# @auth_params = {
|
194
|
-
# auth_token: @token.token,
|
195
|
-
# client_id: @token.client,
|
196
|
-
# uid: @resource.uid,
|
197
|
-
# expiry: @token.expiry,
|
198
|
-
# config: @config
|
199
|
-
# }
|
200
193
|
@auth_params.merge!(oauth_registration: true) if @oauth_registration
|
201
194
|
@auth_params
|
202
195
|
end
|
@@ -208,7 +201,10 @@ module DeviseJwtAuth
|
|
208
201
|
end
|
209
202
|
|
210
203
|
def render_error_not_allowed_auth_origin_url
|
211
|
-
message =
|
204
|
+
message =
|
205
|
+
I18n.t('devise_jwt_auth.omniauth.not_allowed_redirect_url',
|
206
|
+
redirect_url: unsafe_auth_origin_url)
|
207
|
+
|
212
208
|
render_data_or_redirect('authFailure', error: message)
|
213
209
|
end
|
214
210
|
|
@@ -218,7 +214,6 @@ module DeviseJwtAuth
|
|
218
214
|
end
|
219
215
|
|
220
216
|
def render_data_or_redirect(message, data, user_data = {})
|
221
|
-
|
222
217
|
# We handle inAppBrowser and newWindow the same, but it is nice
|
223
218
|
# to support values in case people need custom implementations for each case
|
224
219
|
# (For example, nbrustein does not allow new users to be created if logging in with
|
@@ -245,7 +240,7 @@ module DeviseJwtAuth
|
|
245
240
|
end
|
246
241
|
|
247
242
|
def fallback_render(text)
|
248
|
-
|
243
|
+
render inline: %(
|
249
244
|
|
250
245
|
<html>
|
251
246
|
<head></head>
|
@@ -271,9 +266,7 @@ module DeviseJwtAuth
|
|
271
266
|
provider: auth_hash['provider']
|
272
267
|
).first_or_initialize
|
273
268
|
|
274
|
-
if @resource.new_record?
|
275
|
-
handle_new_resource
|
276
|
-
end
|
269
|
+
handle_new_resource if @resource.new_record?
|
277
270
|
|
278
271
|
# sync user info with provider, update/generate auth token
|
279
272
|
assign_provider_attrs(@resource, auth_hash)
|
@@ -287,5 +280,4 @@ module DeviseJwtAuth
|
|
287
280
|
@resource
|
288
281
|
end
|
289
282
|
end
|
290
|
-
|
291
283
|
end
|
@@ -3,9 +3,8 @@
|
|
3
3
|
module DeviseJwtAuth
|
4
4
|
class PasswordsController < DeviseJwtAuth::ApplicationController
|
5
5
|
before_action :validate_redirect_url_param, only: [:create, :edit]
|
6
|
-
# skip_after_action :update_auth_header, only: [:create, :edit]
|
7
6
|
|
8
|
-
#
|
7
|
+
# This action is responsible for generating password reset tokens and sending emails
|
9
8
|
def create
|
10
9
|
return render_create_error_missing_email unless resource_params[:email]
|
11
10
|
|
@@ -17,12 +16,11 @@ module DeviseJwtAuth
|
|
17
16
|
@resource.send_reset_password_instructions(
|
18
17
|
email: @email,
|
19
18
|
provider: 'email',
|
20
|
-
redirect_url: @redirect_url
|
21
|
-
client_config: params[:config_name]
|
19
|
+
redirect_url: @redirect_url
|
22
20
|
)
|
23
21
|
|
24
22
|
if @resource.errors.empty?
|
25
|
-
|
23
|
+
render_create_success
|
26
24
|
else
|
27
25
|
render_create_error @resource.errors
|
28
26
|
end
|
@@ -31,17 +29,14 @@ module DeviseJwtAuth
|
|
31
29
|
end
|
32
30
|
end
|
33
31
|
|
34
|
-
#
|
32
|
+
# This is where users arrive after visiting the password reset confirmation link.
|
35
33
|
def edit
|
36
|
-
# if a user is not found, return nil
|
37
34
|
@resource = resource_class.with_reset_password_token(resource_params[:reset_password_token])
|
38
35
|
|
39
|
-
if @resource
|
40
|
-
# TODO: add a token invalidator
|
41
|
-
# token = @resource.create_token unless require_client_password_reset_token?
|
42
|
-
|
36
|
+
if @resource&.reset_password_period_valid?
|
43
37
|
# ensure that user is confirmed
|
44
38
|
@resource.skip_confirmation! if confirmable_enabled? && !@resource.confirmed_at
|
39
|
+
|
45
40
|
# allow user to change password once without current_password
|
46
41
|
@resource.allow_password_change = true if recoverable_enabled?
|
47
42
|
@resource.save!
|
@@ -49,19 +44,16 @@ module DeviseJwtAuth
|
|
49
44
|
yield @resource if block_given?
|
50
45
|
|
51
46
|
if require_client_password_reset_token?
|
52
|
-
|
53
|
-
else
|
54
|
-
redirect_header_options = { reset_password: true }
|
55
|
-
redirect_headers = @resource.create_named_token_pair.
|
56
|
-
merge(redirect_header_options)
|
47
|
+
clear_refresh_token_cookie
|
57
48
|
|
49
|
+
redirect_to DeviseJwtAuth::Url.generate(
|
50
|
+
@redirect_url,
|
51
|
+
reset_password_token: resource_params[:reset_password_token]
|
52
|
+
)
|
53
|
+
else
|
58
54
|
# TODO: do we put the refresh token here?
|
59
|
-
# we do if token exists (see line 41)
|
60
55
|
update_refresh_token_cookie
|
61
|
-
|
62
|
-
redirect_to_link = DeviseJwtAuth::Url.generate(@redirect_url, redirect_headers)
|
63
|
-
|
64
|
-
redirect_to redirect_to_link
|
56
|
+
redirect_to @redirect_url
|
65
57
|
end
|
66
58
|
else
|
67
59
|
render_edit_error
|
@@ -69,12 +61,11 @@ module DeviseJwtAuth
|
|
69
61
|
end
|
70
62
|
|
71
63
|
def update
|
72
|
-
#
|
64
|
+
# Make sure user is authorized. Either by a reset_password_token or a valid access token.
|
73
65
|
if require_client_password_reset_token? && resource_params[:reset_password_token]
|
74
66
|
@resource = resource_class.with_reset_password_token(resource_params[:reset_password_token])
|
75
|
-
return render_update_error_unauthorized unless @resource
|
76
67
|
|
77
|
-
|
68
|
+
return render_update_error_unauthorized unless @resource
|
78
69
|
else
|
79
70
|
@resource = set_user_by_token
|
80
71
|
end
|
@@ -82,9 +73,7 @@ module DeviseJwtAuth
|
|
82
73
|
return render_update_error_unauthorized unless @resource
|
83
74
|
|
84
75
|
# make sure account doesn't use oauth2 provider
|
85
|
-
unless @resource.provider == 'email'
|
86
|
-
return render_update_error_password_not_required
|
87
|
-
end
|
76
|
+
return render_update_error_password_not_required unless @resource.provider == 'email'
|
88
77
|
|
89
78
|
# ensure that password params were sent
|
90
79
|
unless password_resource_params[:password] && password_resource_params[:password_confirmation]
|
@@ -100,16 +89,20 @@ module DeviseJwtAuth
|
|
100
89
|
# send refresh cookie
|
101
90
|
# send access token
|
102
91
|
update_refresh_token_cookie
|
103
|
-
|
92
|
+
render_update_success
|
104
93
|
else
|
105
|
-
|
94
|
+
render_update_error
|
106
95
|
end
|
107
96
|
end
|
108
97
|
|
109
98
|
protected
|
110
99
|
|
111
100
|
def resource_update_method
|
112
|
-
allow_password_change =
|
101
|
+
allow_password_change =
|
102
|
+
recoverable_enabled? &&
|
103
|
+
@resource.allow_password_change == true ||
|
104
|
+
require_client_password_reset_token?
|
105
|
+
|
113
106
|
if DeviseJwtAuth.check_current_password_before_update == false || allow_password_change
|
114
107
|
'update'
|
115
108
|
else
|
@@ -128,9 +121,10 @@ module DeviseJwtAuth
|
|
128
121
|
def render_error_not_allowed_redirect_url
|
129
122
|
response = {
|
130
123
|
status: 'error',
|
131
|
-
data:
|
124
|
+
data: resource_data
|
132
125
|
}
|
133
|
-
message = I18n.t('devise_jwt_auth.passwords.not_allowed_redirect_url',
|
126
|
+
message = I18n.t('devise_jwt_auth.passwords.not_allowed_redirect_url',
|
127
|
+
redirect_url: @redirect_url)
|
134
128
|
render_error(422, message, response)
|
135
129
|
end
|
136
130
|
|
@@ -157,7 +151,8 @@ module DeviseJwtAuth
|
|
157
151
|
end
|
158
152
|
|
159
153
|
def render_update_error_password_not_required
|
160
|
-
render_error(422, I18n.t('devise_jwt_auth.passwords.password_not_required',
|
154
|
+
render_error(422, I18n.t('devise_jwt_auth.passwords.password_not_required',
|
155
|
+
provider: @resource.provider.humanize))
|
161
156
|
end
|
162
157
|
|
163
158
|
def render_update_error_missing_password
|
@@ -170,7 +165,7 @@ module DeviseJwtAuth
|
|
170
165
|
data: resource_data,
|
171
166
|
message: I18n.t('devise_jwt_auth.passwords.successfully_updated')
|
172
167
|
}.merge!(@resource.create_named_token_pair)
|
173
|
-
|
168
|
+
|
174
169
|
render json: response_body
|
175
170
|
end
|
176
171
|
|
@@ -203,11 +198,14 @@ module DeviseJwtAuth
|
|
203
198
|
)
|
204
199
|
|
205
200
|
return render_create_error_missing_redirect_url unless @redirect_url
|
206
|
-
|
201
|
+
|
202
|
+
render_error_not_allowed_redirect_url if blacklisted_redirect_url?(@redirect_url)
|
207
203
|
end
|
208
204
|
|
209
205
|
def reset_password_token_as_raw?(recoverable)
|
210
|
-
recoverable &&
|
206
|
+
recoverable &&
|
207
|
+
recoverable.reset_password_token.present? &&
|
208
|
+
!require_client_password_reset_token?
|
211
209
|
end
|
212
210
|
|
213
211
|
def require_client_password_reset_token?
|