devise_token_auth 1.1.0 → 1.1.5

Sign up to get free protection for your applications and to get access to all the features.
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