devise_token_auth 1.1.0 → 1.1.5

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.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -0
  3. data/app/controllers/devise_token_auth/application_controller.rb +2 -2
  4. data/app/controllers/devise_token_auth/concerns/set_user_by_token.rb +28 -31
  5. data/app/controllers/devise_token_auth/confirmations_controller.rb +55 -7
  6. data/app/controllers/devise_token_auth/omniauth_callbacks_controller.rb +34 -11
  7. data/app/controllers/devise_token_auth/passwords_controller.rb +32 -14
  8. data/app/controllers/devise_token_auth/registrations_controller.rb +6 -5
  9. data/app/controllers/devise_token_auth/sessions_controller.rb +5 -5
  10. data/app/controllers/devise_token_auth/unlocks_controller.rb +3 -3
  11. data/app/models/devise_token_auth/concerns/active_record_support.rb +1 -21
  12. data/app/models/devise_token_auth/concerns/confirmable_support.rb +28 -0
  13. data/app/models/devise_token_auth/concerns/tokens_serialization.rb +31 -0
  14. data/app/models/devise_token_auth/concerns/user.rb +43 -48
  15. data/app/models/devise_token_auth/concerns/user_omniauth_callbacks.rb +5 -2
  16. data/app/validators/{devise_token_auth/email_validator.rb → devise_token_auth_email_validator.rb} +2 -2
  17. data/config/locales/da-DK.yml +2 -0
  18. data/config/locales/de.yml +2 -0
  19. data/config/locales/en.yml +7 -0
  20. data/config/locales/es.yml +2 -0
  21. data/config/locales/fr.yml +2 -0
  22. data/config/locales/he.yml +2 -0
  23. data/config/locales/it.yml +2 -0
  24. data/config/locales/ja.yml +3 -1
  25. data/config/locales/ko.yml +51 -0
  26. data/config/locales/nl.yml +2 -0
  27. data/config/locales/pl.yml +6 -3
  28. data/config/locales/pt-BR.yml +2 -0
  29. data/config/locales/pt.yml +6 -3
  30. data/config/locales/ro.yml +2 -0
  31. data/config/locales/ru.yml +2 -0
  32. data/config/locales/sq.yml +2 -0
  33. data/config/locales/sv.yml +2 -0
  34. data/config/locales/uk.yml +2 -0
  35. data/config/locales/vi.yml +2 -0
  36. data/config/locales/zh-CN.yml +2 -0
  37. data/config/locales/zh-HK.yml +2 -0
  38. data/config/locales/zh-TW.yml +2 -0
  39. data/lib/devise_token_auth.rb +1 -0
  40. data/lib/devise_token_auth/controllers/helpers.rb +5 -9
  41. data/lib/devise_token_auth/engine.rb +7 -1
  42. data/lib/devise_token_auth/rails/routes.rb +16 -11
  43. data/lib/devise_token_auth/token_factory.rb +126 -0
  44. data/lib/devise_token_auth/url.rb +3 -0
  45. data/lib/devise_token_auth/version.rb +1 -1
  46. data/lib/generators/devise_token_auth/USAGE +1 -1
  47. data/lib/generators/devise_token_auth/install_generator.rb +4 -4
  48. data/lib/generators/devise_token_auth/install_mongoid_generator.rb +2 -2
  49. data/lib/generators/devise_token_auth/templates/devise_token_auth.rb +10 -0
  50. data/lib/generators/devise_token_auth/templates/devise_token_auth_create_users.rb.erb +1 -1
  51. data/lib/generators/devise_token_auth/templates/user.rb.erb +2 -2
  52. data/lib/generators/devise_token_auth/templates/user_mongoid.rb.erb +2 -2
  53. data/test/controllers/demo_user_controller_test.rb +2 -2
  54. data/test/controllers/devise_token_auth/confirmations_controller_test.rb +43 -0
  55. data/test/controllers/devise_token_auth/omniauth_callbacks_controller_test.rb +107 -42
  56. data/test/controllers/devise_token_auth/passwords_controller_test.rb +112 -8
  57. data/test/controllers/devise_token_auth/registrations_controller_test.rb +3 -3
  58. data/test/dummy/app/active_record/confirmable_user.rb +11 -0
  59. data/test/dummy/app/controllers/overrides/confirmations_controller.rb +3 -3
  60. data/test/dummy/app/controllers/overrides/passwords_controller.rb +3 -3
  61. data/test/dummy/app/controllers/overrides/registrations_controller.rb +1 -1
  62. data/test/dummy/app/controllers/overrides/sessions_controller.rb +1 -1
  63. data/test/dummy/app/mongoid/confirmable_user.rb +52 -0
  64. data/test/dummy/app/views/layouts/application.html.erb +0 -2
  65. data/test/dummy/config/application.rb +0 -1
  66. data/test/dummy/config/environments/development.rb +0 -10
  67. data/test/dummy/config/environments/production.rb +0 -16
  68. data/test/dummy/config/initializers/devise.rb +275 -2
  69. data/test/dummy/config/initializers/devise_token_auth.rb +35 -4
  70. data/test/dummy/config/initializers/figaro.rb +1 -1
  71. data/test/dummy/config/initializers/omniauth.rb +1 -0
  72. data/test/dummy/config/routes.rb +2 -0
  73. data/test/dummy/db/migrate/20190924101113_devise_token_auth_create_confirmable_users.rb +49 -0
  74. data/test/dummy/db/schema.rb +26 -1
  75. data/test/dummy/tmp/generators/app/models/azpire/v1/human_resource/user.rb +2 -2
  76. data/test/dummy/tmp/generators/config/initializers/devise_token_auth.rb +10 -0
  77. data/test/dummy/tmp/generators/db/migrate/{20190112150327_devise_token_auth_create_azpire_v1_human_resource_users.rb → 20210126004321_devise_token_auth_create_azpire_v1_human_resource_users.rb} +1 -8
  78. data/test/factories/users.rb +3 -2
  79. data/test/lib/devise_token_auth/rails/custom_routes_test.rb +29 -0
  80. data/test/lib/devise_token_auth/rails/routes_test.rb +87 -0
  81. data/test/lib/devise_token_auth/token_factory_test.rb +191 -0
  82. data/test/lib/devise_token_auth/url_test.rb +2 -2
  83. data/test/lib/generators/devise_token_auth/install_generator_test.rb +1 -1
  84. data/test/lib/generators/devise_token_auth/install_generator_with_namespace_test.rb +1 -1
  85. data/test/models/concerns/tokens_serialization_test.rb +104 -0
  86. data/test/models/confirmable_user_test.rb +35 -0
  87. data/test/models/user_test.rb +0 -32
  88. data/test/test_helper.rb +1 -1
  89. metadata +46 -17
  90. data/test/dummy/config/initializers/assets.rb +0 -10
  91. data/test/dummy/tmp/generators/config/routes.rb +0 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5baf8b0a539be2dcf9b1add5ee2dfaac82753127a6180500c653e7d710c04da3
