devise_token_auth 1.0.0 → 1.1.1
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.
Potentially problematic release.
This version of devise_token_auth might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/README.md +4 -2
- data/app/controllers/devise_token_auth/application_controller.rb +0 -1
- data/app/controllers/devise_token_auth/concerns/resource_finder.rb +11 -12
- data/app/controllers/devise_token_auth/concerns/set_user_by_token.rb +39 -55
- data/app/controllers/devise_token_auth/confirmations_controller.rb +62 -20
- data/app/controllers/devise_token_auth/omniauth_callbacks_controller.rb +51 -26
- data/app/controllers/devise_token_auth/passwords_controller.rb +19 -23
- data/app/controllers/devise_token_auth/registrations_controller.rb +32 -40
- data/app/controllers/devise_token_auth/sessions_controller.rb +5 -5
- data/app/controllers/devise_token_auth/unlocks_controller.rb +4 -4
- data/app/models/devise_token_auth/concerns/active_record_support.rb +16 -0
- data/app/models/devise_token_auth/concerns/mongoid_support.rb +19 -0
- data/app/models/devise_token_auth/concerns/tokens_serialization.rb +19 -0
- data/app/models/devise_token_auth/concerns/user.rb +44 -67
- data/app/models/devise_token_auth/concerns/user_omniauth_callbacks.rb +2 -2
- data/app/validators/{email_validator.rb → devise_token_auth_email_validator.rb} +1 -1
- data/config/locales/en.yml +5 -0
- data/config/locales/he.yml +50 -0
- data/config/locales/ja.yml +1 -1
- data/lib/devise_token_auth/blacklist.rb +2 -0
- data/lib/devise_token_auth/engine.rb +2 -0
- data/lib/devise_token_auth/rails/routes.rb +1 -1
- data/lib/devise_token_auth/token_factory.rb +126 -0
- data/lib/devise_token_auth/version.rb +1 -1
- data/lib/devise_token_auth.rb +6 -3
- data/lib/generators/devise_token_auth/install_generator.rb +3 -87
- data/lib/generators/devise_token_auth/install_generator_helpers.rb +98 -0
- data/lib/generators/devise_token_auth/install_mongoid_generator.rb +46 -0
- data/lib/generators/devise_token_auth/templates/devise_token_auth.rb +5 -0
- data/lib/generators/devise_token_auth/templates/devise_token_auth_create_users.rb.erb +0 -7
- data/lib/generators/devise_token_auth/templates/user_mongoid.rb.erb +56 -0
- data/test/controllers/custom/custom_confirmations_controller_test.rb +1 -1
- data/test/controllers/demo_user_controller_test.rb +2 -2
- data/test/controllers/devise_token_auth/confirmations_controller_test.rb +79 -19
- data/test/controllers/devise_token_auth/omniauth_callbacks_controller_test.rb +2 -0
- data/test/controllers/devise_token_auth/passwords_controller_test.rb +115 -94
- data/test/controllers/devise_token_auth/registrations_controller_test.rb +31 -4
- data/test/controllers/devise_token_auth/sessions_controller_test.rb +0 -38
- data/test/controllers/devise_token_auth/token_validations_controller_test.rb +2 -1
- data/test/dummy/app/{models → active_record}/scoped_user.rb +2 -2
- data/test/dummy/app/{models → active_record}/unconfirmable_user.rb +1 -2
- data/test/dummy/app/{models → active_record}/unregisterable_user.rb +3 -3
- data/test/dummy/app/active_record/user.rb +6 -0
- data/test/dummy/app/controllers/overrides/confirmations_controller.rb +3 -3
- data/test/dummy/app/controllers/overrides/passwords_controller.rb +3 -3
- data/test/dummy/app/controllers/overrides/registrations_controller.rb +1 -1
- data/test/dummy/app/controllers/overrides/sessions_controller.rb +2 -2
- data/test/dummy/app/models/{user.rb → concerns/favorite_color.rb} +7 -8
- data/test/dummy/app/mongoid/lockable_user.rb +38 -0
- data/test/dummy/app/mongoid/mang.rb +46 -0
- data/test/dummy/app/mongoid/only_email_user.rb +33 -0
- data/test/dummy/app/mongoid/scoped_user.rb +50 -0
- data/test/dummy/app/mongoid/unconfirmable_user.rb +44 -0
- data/test/dummy/app/mongoid/unregisterable_user.rb +47 -0
- data/test/dummy/app/mongoid/user.rb +49 -0
- data/test/dummy/config/application.rb +23 -1
- data/test/dummy/config/boot.rb +4 -0
- data/test/dummy/config/initializers/devise.rb +285 -0
- data/test/dummy/config/initializers/devise_token_auth.rb +35 -4
- data/test/dummy/db/migrate/20140715061447_devise_token_auth_create_users.rb +0 -7
- data/test/dummy/db/migrate/20140715061805_devise_token_auth_create_mangs.rb +0 -7
- data/test/dummy/db/migrate/20141222035835_devise_token_auth_create_only_email_users.rb +0 -7
- data/test/dummy/db/migrate/20141222053502_devise_token_auth_create_unregisterable_users.rb +0 -7
- data/test/dummy/db/migrate/20150708104536_devise_token_auth_create_unconfirmable_users.rb +0 -7
- data/test/dummy/db/migrate/20160103235141_devise_token_auth_create_scoped_users.rb +0 -7
- data/test/dummy/db/migrate/20160629184441_devise_token_auth_create_lockable_users.rb +0 -7
- data/test/dummy/db/schema.rb +1 -28
- data/test/factories/users.rb +1 -1
- data/test/lib/devise_token_auth/blacklist_test.rb +11 -0
- data/test/lib/devise_token_auth/token_factory_test.rb +191 -0
- data/test/lib/generators/devise_token_auth/install_generator_test.rb +51 -31
- data/test/lib/generators/devise_token_auth/install_generator_with_namespace_test.rb +51 -31
- data/test/models/concerns/mongoid_support_test.rb +31 -0
- data/test/models/concerns/tokens_serialization_test.rb +70 -0
- data/test/models/only_email_user_test.rb +0 -8
- data/test/models/user_test.rb +1 -33
- data/test/test_helper.rb +12 -2
- metadata +105 -25
- data/config/initializers/devise.rb +0 -198
- /data/test/dummy/app/{models → active_record}/lockable_user.rb +0 -0
- /data/test/dummy/app/{models → active_record}/mang.rb +0 -0
- /data/test/dummy/app/{models → active_record}/only_email_user.rb +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 25a0c261827b5f9e1f7dccc40b782a5321d34c50a730fac7bdf9f2c281c397d9
|
4
|
+
data.tar.gz: dfee96bd1789d025ea52a83573d90d0ae784e4c63723d2ea864d17eea8fdbaf3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e68ff8599b70eebdfb2eceab3f76fce22a5cac1976234f485a58363c3821815e541982523f8ff08cd35677e794b507a10c5239c718dd033dc799f5594de0877a
|
7
|
+
data.tar.gz: d48ee0ebfa6a9117f1dbcb96180c4a6d06436ba3b555b75899da653115332fa2e69090cdb11ae8d1df3617f799a3e04547ac12bb45e0d148a49a52ac63b6c072
|
data/README.md
CHANGED
@@ -19,7 +19,7 @@ Also, it maintains a session for each client/device, so you can have as many ses
|
|
19
19
|
|
20
20
|
* Seamless integration with:
|
21
21
|
* [ng-token-auth](https://github.com/lynndylanhurley/ng-token-auth) for [AngularJS](https://github.com/angular/angular.js)
|
22
|
-
* [
|
22
|
+
* [Angular-Token](https://github.com/neroniaky/angular-token) for [Angular](https://github.com/angular/angular)
|
23
23
|
* [redux-token-auth](https://github.com/kylecorbelli/redux-token-auth) for [React with Redux](https://github.com/reactjs/react-redux)
|
24
24
|
* [jToker](https://github.com/lynndylanhurley/j-toker) for [jQuery](https://jquery.com/)
|
25
25
|
* Oauth2 authentication using [OmniAuth](https://github.com/intridea/omniauth).
|
@@ -65,11 +65,13 @@ Please read the [issue template](https://github.com/lynndylanhurley/devise_token
|
|
65
65
|
|
66
66
|
See our [Contribution Guidelines](https://github.com/lynndylanhurley/devise_token_auth/blob/master/.github/CONTRIBUTING.md). Feel free to submit pull requests, review pull requests, or review open issues. If you'd like to get in contact, [Zach Feldman](https://github.com/zachfeldman) has been wrangling this effort, you can reach him with his name @gmail. Further discussion of this in [this issue](https://github.com/lynndylanhurley/devise_token_auth/issues/969).
|
67
67
|
|
68
|
+
We have some bounties for some issues, [check them out](https://github.com/lynndylanhurley/devise_token_auth/issues?q=is%3Aopen+is%3Aissue+label%3Abounty)!
|
69
|
+
|
68
70
|
## Live Demos
|
69
71
|
|
70
72
|
[Here is a demo](http://ng-token-auth-demo.herokuapp.com/) of this app running with the [ng-token-auth](https://github.com/lynndylanhurley/ng-token-auth) module and [AngularJS](https://github.com/angular/angular.js).
|
71
73
|
|
72
|
-
[Here is a demo](https://
|
74
|
+
[Here is a demo](https://stackblitz.com/github/neroniaky/angular-token) of this app running with the [Angular-Token](https://github.com/neroniaky/angular-token) service and [Angular](https://github.com/angular/angular).
|
73
75
|
|
74
76
|
[Here is a demo](https://j-toker-demo.herokuapp.com/) of this app using the [jToker](https://github.com/lynndylanhurley/j-toker) plugin and [React](http://facebook.github.io/react/).
|
75
77
|
|
@@ -3,7 +3,6 @@
|
|
3
3
|
module DeviseTokenAuth
|
4
4
|
class ApplicationController < DeviseController
|
5
5
|
include DeviseTokenAuth::Concerns::SetUserByToken
|
6
|
-
include DeviseTokenAuth::Concerns::ResourceFinder
|
7
6
|
|
8
7
|
def resource_data(opts = {})
|
9
8
|
response_data = opts[:resource_json] || @resource.as_json
|
@@ -20,21 +20,20 @@ module DeviseTokenAuth::Concerns::ResourceFinder
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def find_resource(field, value)
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
@resource = resource_class.where(q, value).first
|
23
|
+
@resource = if resource_class.try(:connection_config).try(:[], :adapter).try(:include?, 'mysql')
|
24
|
+
# fix for mysql default case insensitivity
|
25
|
+
resource_class.where("BINARY #{field} = ? AND provider= ?", value, provider).first
|
26
|
+
else
|
27
|
+
resource_class.dta_find_by(field => value, 'provider' => provider)
|
28
|
+
end
|
30
29
|
end
|
31
30
|
|
32
31
|
def resource_class(m = nil)
|
33
|
-
if m
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
32
|
+
mapping = if m
|
33
|
+
Devise.mappings[m]
|
34
|
+
else
|
35
|
+
Devise.mappings[resource_name] || Devise.mappings.values.first
|
36
|
+
end
|
38
37
|
|
39
38
|
mapping.to
|
40
39
|
end
|
@@ -17,24 +17,11 @@ module DeviseTokenAuth::Concerns::SetUserByToken
|
|
17
17
|
@used_auth_by_token = true
|
18
18
|
|
19
19
|
# initialize instance variables
|
20
|
-
@
|
20
|
+
@token = DeviseTokenAuth::TokenFactory.new
|
21
21
|
@resource ||= nil
|
22
|
-
@token ||= nil
|
23
22
|
@is_batch_request ||= nil
|
24
23
|
end
|
25
24
|
|
26
|
-
def ensure_pristine_resource
|
27
|
-
if @resource.changed?
|
28
|
-
# Stash pending changes in the resource before reloading.
|
29
|
-
changes = @resource.changes
|
30
|
-
@resource.reload
|
31
|
-
end
|
32
|
-
yield
|
33
|
-
ensure
|
34
|
-
# Reapply pending changes
|
35
|
-
@resource.assign_attributes(changes) if changes
|
36
|
-
end
|
37
|
-
|
38
25
|
# user auth
|
39
26
|
def set_user_by_token(mapping = nil)
|
40
27
|
# determine target authentication class
|
@@ -49,17 +36,18 @@ module DeviseTokenAuth::Concerns::SetUserByToken
|
|
49
36
|
client_name = DeviseTokenAuth.headers_names[:'client']
|
50
37
|
|
51
38
|
# parse header for values necessary for authentication
|
52
|
-
uid
|
53
|
-
@token
|
54
|
-
@
|
39
|
+
uid = request.headers[uid_name] || params[uid_name]
|
40
|
+
@token = DeviseTokenAuth::TokenFactory.new unless @token
|
41
|
+
@token.token ||= request.headers[access_token_name] || params[access_token_name]
|
42
|
+
@token.client ||= request.headers[client_name] || params[client_name]
|
55
43
|
|
56
|
-
#
|
57
|
-
@
|
44
|
+
# client isn't required, set to 'default' if absent
|
45
|
+
@token.client ||= 'default'
|
58
46
|
|
59
47
|
# check for an existing user, authenticated via warden/devise, if enabled
|
60
48
|
if DeviseTokenAuth.enable_standard_devise_support
|
61
49
|
devise_warden_user = warden.user(rc.to_s.underscore.to_sym)
|
62
|
-
if devise_warden_user && devise_warden_user.tokens[@
|
50
|
+
if devise_warden_user && devise_warden_user.tokens[@token.client].nil?
|
63
51
|
@used_auth_by_token = false
|
64
52
|
@resource = devise_warden_user
|
65
53
|
# REVIEW: The following line _should_ be safe to remove;
|
@@ -71,46 +59,44 @@ module DeviseTokenAuth::Concerns::SetUserByToken
|
|
71
59
|
# user has already been found and authenticated
|
72
60
|
return @resource if @resource && @resource.is_a?(rc)
|
73
61
|
|
74
|
-
# ensure we clear the
|
75
|
-
unless @token
|
76
|
-
@
|
62
|
+
# ensure we clear the client
|
63
|
+
unless @token.present?
|
64
|
+
@token.client = nil
|
77
65
|
return
|
78
66
|
end
|
79
67
|
|
80
|
-
return false unless @token
|
81
|
-
|
82
68
|
# mitigate timing attacks by finding by uid instead of auth token
|
83
|
-
user = uid && rc.
|
69
|
+
user = uid && rc.dta_find_by(uid: uid)
|
70
|
+
scope = rc.to_s.underscore.to_sym
|
84
71
|
|
85
|
-
if user && user.valid_token?(@token, @
|
72
|
+
if user && user.valid_token?(@token.token, @token.client)
|
86
73
|
# sign_in with bypass: true will be deprecated in the next version of Devise
|
87
74
|
if respond_to?(:bypass_sign_in) && DeviseTokenAuth.bypass_sign_in
|
88
|
-
bypass_sign_in(user, scope:
|
75
|
+
bypass_sign_in(user, scope: scope)
|
89
76
|
else
|
90
|
-
sign_in(
|
77
|
+
sign_in(scope, user, store: false, event: :fetch, bypass: DeviseTokenAuth.bypass_sign_in)
|
91
78
|
end
|
92
79
|
return @resource = user
|
93
80
|
else
|
94
81
|
# zero all values previously set values
|
95
|
-
@
|
82
|
+
@token.client = nil
|
96
83
|
return @resource = nil
|
97
84
|
end
|
98
85
|
end
|
99
86
|
|
100
87
|
def update_auth_header
|
101
88
|
# cannot save object if model has invalid params
|
89
|
+
return unless @resource && @token.client
|
102
90
|
|
103
|
-
|
104
|
-
|
105
|
-
# Generate new client_id with existing authentication
|
106
|
-
@client_id = nil unless @used_auth_by_token
|
91
|
+
# Generate new client with existing authentication
|
92
|
+
@token.client = nil unless @used_auth_by_token
|
107
93
|
|
108
94
|
if @used_auth_by_token && !DeviseTokenAuth.change_headers_on_each_request
|
109
95
|
# should not append auth header if @resource related token was
|
110
96
|
# cleared by sign out in the meantime
|
111
|
-
return if @resource.reload.tokens[@
|
97
|
+
return if @resource.reload.tokens[@token.client].nil?
|
112
98
|
|
113
|
-
auth_header = @resource.build_auth_header(@token, @
|
99
|
+
auth_header = @resource.build_auth_header(@token.token, @token.client)
|
114
100
|
|
115
101
|
# update the response header
|
116
102
|
response.headers.merge!(auth_header)
|
@@ -130,37 +116,35 @@ module DeviseTokenAuth::Concerns::SetUserByToken
|
|
130
116
|
private
|
131
117
|
|
132
118
|
def refresh_headers
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
@resource
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
end # end lock
|
144
|
-
end # end ensure_pristine_resource
|
119
|
+
# Lock the user record during any auth_header updates to ensure
|
120
|
+
# we don't have write contention from multiple threads
|
121
|
+
@resource.with_lock do
|
122
|
+
# should not append auth header if @resource related token was
|
123
|
+
# cleared by sign out in the meantime
|
124
|
+
return if @used_auth_by_token && @resource.tokens[@token.client].nil?
|
125
|
+
|
126
|
+
# update the response header
|
127
|
+
response.headers.merge!(auth_header_from_batch_request)
|
128
|
+
end # end lock
|
145
129
|
end
|
146
130
|
|
147
|
-
def is_batch_request?(user,
|
131
|
+
def is_batch_request?(user, client)
|
148
132
|
!params[:unbatch] &&
|
149
|
-
user.tokens[
|
150
|
-
user.tokens[
|
151
|
-
|
133
|
+
user.tokens[client] &&
|
134
|
+
user.tokens[client]['updated_at'] &&
|
135
|
+
user.tokens[client]['updated_at'].to_time > @request_started_at - DeviseTokenAuth.batch_request_buffer_throttle
|
152
136
|
end
|
153
137
|
|
154
138
|
def auth_header_from_batch_request
|
155
139
|
# determine batch request status after request processing, in case
|
156
140
|
# another processes has updated it during that processing
|
157
|
-
@is_batch_request = is_batch_request?(@resource, @
|
141
|
+
@is_batch_request = is_batch_request?(@resource, @token.client)
|
158
142
|
|
159
143
|
auth_header = {}
|
160
144
|
# extend expiration of batch buffer to account for the duration of
|
161
145
|
# this request
|
162
146
|
if @is_batch_request
|
163
|
-
auth_header = @resource.extend_batch_buffer(@token, @
|
147
|
+
auth_header = @resource.extend_batch_buffer(@token.token, @token.client)
|
164
148
|
|
165
149
|
# Do not return token for batch requests to avoid invalidated
|
166
150
|
# tokens returned to the client in case of race conditions.
|
@@ -171,7 +155,7 @@ module DeviseTokenAuth::Concerns::SetUserByToken
|
|
171
155
|
auth_header[DeviseTokenAuth.headers_names[:"expiry"]] = ' '
|
172
156
|
else
|
173
157
|
# update Authorization response header with new token
|
174
|
-
auth_header = @resource.create_new_auth_token(@
|
158
|
+
auth_header = @resource.create_new_auth_token(@token.client)
|
175
159
|
end
|
176
160
|
auth_header
|
177
161
|
end
|
@@ -2,38 +2,80 @@
|
|
2
2
|
|
3
3
|
module DeviseTokenAuth
|
4
4
|
class ConfirmationsController < DeviseTokenAuth::ApplicationController
|
5
|
-
def show
|
6
|
-
@resource = resource_class.confirm_by_token(params[:confirmation_token])
|
7
|
-
|
8
|
-
if @resource && @resource.id
|
9
|
-
expiry = nil
|
10
|
-
if defined?(@resource.sign_in_count) && @resource.sign_in_count > 0
|
11
|
-
expiry = (Time.zone.now + 1.second).to_i
|
12
|
-
end
|
13
|
-
|
14
|
-
client_id, token = @resource.create_token expiry: expiry
|
15
5
|
|
16
|
-
|
17
|
-
|
6
|
+
def show
|
7
|
+
@resource = resource_class.confirm_by_token(resource_params[:confirmation_token])
|
18
8
|
|
9
|
+
if @resource.errors.empty?
|
19
10
|
yield @resource if block_given?
|
20
11
|
|
21
12
|
redirect_header_options = { account_confirmation_success: true }
|
22
|
-
redirect_headers = build_redirect_headers(token,
|
23
|
-
client_id,
|
24
|
-
redirect_header_options)
|
25
13
|
|
26
|
-
|
27
|
-
|
14
|
+
if signed_in?(resource_name)
|
15
|
+
token = signed_in_resource.create_token
|
28
16
|
|
29
|
-
|
30
|
-
|
17
|
+
redirect_headers = build_redirect_headers(token.token,
|
18
|
+
token.client,
|
19
|
+
redirect_header_options)
|
31
20
|
|
21
|
+
redirect_to_link = signed_in_resource.build_auth_url(redirect_url, redirect_headers)
|
22
|
+
else
|
23
|
+
redirect_to_link = DeviseTokenAuth::Url.generate(redirect_url, redirect_header_options)
|
24
|
+
end
|
32
25
|
|
33
|
-
redirect_to(
|
26
|
+
redirect_to(redirect_to_link)
|
34
27
|
else
|
35
28
|
raise ActionController::RoutingError, 'Not Found'
|
36
29
|
end
|
37
30
|
end
|
31
|
+
|
32
|
+
def create
|
33
|
+
return render_create_error_missing_email if resource_params[:email].blank?
|
34
|
+
|
35
|
+
@email = get_case_insensitive_field_from_resource_params(:email)
|
36
|
+
|
37
|
+
@resource = resource_class.dta_find_by(uid: @email, provider: provider)
|
38
|
+
|
39
|
+
return render_not_found_error unless @resource
|
40
|
+
|
41
|
+
@resource.send_confirmation_instructions({
|
42
|
+
redirect_url: redirect_url,
|
43
|
+
client_config: resource_params[:config_name]
|
44
|
+
})
|
45
|
+
|
46
|
+
return render_create_success
|
47
|
+
end
|
48
|
+
|
49
|
+
protected
|
50
|
+
|
51
|
+
def render_create_error_missing_email
|
52
|
+
render_error(401, I18n.t('devise_token_auth.confirmations.missing_email'))
|
53
|
+
end
|
54
|
+
|
55
|
+
def render_create_success
|
56
|
+
render json: {
|
57
|
+
success: true,
|
58
|
+
message: I18n.t('devise_token_auth.confirmations.sended', email: @email)
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
def render_not_found_error
|
63
|
+
render_error(404, I18n.t('devise_token_auth.confirmations.user_not_found', email: @email))
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def resource_params
|
69
|
+
params.permit(:email, :confirmation_token, :config_name)
|
70
|
+
end
|
71
|
+
|
72
|
+
# give redirect value from params priority or fall back to default value if provided
|
73
|
+
def redirect_url
|
74
|
+
params.fetch(
|
75
|
+
:redirect_url,
|
76
|
+
DeviseTokenAuth.default_confirm_success_url
|
77
|
+
)
|
78
|
+
end
|
79
|
+
|
38
80
|
end
|
39
81
|
end
|
@@ -12,11 +12,8 @@ module DeviseTokenAuth
|
|
12
12
|
|
13
13
|
# derive target redirect route from 'resource_class' param, which was set
|
14
14
|
# before authentication.
|
15
|
-
devise_mapping =
|
16
|
-
|
17
|
-
path = "#{Devise.mappings[devise_mapping.to_sym].fullpath}/#{params[:provider]}/callback"
|
18
|
-
klass = request.scheme == 'https' ? URI::HTTPS : URI::HTTP
|
19
|
-
redirect_route = klass.build(host: request.host, port: request.port, path: path).to_s
|
15
|
+
devise_mapping = get_devise_mapping
|
16
|
+
redirect_route = get_redirect_route(devise_mapping)
|
20
17
|
|
21
18
|
# preserve omniauth info for success route. ignore 'extra' in twitter
|
22
19
|
# auth response to avoid CookieOverflow.
|
@@ -26,6 +23,34 @@ module DeviseTokenAuth
|
|
26
23
|
redirect_to redirect_route
|
27
24
|
end
|
28
25
|
|
26
|
+
def get_redirect_route(devise_mapping)
|
27
|
+
path = "#{Devise.mappings[devise_mapping.to_sym].fullpath}/#{params[:provider]}/callback"
|
28
|
+
klass = request.scheme == 'https' ? URI::HTTPS : URI::HTTP
|
29
|
+
redirect_route = klass.build(host: request.host, port: request.port, path: path).to_s
|
30
|
+
end
|
31
|
+
|
32
|
+
def get_devise_mapping
|
33
|
+
# derive target redirect route from 'resource_class' param, which was set
|
34
|
+
# before authentication.
|
35
|
+
devise_mapping = [request.env['omniauth.params']['namespace_name'],
|
36
|
+
request.env['omniauth.params']['resource_class'].underscore.gsub('/', '_')].compact.join('_')
|
37
|
+
rescue NoMethodError => err
|
38
|
+
default_devise_mapping
|
39
|
+
end
|
40
|
+
|
41
|
+
# This method will only be called if `get_devise_mapping` cannot
|
42
|
+
# find the mapping in `omniauth.params`.
|
43
|
+
#
|
44
|
+
# One example use-case here is for IDP-initiated SAML login. In that
|
45
|
+
# case, there will have been no initial request in which to save
|
46
|
+
# the devise mapping. If you are in a situation like that, and
|
47
|
+
# your app allows for you to determine somehow what the devise
|
48
|
+
# mapping should be (because, for example, it is always the same),
|
49
|
+
# then you can handle it by overriding this method.
|
50
|
+
def default_devise_mapping
|
51
|
+
raise NotImplementedError.new('no default_devise_mapping set')
|
52
|
+
end
|
53
|
+
|
29
54
|
def omniauth_success
|
30
55
|
get_resource_from_auth_hash
|
31
56
|
set_token_on_resource
|
@@ -79,7 +104,7 @@ module DeviseTokenAuth
|
|
79
104
|
|
80
105
|
# break out provider attribute assignment for easy method extension
|
81
106
|
def assign_provider_attrs(user, auth_hash)
|
82
|
-
attrs = auth_hash['info'].slice(*user.
|
107
|
+
attrs = auth_hash['info'].slice(*user.attribute_names)
|
83
108
|
user.assign_attributes(attrs)
|
84
109
|
end
|
85
110
|
|
@@ -136,16 +161,6 @@ module DeviseTokenAuth
|
|
136
161
|
true
|
137
162
|
end
|
138
163
|
|
139
|
-
# necessary for access to devise_parameter_sanitizers
|
140
|
-
def devise_mapping
|
141
|
-
if omniauth_params
|
142
|
-
Devise.mappings[[omniauth_params['namespace_name'],
|
143
|
-
omniauth_params['resource_class'].underscore].compact.join('_').to_sym]
|
144
|
-
else
|
145
|
-
request.env['devise.mapping']
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
164
|
def set_random_password
|
150
165
|
# set crazy password for new oauth users. this is only used to prevent
|
151
166
|
# access via email sign-in.
|
@@ -156,11 +171,11 @@ module DeviseTokenAuth
|
|
156
171
|
|
157
172
|
def create_auth_params
|
158
173
|
@auth_params = {
|
159
|
-
auth_token:
|
160
|
-
client_id:
|
161
|
-
uid:
|
162
|
-
expiry:
|
163
|
-
config:
|
174
|
+
auth_token: @token.token,
|
175
|
+
client_id: @token.client,
|
176
|
+
uid: @resource.uid,
|
177
|
+
expiry: @token.expiry,
|
178
|
+
config: @config
|
164
179
|
}
|
165
180
|
@auth_params.merge!(oauth_registration: true) if @oauth_registration
|
166
181
|
@auth_params
|
@@ -168,7 +183,7 @@ module DeviseTokenAuth
|
|
168
183
|
|
169
184
|
def set_token_on_resource
|
170
185
|
@config = omniauth_params['config_name']
|
171
|
-
@
|
186
|
+
@token = @resource.create_token
|
172
187
|
end
|
173
188
|
|
174
189
|
def render_data(message, data)
|
@@ -214,6 +229,15 @@ module DeviseTokenAuth
|
|
214
229
|
</html>)
|
215
230
|
end
|
216
231
|
|
232
|
+
def handle_new_resource
|
233
|
+
@oauth_registration = true
|
234
|
+
set_random_password
|
235
|
+
end
|
236
|
+
|
237
|
+
def assign_whitelisted_params?
|
238
|
+
true
|
239
|
+
end
|
240
|
+
|
217
241
|
def get_resource_from_auth_hash
|
218
242
|
# find or create user by provider and provider uid
|
219
243
|
@resource = resource_class.where(
|
@@ -222,16 +246,17 @@ module DeviseTokenAuth
|
|
222
246
|
).first_or_initialize
|
223
247
|
|
224
248
|
if @resource.new_record?
|
225
|
-
|
226
|
-
set_random_password
|
249
|
+
handle_new_resource
|
227
250
|
end
|
228
251
|
|
229
252
|
# sync user info with provider, update/generate auth token
|
230
253
|
assign_provider_attrs(@resource, auth_hash)
|
231
254
|
|
232
255
|
# assign any additional (whitelisted) attributes
|
233
|
-
|
234
|
-
|
256
|
+
if assign_whitelisted_params?
|
257
|
+
extra_params = whitelisted_params
|
258
|
+
@resource.assign_attributes(extra_params) if extra_params
|
259
|
+
end
|
235
260
|
|
236
261
|
@resource
|
237
262
|
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
module DeviseTokenAuth
|
4
4
|
class PasswordsController < DeviseTokenAuth::ApplicationController
|
5
5
|
before_action :set_user_by_token, only: [:update]
|
6
|
+
before_action :validate_redirect_url_param, only: [:create, :edit]
|
6
7
|
skip_after_action :update_auth_header, only: [:create, :edit]
|
7
8
|
|
8
9
|
# this action is responsible for generating password reset tokens and
|
@@ -10,15 +11,6 @@ module DeviseTokenAuth
|
|
10
11
|
def create
|
11
12
|
return render_create_error_missing_email unless resource_params[:email]
|
12
13
|
|
13
|
-
# give redirect value from params priority
|
14
|
-
@redirect_url = params.fetch(
|
15
|
-
:redirect_url,
|
16
|
-
DeviseTokenAuth.default_password_reset_url
|
17
|
-
)
|
18
|
-
|
19
|
-
return render_create_error_missing_redirect_url unless @redirect_url
|
20
|
-
return render_create_error_not_allowed_redirect_url if blacklisted_redirect_url?
|
21
|
-
|
22
14
|
@email = get_case_insensitive_field_from_resource_params(:email)
|
23
15
|
@resource = find_resource(:uid, @email)
|
24
16
|
|
@@ -44,10 +36,10 @@ module DeviseTokenAuth
|
|
44
36
|
# this is where users arrive after visiting the password reset confirmation link
|
45
37
|
def edit
|
46
38
|
# if a user is not found, return nil
|
47
|
-
@resource = with_reset_password_token(resource_params[:reset_password_token])
|
39
|
+
@resource = resource_class.with_reset_password_token(resource_params[:reset_password_token])
|
48
40
|
|
49
41
|
if @resource && @resource.reset_password_period_valid?
|
50
|
-
|
42
|
+
token = @resource.create_token
|
51
43
|
|
52
44
|
# ensure that user is confirmed
|
53
45
|
@resource.skip_confirmation! if confirmable_enabled? && !@resource.confirmed_at
|
@@ -60,10 +52,10 @@ module DeviseTokenAuth
|
|
60
52
|
yield @resource if block_given?
|
61
53
|
|
62
54
|
redirect_header_options = { reset_password: true }
|
63
|
-
redirect_headers = build_redirect_headers(token,
|
64
|
-
|
55
|
+
redirect_headers = build_redirect_headers(token.token,
|
56
|
+
token.client,
|
65
57
|
redirect_header_options)
|
66
|
-
redirect_to(@resource.build_auth_url(
|
58
|
+
redirect_to(@resource.build_auth_url(@redirect_url,
|
67
59
|
redirect_headers))
|
68
60
|
else
|
69
61
|
render_edit_error
|
@@ -100,7 +92,7 @@ module DeviseTokenAuth
|
|
100
92
|
def resource_update_method
|
101
93
|
allow_password_change = recoverable_enabled? && @resource.allow_password_change == true
|
102
94
|
if DeviseTokenAuth.check_current_password_before_update == false || allow_password_change
|
103
|
-
'
|
95
|
+
'update'
|
104
96
|
else
|
105
97
|
'update_with_password'
|
106
98
|
end
|
@@ -114,7 +106,7 @@ module DeviseTokenAuth
|
|
114
106
|
render_error(401, I18n.t('devise_token_auth.passwords.missing_redirect_url'))
|
115
107
|
end
|
116
108
|
|
117
|
-
def
|
109
|
+
def render_error_not_allowed_redirect_url
|
118
110
|
response = {
|
119
111
|
status: 'error',
|
120
112
|
data: resource_data
|
@@ -178,15 +170,19 @@ module DeviseTokenAuth
|
|
178
170
|
params.permit(*params_for_resource(:account_update))
|
179
171
|
end
|
180
172
|
|
181
|
-
def with_reset_password_token token
|
182
|
-
recoverable = resource_class.with_reset_password_token(token)
|
183
|
-
|
184
|
-
recoverable.reset_password_token = token if recoverable && recoverable.reset_password_token.present?
|
185
|
-
recoverable
|
186
|
-
end
|
187
|
-
|
188
173
|
def render_not_found_error
|
189
174
|
render_error(404, I18n.t('devise_token_auth.passwords.user_not_found', email: @email))
|
190
175
|
end
|
176
|
+
|
177
|
+
def validate_redirect_url_param
|
178
|
+
# give redirect value from params priority
|
179
|
+
@redirect_url = params.fetch(
|
180
|
+
:redirect_url,
|
181
|
+
DeviseTokenAuth.default_password_reset_url
|
182
|
+
)
|
183
|
+
|
184
|
+
return render_create_error_missing_redirect_url unless @redirect_url
|
185
|
+
return render_error_not_allowed_redirect_url if blacklisted_redirect_url?
|
186
|
+
end
|
191
187
|
end
|
192
188
|
end
|