4
- data.tar.gz: 794584507c533b59b88c724c810f7099d06221ff35faab7ee558f92d6849688e
3
+ metadata.gz: 7a64d8fc927471b28cec59b5191e06ef4d2fd7152dadcc9f49b5c512611ba4e6
4
+ data.tar.gz: 3ac708a845da1df134975f293a7db9e8977cd116c0d8dbdc7650e249bb99df82
5
5
  SHA512:
6
- metadata.gz: 58f70c5a715ef337e2d949261f0c774f020831f9755d12fc37b04ca4cba2e416080658946bdb95f5fc1625a3a53c3836202b9e9842dbf420363959be163786cc
7
- data.tar.gz: 8991c6cea21651fff0c98561ac6004bd4a75e04e78ad1af749c04e71fcb9caf8ebb19255ecb78ae91e610b6db05d878d9cf41492560941ea131bcefb7ea0bc0b
6
+ metadata.gz: 51a73c32d0debfc772ff7f7b8b5a524a67fde1676bb66a1d77d243c451a3ca5b375c593287bfb1be2abff7ff881947e39470a6d46421c73f112d4a5b1d774858
7
+ data.tar.gz: a79f4e32938818a92fddbcb88eb918da3c53afe8bf304769fa9d02f1841ed67093ab0bf7b004263094737da15d3dae222b785c70ef233e1b6f43a07a7f49f2b5
data/README.md CHANGED
@@ -65,6 +65,8 @@ 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).
@@ -16,8 +16,8 @@ module DeviseTokenAuth
16
16
 
17
17
  protected
18
18
 
19
- def blacklisted_redirect_url?
20
- DeviseTokenAuth.redirect_whitelist && !DeviseTokenAuth::Url.whitelisted?(@redirect_url)
19
+ def blacklisted_redirect_url?(redirect_url)
20
+ DeviseTokenAuth.redirect_whitelist && !DeviseTokenAuth::Url.whitelisted?(redirect_url)
21
21
  end
22
22
 
23
23
  def build_redirect_headers(access_token, client, redirect_header_options = {})
@@ -17,9 +17,8 @@ module DeviseTokenAuth::Concerns::SetUserByToken
17
17
  @used_auth_by_token = true
18
18
 
19
19
  # initialize instance variables
20
- @client_id ||= nil
20
+ @token ||= DeviseTokenAuth::TokenFactory.new
21
21
  @resource ||= nil
22
- @token ||= nil
23
22
  @is_batch_request ||= nil
24
23
  end
25
24
 
@@ -37,17 +36,18 @@ module DeviseTokenAuth::Concerns::SetUserByToken
37
36
  client_name = DeviseTokenAuth.headers_names[:'client']
38
37
 
39
38
  # parse header for values necessary for authentication
40
- uid = request.headers[uid_name] || params[uid_name]
41
- @token ||= request.headers[access_token_name] || params[access_token_name]
42
- @client_id ||= request.headers[client_name] || params[client_name]
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]
43
43
 
44
- # client_id isn't required, set to 'default' if absent
45
- @client_id ||= 'default'
44
+ # client isn't required, set to 'default' if absent
45
+ @token.client ||= 'default'
46
46
 
47
47
  # check for an existing user, authenticated via warden/devise, if enabled
48
48
  if DeviseTokenAuth.enable_standard_devise_support
49
- devise_warden_user = warden.user(rc.to_s.underscore.to_sym)
50
- if devise_warden_user && devise_warden_user.tokens[@client_id].nil?
49
+ devise_warden_user = warden.user(mapping)
50
+ if devise_warden_user && devise_warden_user.tokens[@token.client].nil?
51
51
  @used_auth_by_token = false
52
52
  @resource = devise_warden_user
53
53
  # REVIEW: The following line _should_ be safe to remove;
@@ -59,19 +59,17 @@ module DeviseTokenAuth::Concerns::SetUserByToken
59
59
  # user has already been found and authenticated
60
60
  return @resource if @resource && @resource.is_a?(rc)
61
61
 
62
- # ensure we clear the client_id
63
- unless @token
64
- @client_id = nil
62
+ # ensure we clear the client
63
+ unless @token.present?
64
+ @token.client = nil
65
65
  return
66
66
  end
67
67
 
68
- return false unless @token
69
-
70
68
  # mitigate timing attacks by finding by uid instead of auth token
71
69
  user = uid && rc.dta_find_by(uid: uid)
72
70
  scope = rc.to_s.underscore.to_sym
73
71
 
74
- if user && user.valid_token?(@token, @client_id)
72
+ if user && user.valid_token?(@token.token, @token.client)
75
73
  # sign_in with bypass: true will be deprecated in the next version of Devise
76
74
  if respond_to?(:bypass_sign_in) && DeviseTokenAuth.bypass_sign_in
77
75
  bypass_sign_in(user, scope: scope)
@@ -81,32 +79,31 @@ module DeviseTokenAuth::Concerns::SetUserByToken
81
79
  return @resource = user
82
80
  else
83
81
  # zero all values previously set values
84
- @client_id = nil
82
+ @token.client = nil
85
83
  return @resource = nil
86
84
  end
87
85
  end
88
86
 
89
87
  def update_auth_header
90
88
  # cannot save object if model has invalid params
89
+ return unless @resource && @token.client
91
90
 
92
- return unless @resource && @client_id
93
-
94
- # Generate new client_id with existing authentication
95
- @client_id = nil unless @used_auth_by_token
91
+ # Generate new client with existing authentication
92
+ @token.client = nil unless @used_auth_by_token
96
93
 
97
94
  if @used_auth_by_token && !DeviseTokenAuth.change_headers_on_each_request
98
95
  # should not append auth header if @resource related token was
99
96
  # cleared by sign out in the meantime
100
- return if @resource.reload.tokens[@client_id].nil?
97
+ return if @resource.reload.tokens[@token.client].nil?
101
98
 
102
- auth_header = @resource.build_auth_header(@token, @client_id)
99
+ auth_header = @resource.build_auth_header(@token.token, @token.client)
103
100
 
104
101
  # update the response header
105
102
  response.headers.merge!(auth_header)
106
103
 
107
104
  else
108
105
  unless @resource.reload.valid?
109
- @resource = resource_class.find(@resource.to_param) # errors remain after reload
106
+ @resource = @resource.class.find(@resource.to_param) # errors remain after reload
110
107
  # if we left the model in a bad state, something is wrong in our app
111
108
  unless @resource.valid?
112
109
  raise DeviseTokenAuth::Errors::InvalidModel, "Cannot set auth token in invalid model. Errors: #{@resource.errors.full_messages}"
@@ -124,30 +121,30 @@ module DeviseTokenAuth::Concerns::SetUserByToken
124
121
  @resource.with_lock do
125
122
  # should not append auth header if @resource related token was
126
123
  # cleared by sign out in the meantime
127
- return if @used_auth_by_token && @resource.tokens[@client_id].nil?
124
+ return if @used_auth_by_token && @resource.tokens[@token.client].nil?
128
125
 
129
126
  # update the response header
130
127
  response.headers.merge!(auth_header_from_batch_request)
131
128
  end # end lock
132
129
  end
133
130
 
134
- def is_batch_request?(user, client_id)
131
+ def is_batch_request?(user, client)
135
132
  !params[:unbatch] &&
136
- user.tokens[client_id] &&
137
- user.tokens[client_id]['updated_at'] &&
138
- user.tokens[client_id]['updated_at'].to_time > @request_started_at - DeviseTokenAuth.batch_request_buffer_throttle
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
139
136
  end
140
137
 
141
138
  def auth_header_from_batch_request
142
139
  # determine batch request status after request processing, in case
143
140
  # another processes has updated it during that processing
144
- @is_batch_request = is_batch_request?(@resource, @client_id)
141
+ @is_batch_request = is_batch_request?(@resource, @token.client)
145
142
 
146
143
  auth_header = {}
147
144
  # extend expiration of batch buffer to account for the duration of
148
145
  # this request
149
146
  if @is_batch_request
150
- auth_header = @resource.extend_batch_buffer(@token, @client_id)
147
+ auth_header = @resource.extend_batch_buffer(@token.token, @token.client)
151
148
 
152
149
  # Do not return token for batch requests to avoid invalidated
153
150
  # tokens returned to the client in case of race conditions.
@@ -158,7 +155,7 @@ module DeviseTokenAuth::Concerns::SetUserByToken
158
155
  auth_header[DeviseTokenAuth.headers_names[:"expiry"]] = ' '
159
156
  else
160
157
  # update Authorization response header with new token
161
- auth_header = @resource.create_new_auth_token(@client_id)
158
+ auth_header = @resource.create_new_auth_token(@token.client)
162
159
  end
163
160
  auth_header
164
161
  end
@@ -2,22 +2,21 @@
2
2
 
3
3
  module DeviseTokenAuth
4
4
  class ConfirmationsController < DeviseTokenAuth::ApplicationController
5
+
5
6
  def show
6
- @resource = resource_class.confirm_by_token(params[:confirmation_token])
7
+ @resource = resource_class.confirm_by_token(resource_params[:confirmation_token])
7
8
 
8
9
  if @resource.errors.empty?
9
10
  yield @resource if block_given?
10
11
 
11
12
  redirect_header_options = { account_confirmation_success: true }
12
13
 
13
- # give redirect value from params priority or fall back to default value if provided
14
- redirect_url = params[:redirect_url] || DeviseTokenAuth.default_confirm_success_url
15
-
16
14
  if signed_in?(resource_name)
17
- client_id, token = signed_in_resource.create_token
15
+ token = signed_in_resource.create_token
16
+ signed_in_resource.save!
18
17
 
19
- redirect_headers = build_redirect_headers(token,
20
- client_id,
18
+ redirect_headers = build_redirect_headers(token.token,
19
+ token.client,
21
20
  redirect_header_options)
22
21
 
23
22
  redirect_to_link = signed_in_resource.build_auth_url(redirect_url, redirect_headers)
@@ -30,5 +29,54 @@ module DeviseTokenAuth
30
29
  raise ActionController::RoutingError, 'Not Found'
31
30
  end
32
31
  end
32
+
33
+ def create
34
+ return render_create_error_missing_email if resource_params[:email].blank?
35
+
36
+ @email = get_case_insensitive_field_from_resource_params(:email)
37
+
38
+ @resource = resource_class.dta_find_by(uid: @email, provider: provider)
39
+
40
+ return render_not_found_error unless @resource
41
+
42
+ @resource.send_confirmation_instructions({
43
+ redirect_url: redirect_url,
44
+ client_config: resource_params[:config_name]
45
+ })
46
+
47
+ return render_create_success
48
+ end
49
+
50
+ protected
51
+
52
+ def render_create_error_missing_email
53
+ render_error(401, I18n.t('devise_token_auth.confirmations.missing_email'))
54
+ end
55
+
56
+ def render_create_success
57
+ render json: {
58
+ success: true,
59
+ message: I18n.t('devise_token_auth.confirmations.sended', email: @email)
60
+ }
61
+ end
62
+
63
+ def render_not_found_error
64
+ render_error(404, I18n.t('devise_token_auth.confirmations.user_not_found', email: @email))
65
+ end
66
+
67
+ private
68
+
69
+ def resource_params
70
+ params.permit(:email, :confirmation_token, :config_name)
71
+ end
72
+
73
+ # give redirect value from params priority or fall back to default value if provided
74
+ def redirect_url
75
+ params.fetch(
76
+ :redirect_url,
77
+ DeviseTokenAuth.default_confirm_success_url
78
+ )
79
+ end
80
+
33
81
  end
34
82
  end
@@ -3,6 +3,9 @@
3
3
  module DeviseTokenAuth
4
4
  class OmniauthCallbacksController < DeviseTokenAuth::ApplicationController
5
5
  attr_reader :auth_params
6
+
7
+ before_action :validate_auth_origin_url_param
8
+
6
9
  skip_before_action :set_user_by_token, raise: false
7
10
  skip_after_action :update_auth_header
8
11
 
@@ -62,7 +65,7 @@ module DeviseTokenAuth
62
65
  end
63
66
 
64
67
  sign_in(:user, @resource, store: false, bypass: false)
65
-
68
+
66
69
  @resource.save!
67
70
 
68
71
  yield @resource if block_given?
@@ -75,6 +78,11 @@ module DeviseTokenAuth
75
78
  render_data_or_redirect('authFailure', error: @error)
76
79
  end
77
80
 
81
+ def validate_auth_origin_url_param
82
+ return render_error_not_allowed_auth_origin_url if auth_origin_url && blacklisted_redirect_url?(auth_origin_url)
83
+ end
84
+
85
+
78
86
  protected
79
87
 
80
88
  # this will be determined differently depending on the action that calls
@@ -104,7 +112,8 @@ module DeviseTokenAuth
104
112
 
105
113
  # break out provider attribute assignment for easy method extension
106
114
  def assign_provider_attrs(user, auth_hash)
107
- attrs = auth_hash['info'].slice(*user.attribute_names)
115
+ attrs = auth_hash['info'].to_hash
116
+ attrs = attrs.slice(*user.attribute_names)
108
117
  user.assign_attributes(attrs)
109
118
  end
110
119
 
@@ -137,10 +146,18 @@ module DeviseTokenAuth
137
146
  omniauth_params['omniauth_window_type']
138
147
  end
139
148
 
140
- def auth_origin_url
149
+ def unsafe_auth_origin_url
141
150
  omniauth_params['auth_origin_url'] || omniauth_params['origin']
142
151
  end
143
152
 
153
+
154
+ def auth_origin_url
155
+ if unsafe_auth_origin_url && blacklisted_redirect_url?(unsafe_auth_origin_url)
156
+ return nil
157
+ end
158
+ return unsafe_auth_origin_url
159
+ end
160
+
144
161
  # in the success case, omniauth_window_type is in the omniauth_params.
145
162
  # in the failure case, it is in a query param. See monkey patch above
146
163
  def omniauth_window_type
@@ -171,11 +188,11 @@ module DeviseTokenAuth
171
188
 
172
189
  def create_auth_params
173
190
  @auth_params = {
174
- auth_token: @token,
175
- client_id: @client_id,
176
- uid: @resource.uid,
177
- expiry: @expiry,
178
- config: @config
191
+ auth_token: @token.token,
192
+ client_id: @token.client,
193
+ uid: @resource.uid,
194
+ expiry: @token.expiry,
195
+ config: @config
179
196
  }
180
197
  @auth_params.merge!(oauth_registration: true) if @oauth_registration
181
198
  @auth_params
@@ -183,11 +200,16 @@ module DeviseTokenAuth
183
200
 
184
201
  def set_token_on_resource
185
202
  @config = omniauth_params['config_name']
186
- @client_id, @token, @expiry = @resource.create_token
203
+ @token = @resource.create_token
204
+ end
205
+
206
+ def render_error_not_allowed_auth_origin_url
207
+ message = I18n.t('devise_token_auth.omniauth.not_allowed_redirect_url', redirect_url: unsafe_auth_origin_url)
208
+ render_data_or_redirect('authFailure', error: message)
187
209
  end
188
210
 
189
211
  def render_data(message, data)
190
- @data = data.merge(message: message)
212
+ @data = data.merge(message: ActionController::Base.helpers.sanitize(message))
191
213
  render layout: nil, template: 'devise_token_auth/omniauth_external_window'
192
214
  end
193
215
 
@@ -224,7 +246,7 @@ module DeviseTokenAuth
224
246
  <html>
225
247
  <head></head>
226
248
  <body>
227
- #{text}
249
+ #{ActionController::Base.helpers.sanitize(text)}
228
250
  </body>
229
251
  </html>)
230
252
  end
@@ -261,4 +283,5 @@ module DeviseTokenAuth
261
283
  @resource
262
284
  end
263
285
  end
286
+
264
287
  end
@@ -2,12 +2,10 @@
2
2
 
3
3
  module DeviseTokenAuth
4
4
  class PasswordsController < DeviseTokenAuth::ApplicationController
5
- before_action :set_user_by_token, only: [:update]
6
5
  before_action :validate_redirect_url_param, only: [:create, :edit]
7
6
  skip_after_action :update_auth_header, only: [:create, :edit]
8
7
 
9
- # this action is responsible for generating password reset tokens and
10
- # sending emails
8
+ # this action is responsible for generating password reset tokens and sending emails
11
9
  def create
12
10
  return render_create_error_missing_email unless resource_params[:email]
13
11
 
@@ -39,11 +37,10 @@ module DeviseTokenAuth
39
37
  @resource = resource_class.with_reset_password_token(resource_params[:reset_password_token])
40
38
 
41
39
  if @resource && @resource.reset_password_period_valid?
42
- client_id, token = @resource.create_token
40
+ token = @resource.create_token unless require_client_password_reset_token?
43
41
 
44
42
  # ensure that user is confirmed
45
43
  @resource.skip_confirmation! if confirmable_enabled? && !@resource.confirmed_at
46
-
47
44
  # allow user to change password once without current_password
48
45
  @resource.allow_password_change = true if recoverable_enabled?
49
46
 
@@ -51,12 +48,16 @@ module DeviseTokenAuth
51
48
 
52
49
  yield @resource if block_given?
53
50
 
54
- redirect_header_options = { reset_password: true }
55
- redirect_headers = build_redirect_headers(token,
56
- client_id,
57
- redirect_header_options)
58
- redirect_to(@resource.build_auth_url(@redirect_url,
59
- redirect_headers))
51
+ if require_client_password_reset_token?
52
+ redirect_to DeviseTokenAuth::Url.generate(@redirect_url, reset_password_token: resource_params[:reset_password_token])
53
+ else
54
+ redirect_header_options = { reset_password: true }
55
+ redirect_headers = build_redirect_headers(token.token,
56
+ token.client,
57
+ redirect_header_options)
58
+ redirect_to(@resource.build_auth_url(@redirect_url,
59
+ redirect_headers))
60
+ end
60
61
  else
61
62
  render_edit_error
62
63
  end
@@ -64,6 +65,15 @@ module DeviseTokenAuth
64
65
 
65
66
  def update
66
67
  # make sure user is authorized
68
+ if require_client_password_reset_token? && resource_params[:reset_password_token]
69
+ @resource = resource_class.with_reset_password_token(resource_params[:reset_password_token])
70
+ return render_update_error_unauthorized unless @resource
71
+
72
+ @token = @resource.create_token
73
+ else
74
+ @resource = set_user_by_token
75
+ end
76
+
67
77
  return render_update_error_unauthorized unless @resource
68
78
 
69
79
  # make sure account doesn't use oauth2 provider
@@ -90,9 +100,9 @@ module DeviseTokenAuth
90
100
  protected
91
101
 
92
102
  def resource_update_method
93
- allow_password_change = recoverable_enabled? && @resource.allow_password_change == true
103
+ allow_password_change = recoverable_enabled? && @resource.allow_password_change == true || require_client_password_reset_token?
94
104
  if DeviseTokenAuth.check_current_password_before_update == false || allow_password_change
95
- 'update_attributes'
105
+ 'update'
96
106
  else
97
107
  'update_with_password'
98
108
  end
@@ -182,7 +192,15 @@ module DeviseTokenAuth
182
192
  )
183
193
 
184
194
  return render_create_error_missing_redirect_url unless @redirect_url
185
- return render_error_not_allowed_redirect_url if blacklisted_redirect_url?
195
+ return render_error_not_allowed_redirect_url if blacklisted_redirect_url?(@redirect_url)
196
+ end
197
+
198
+ def reset_password_token_as_raw?(recoverable)
199
+ recoverable && recoverable.reset_password_token.present? && !require_client_password_reset_token?
200
+ end
201
+
202
+ def require_client_password_reset_token?
203
+ DeviseTokenAuth.require_client_password_reset_token
186
204
  end
187
205
  end
188
206
  end