devise_token_auth 0.1.43 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (183) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +42 -895
  3. data/Rakefile +11 -4
  4. data/app/controllers/devise_token_auth/application_controller.rb +19 -8
  5. data/app/controllers/devise_token_auth/concerns/resource_finder.rb +26 -12
  6. data/app/controllers/devise_token_auth/concerns/set_user_by_token.rb +106 -85
  7. data/app/controllers/devise_token_auth/confirmations_controller.rb +73 -17
  8. data/app/controllers/devise_token_auth/omniauth_callbacks_controller.rb +95 -51
  9. data/app/controllers/devise_token_auth/passwords_controller.rb +65 -57
  10. data/app/controllers/devise_token_auth/registrations_controller.rb +61 -61
  11. data/app/controllers/devise_token_auth/sessions_controller.rb +22 -18
  12. data/app/controllers/devise_token_auth/token_validations_controller.rb +5 -3
  13. data/app/controllers/devise_token_auth/unlocks_controller.rb +20 -16
  14. data/app/models/devise_token_auth/concerns/active_record_support.rb +14 -0
  15. data/app/models/devise_token_auth/concerns/confirmable_support.rb +28 -0
  16. data/app/models/devise_token_auth/concerns/mongoid_support.rb +19 -0
  17. data/app/models/devise_token_auth/concerns/tokens_serialization.rb +31 -0
  18. data/app/models/devise_token_auth/concerns/user.rb +92 -100
  19. data/app/models/devise_token_auth/concerns/user_omniauth_callbacks.rb +8 -3
  20. data/app/validators/{email_validator.rb → devise_token_auth_email_validator.rb} +5 -3
  21. data/app/views/devise_token_auth/omniauth_external_window.html.erb +1 -1
  22. data/config/locales/da-DK.yml +11 -9
  23. data/config/locales/de.yml +2 -0
  24. data/config/locales/en.yml +10 -0
  25. data/config/locales/es.yml +2 -0
  26. data/config/locales/fr.yml +2 -0
  27. data/config/locales/he.yml +52 -0
  28. data/config/locales/it.yml +2 -0
  29. data/config/locales/ja.yml +4 -2
  30. data/config/locales/ko.yml +51 -0
  31. data/config/locales/nl.yml +2 -0
  32. data/config/locales/pl.yml +6 -3
  33. data/config/locales/pt-BR.yml +2 -0
  34. data/config/locales/pt.yml +6 -3
  35. data/config/locales/ro.yml +2 -0
  36. data/config/locales/ru.yml +2 -0
  37. data/config/locales/sq.yml +2 -0
  38. data/config/locales/sv.yml +52 -0
  39. data/config/locales/uk.yml +2 -0
  40. data/config/locales/vi.yml +2 -0
  41. data/config/locales/zh-CN.yml +2 -0
  42. data/config/locales/zh-HK.yml +2 -0
  43. data/config/locales/zh-TW.yml +2 -0
  44. data/lib/devise_token_auth/blacklist.rb +6 -0
  45. data/lib/devise_token_auth/controllers/helpers.rb +21 -13
  46. data/lib/devise_token_auth/controllers/url_helpers.rb +2 -0
  47. data/lib/devise_token_auth/engine.rb +26 -14
  48. data/lib/devise_token_auth/errors.rb +8 -0
  49. data/lib/devise_token_auth/rails/routes.rb +37 -30
  50. data/lib/devise_token_auth/token_factory.rb +126 -0
  51. data/lib/devise_token_auth/url.rb +11 -4
  52. data/lib/devise_token_auth/version.rb +3 -1
  53. data/lib/devise_token_auth.rb +11 -5
  54. data/lib/generators/devise_token_auth/USAGE +2 -2
  55. data/lib/generators/devise_token_auth/install_generator.rb +36 -105
  56. data/lib/generators/devise_token_auth/install_generator_helpers.rb +98 -0
  57. data/lib/generators/devise_token_auth/install_mongoid_generator.rb +46 -0
  58. data/lib/generators/devise_token_auth/install_views_generator.rb +7 -5
  59. data/lib/generators/devise_token_auth/templates/devise_token_auth.rb +12 -0
  60. data/lib/generators/devise_token_auth/templates/devise_token_auth_create_users.rb.erb +8 -14
  61. data/lib/generators/devise_token_auth/templates/user.rb.erb +9 -0
  62. data/lib/generators/devise_token_auth/templates/user_mongoid.rb.erb +56 -0
  63. data/lib/tasks/devise_token_auth_tasks.rake +2 -0
  64. data/test/controllers/custom/custom_confirmations_controller_test.rb +5 -1
  65. data/test/controllers/custom/custom_omniauth_callbacks_controller_test.rb +4 -0
  66. data/test/controllers/custom/custom_passwords_controller_test.rb +6 -2
  67. data/test/controllers/custom/custom_registrations_controller_test.rb +17 -8
  68. data/test/controllers/custom/custom_sessions_controller_test.rb +7 -5
  69. data/test/controllers/custom/custom_token_validations_controller_test.rb +5 -3
  70. data/test/controllers/demo_group_controller_test.rb +4 -6
  71. data/test/controllers/demo_mang_controller_test.rb +3 -3
  72. data/test/controllers/demo_user_controller_test.rb +53 -25
  73. data/test/controllers/devise_token_auth/confirmations_controller_test.rb +159 -25
  74. data/test/controllers/devise_token_auth/omniauth_callbacks_controller_test.rb +117 -47
  75. data/test/controllers/devise_token_auth/passwords_controller_test.rb +309 -126
  76. data/test/controllers/devise_token_auth/registrations_controller_test.rb +65 -23
  77. data/test/controllers/devise_token_auth/sessions_controller_test.rb +93 -61
  78. data/test/controllers/devise_token_auth/token_validations_controller_test.rb +18 -6
  79. data/test/controllers/devise_token_auth/unlocks_controller_test.rb +24 -5
  80. data/test/controllers/overrides/confirmations_controller_test.rb +6 -2
  81. data/test/controllers/overrides/omniauth_callbacks_controller_test.rb +5 -1
  82. data/test/controllers/overrides/passwords_controller_test.rb +27 -29
  83. data/test/controllers/overrides/registrations_controller_test.rb +33 -27
  84. data/test/controllers/overrides/sessions_controller_test.rb +6 -4
  85. data/test/controllers/overrides/token_validations_controller_test.rb +5 -3
  86. data/test/dummy/app/active_record/confirmable_user.rb +11 -0
  87. data/test/dummy/app/{models → active_record}/lockable_user.rb +2 -0
  88. data/test/dummy/app/{models → active_record}/mang.rb +2 -0
  89. data/test/dummy/app/{models → active_record}/only_email_user.rb +2 -0
  90. data/test/dummy/app/{models → active_record}/scoped_user.rb +4 -2
  91. data/test/dummy/app/{models → active_record}/unconfirmable_user.rb +3 -2
  92. data/test/dummy/app/active_record/unregisterable_user.rb +9 -0
  93. data/test/dummy/app/active_record/user.rb +6 -0
  94. data/test/dummy/app/controllers/application_controller.rb +2 -0
  95. data/test/dummy/app/controllers/auth_origin_controller.rb +2 -0
  96. data/test/dummy/app/controllers/custom/confirmations_controller.rb +2 -2
  97. data/test/dummy/app/controllers/custom/omniauth_callbacks_controller.rb +2 -0
  98. data/test/dummy/app/controllers/custom/passwords_controller.rb +3 -4
  99. data/test/dummy/app/controllers/custom/registrations_controller.rb +3 -3
  100. data/test/dummy/app/controllers/custom/sessions_controller.rb +3 -3
  101. data/test/dummy/app/controllers/custom/token_validations_controller.rb +3 -3
  102. data/test/dummy/app/controllers/demo_group_controller.rb +2 -0
  103. data/test/dummy/app/controllers/demo_mang_controller.rb +2 -0
  104. data/test/dummy/app/controllers/demo_user_controller.rb +2 -0
  105. data/test/dummy/app/controllers/overrides/confirmations_controller.rb +8 -6
  106. data/test/dummy/app/controllers/overrides/omniauth_callbacks_controller.rb +5 -3
  107. data/test/dummy/app/controllers/overrides/passwords_controller.rb +10 -8
  108. data/test/dummy/app/controllers/overrides/registrations_controller.rb +5 -3
  109. data/test/dummy/app/controllers/overrides/sessions_controller.rb +12 -12
  110. data/test/dummy/app/controllers/overrides/token_validations_controller.rb +5 -5
  111. data/test/dummy/app/helpers/application_helper.rb +1029 -1036
  112. data/test/dummy/app/models/{user.rb → concerns/favorite_color.rb} +8 -7
  113. data/test/dummy/app/mongoid/confirmable_user.rb +52 -0
  114. data/test/dummy/app/mongoid/lockable_user.rb +38 -0
  115. data/test/dummy/app/mongoid/mang.rb +46 -0
  116. data/test/dummy/app/mongoid/only_email_user.rb +33 -0
  117. data/test/dummy/app/mongoid/scoped_user.rb +50 -0
  118. data/test/dummy/app/mongoid/unconfirmable_user.rb +44 -0
  119. data/test/dummy/app/mongoid/unregisterable_user.rb +47 -0
  120. data/test/dummy/app/mongoid/user.rb +49 -0
  121. data/test/dummy/app/views/layouts/application.html.erb +0 -2
  122. data/test/dummy/config/application.rb +26 -3
  123. data/test/dummy/config/boot.rb +8 -2
  124. data/test/dummy/config/environment.rb +3 -1
  125. data/test/dummy/config/environments/development.rb +5 -13
  126. data/test/dummy/config/environments/production.rb +2 -16
  127. data/test/dummy/config/environments/test.rb +3 -1
  128. data/test/dummy/config/initializers/backtrace_silencers.rb +2 -0
  129. data/test/dummy/config/initializers/cookies_serializer.rb +3 -1
  130. data/test/dummy/config/initializers/devise.rb +287 -0
  131. data/test/dummy/config/initializers/devise_token_auth.rb +37 -4
  132. data/test/dummy/config/initializers/figaro.rb +3 -1
  133. data/test/dummy/config/initializers/filter_parameter_logging.rb +2 -0
  134. data/test/dummy/config/initializers/inflections.rb +2 -0
  135. data/test/dummy/config/initializers/mime_types.rb +2 -0
  136. data/test/dummy/config/initializers/omniauth.rb +5 -2
  137. data/test/dummy/config/initializers/session_store.rb +2 -0
  138. data/test/dummy/config/initializers/wrap_parameters.rb +2 -0
  139. data/test/dummy/config/routes.rb +14 -29
  140. data/test/dummy/config/spring.rb +2 -0
  141. data/test/dummy/config.ru +5 -3
  142. data/test/dummy/db/migrate/20140715061447_devise_token_auth_create_users.rb +9 -14
  143. data/test/dummy/db/migrate/20140715061805_devise_token_auth_create_mangs.rb +8 -13
  144. data/test/dummy/db/migrate/20140829044006_add_operating_thetan_to_user.rb +2 -0
  145. data/test/dummy/db/migrate/20140916224624_add_favorite_color_to_mangs.rb +2 -0
  146. data/test/dummy/db/migrate/20141222035835_devise_token_auth_create_only_email_users.rb +6 -11
  147. data/test/dummy/db/migrate/20141222053502_devise_token_auth_create_unregisterable_users.rb +8 -13
  148. data/test/dummy/db/migrate/20150708104536_devise_token_auth_create_unconfirmable_users.rb +8 -13
  149. data/test/dummy/db/migrate/20160103235141_devise_token_auth_create_scoped_users.rb +8 -13
  150. data/test/dummy/db/migrate/20160629184441_devise_token_auth_create_lockable_users.rb +8 -13
  151. data/test/dummy/{tmp/generators/db/migrate/20171014052631_devise_token_auth_create_users.rb → db/migrate/20190924101113_devise_token_auth_create_confirmable_users.rb} +8 -14
  152. data/test/dummy/db/schema.rb +11 -71
  153. data/test/dummy/lib/migration_database_helper.rb +15 -1
  154. data/test/dummy/tmp/generators/app/controllers/application_controller.rb +6 -0
  155. data/test/dummy/tmp/generators/app/models/azpire/v1/human_resource/user.rb +56 -0
  156. data/test/dummy/tmp/generators/config/initializers/devise_token_auth.rb +12 -0
  157. data/test/factories/users.rb +41 -0
  158. data/test/lib/devise_token_auth/blacklist_test.rb +19 -0
  159. data/test/lib/devise_token_auth/rails/custom_routes_test.rb +29 -0
  160. data/test/lib/devise_token_auth/rails/routes_test.rb +87 -0
  161. data/test/lib/devise_token_auth/token_factory_test.rb +191 -0
  162. data/test/lib/devise_token_auth/url_test.rb +9 -7
  163. data/test/lib/generators/devise_token_auth/install_generator_test.rb +67 -37
  164. data/test/lib/generators/devise_token_auth/install_generator_with_namespace_test.rb +222 -0
  165. data/test/lib/generators/devise_token_auth/install_views_generator_test.rb +3 -1
  166. data/test/models/concerns/mongoid_support_test.rb +31 -0
  167. data/test/models/concerns/tokens_serialization_test.rb +104 -0
  168. data/test/models/confirmable_user_test.rb +35 -0
  169. data/test/models/only_email_user_test.rb +2 -8
  170. data/test/models/user_test.rb +18 -79
  171. data/test/support/controllers/routes.rb +43 -0
  172. data/test/test_helper.rb +83 -26
  173. metadata +153 -44
  174. data/config/initializers/devise.rb +0 -196
  175. data/lib/generators/devise_token_auth/templates/user.rb +0 -7
  176. data/test/dummy/app/models/evil_user.rb +0 -3
  177. data/test/dummy/app/models/nice_user.rb +0 -7
  178. data/test/dummy/app/models/unregisterable_user.rb +0 -7
  179. data/test/dummy/config/initializers/assets.rb +0 -8
  180. data/test/dummy/db/migrate/20140928231203_devise_token_auth_create_evil_users.rb +0 -64
  181. data/test/dummy/db/migrate/20150409095712_devise_token_auth_create_nice_users.rb +0 -61
  182. data/test/dummy/tmp/generators/app/models/user.rb +0 -11
  183. data/test/integration/navigation_test.rb +0 -10
@@ -1,7 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module DeviseTokenAuth
2
4
  class OmniauthCallbacksController < DeviseTokenAuth::ApplicationController
3
-
4
5
  attr_reader :auth_params
6
+
7
+ before_action :validate_auth_origin_url_param
8
+
5
9
  skip_before_action :set_user_by_token, raise: false
6
10
  skip_after_action :update_auth_header
7
11
 
@@ -11,11 +15,8 @@ module DeviseTokenAuth
11
15
 
12
16
  # derive target redirect route from 'resource_class' param, which was set
13
17
  # before authentication.
14
- devise_mapping = [request.env['omniauth.params']['namespace_name'],
15
- request.env['omniauth.params']['resource_class'].underscore.gsub('/', '_')].compact.join('_')
16
- path = "#{Devise.mappings[devise_mapping.to_sym].fullpath}/#{params[:provider]}/callback"
17
- klass = request.scheme == 'https' ? URI::HTTPS : URI::HTTP
18
- redirect_route = klass.build(host: request.host, port: request.port, path: path).to_s
18
+ devise_mapping = get_devise_mapping
19
+ redirect_route = get_redirect_route(devise_mapping)
19
20
 
20
21
  # preserve omniauth info for success route. ignore 'extra' in twitter
21
22
  # auth response to avoid CookieOverflow.
@@ -25,6 +26,34 @@ module DeviseTokenAuth
25
26
  redirect_to redirect_route
26
27
  end
27
28
 
29
+ def get_redirect_route(devise_mapping)
30
+ path = "#{Devise.mappings[devise_mapping.to_sym].fullpath}/#{params[:provider]}/callback"
31
+ klass = request.scheme == 'https' ? URI::HTTPS : URI::HTTP
32
+ redirect_route = klass.build(host: request.host, port: request.port, path: path).to_s
33
+ end
34
+
35
+ def get_devise_mapping
36
+ # derive target redirect route from 'resource_class' param, which was set
37
+ # before authentication.
38
+ devise_mapping = [request.env['omniauth.params']['namespace_name'],
39
+ request.env['omniauth.params']['resource_class'].underscore.gsub('/', '_')].compact.join('_')
40
+ rescue NoMethodError => err
41
+ default_devise_mapping
42
+ end
43
+
44
+ # This method will only be called if `get_devise_mapping` cannot
45
+ # find the mapping in `omniauth.params`.
46
+ #
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
49
+ # the devise mapping. If you are in a situation like that, and
50
+ # your app allows for you to determine somehow what the devise
51
+ # mapping should be (because, for example, it is always the same),
52
+ # then you can handle it by overriding this method.
53
+ def default_devise_mapping
54
+ raise NotImplementedError.new('no default_devise_mapping set')
55
+ end
56
+
28
57
  def omniauth_success
29
58
  get_resource_from_auth_hash
30
59
  set_token_on_resource
@@ -46,9 +75,14 @@ module DeviseTokenAuth
46
75
 
47
76
  def omniauth_failure
48
77
  @error = params[:message]
49
- render_data_or_redirect('authFailure', {error: @error})
78
+ render_data_or_redirect('authFailure', error: @error)
50
79
  end
51
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
+
52
86
  protected
53
87
 
54
88
  # this will be determined differently depending on the action that calls
@@ -60,7 +94,7 @@ module DeviseTokenAuth
60
94
  # after use. In the failure case, finally, the omniauth params
61
95
  # are added as query params in our monkey patch to OmniAuth in engine.rb
62
96
  def omniauth_params
63
- if !defined?(@_omniauth_params)
97
+ unless defined?(@_omniauth_params)
64
98
  if request.env['omniauth.params'] && request.env['omniauth.params'].any?
65
99
  @_omniauth_params = request.env['omniauth.params']
66
100
  elsif session['dta.omniauth.params'] && session['dta.omniauth.params'].any?
@@ -78,7 +112,8 @@ module DeviseTokenAuth
78
112
 
79
113
  # break out provider attribute assignment for easy method extension
80
114
  def assign_provider_attrs(user, auth_hash)
81
- attrs = auth_hash['info'].slice(*user.attributes.keys)
115
+ attrs = auth_hash['info'].to_hash
116
+ attrs = attrs.slice(*user.attribute_names)
82
117
  user.assign_attributes(attrs)
83
118
  end
84
119
 
@@ -86,13 +121,11 @@ module DeviseTokenAuth
86
121
  def whitelisted_params
87
122
  whitelist = params_for_resource(:sign_up)
88
123
 
89
- whitelist.inject({}){|coll, key|
124
+ whitelist.inject({}) do |coll, key|
90
125
  param = omniauth_params[key.to_s]
91
- if param
92
- coll[key] = param
93
- end
126
+ coll[key] = param if param
94
127
  coll
95
- }
128
+ end
96
129
  end
97
130
 
98
131
  def resource_class(mapping = nil)
@@ -101,7 +134,7 @@ module DeviseTokenAuth
101
134
  elsif params['resource_class']
102
135
  params['resource_class'].constantize
103
136
  else
104
- raise "No resource_class found"
137
+ raise 'No resource_class found'
105
138
  end
106
139
  end
107
140
 
@@ -113,10 +146,18 @@ module DeviseTokenAuth
113
146
  omniauth_params['omniauth_window_type']
114
147
  end
115
148
 
116
- def auth_origin_url
149
+ def unsafe_auth_origin_url
117
150
  omniauth_params['auth_origin_url'] || omniauth_params['origin']
118
151
  end
119
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
+
120
161
  # in the success case, omniauth_window_type is in the omniauth_params.
121
162
  # in the failure case, it is in a query param. See monkey patch above
122
163
  def omniauth_window_type
@@ -137,31 +178,21 @@ module DeviseTokenAuth
137
178
  true
138
179
  end
139
180
 
140
- # necessary for access to devise_parameter_sanitizers
141
- def devise_mapping
142
- if omniauth_params
143
- Devise.mappings[[omniauth_params['namespace_name'],
144
- omniauth_params['resource_class'].underscore].compact.join('_').to_sym]
145
- else
146
- request.env['devise.mapping']
147
- end
148
- end
149
-
150
181
  def set_random_password
151
182
  # set crazy password for new oauth users. this is only used to prevent
152
- # access via email sign-in.
153
- p = SecureRandom.urlsafe_base64(nil, false)
154
- @resource.password = p
155
- @resource.password_confirmation = p
183
+ # access via email sign-in.
184
+ p = SecureRandom.urlsafe_base64(nil, false)
185
+ @resource.password = p
186
+ @resource.password_confirmation = p
156
187
  end
157
188
 
158
189
  def create_auth_params
159
190
  @auth_params = {
160
- auth_token: @token,
161
- client_id: @client_id,
162
- uid: @resource.uid,
163
- expiry: @expiry,
164
- config: @config
191
+ auth_token: @token.token,
192
+ client_id: @token.client,
193
+ uid: @resource.uid,
194
+ expiry: @token.expiry,
195
+ config: @config
165
196
  }
166
197
  @auth_params.merge!(oauth_registration: true) if @oauth_registration
167
198
  @auth_params
@@ -169,14 +200,17 @@ module DeviseTokenAuth
169
200
 
170
201
  def set_token_on_resource
171
202
  @config = omniauth_params['config_name']
172
- @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)
173
209
  end
174
210
 
175
211
  def render_data(message, data)
176
- @data = data.merge({
177
- message: message
178
- })
179
- render :layout => nil, :template => "devise_token_auth/omniauth_external_window"
212
+ @data = data.merge(message: ActionController::Base.helpers.sanitize(message))
213
+ render layout: nil, template: 'devise_token_auth/omniauth_external_window'
180
214
  end
181
215
 
182
216
  def render_data_or_redirect(message, data, user_data = {})
@@ -207,37 +241,47 @@ module DeviseTokenAuth
207
241
  end
208
242
 
209
243
  def fallback_render(text)
210
- render inline: %Q|
244
+ render inline: %Q(
211
245
 
212
246
  <html>
213
247
  <head></head>
214
248
  <body>
215
- #{text}
249
+ #{ActionController::Base.helpers.sanitize(text)}
216
250
  </body>
217
- </html>|
251
+ </html>)
252
+ end
253
+
254
+ def handle_new_resource
255
+ @oauth_registration = true
256
+ set_random_password
257
+ end
258
+
259
+ def assign_whitelisted_params?
260
+ true
218
261
  end
219
262
 
220
263
  def get_resource_from_auth_hash
221
264
  # find or create user by provider and provider uid
222
- @resource = resource_class.where({
223
- uid: auth_hash['uid'],
265
+ @resource = resource_class.where(
266
+ uid: auth_hash['uid'],
224
267
  provider: auth_hash['provider']
225
- }).first_or_initialize
268
+ ).first_or_initialize
226
269
 
227
270
  if @resource.new_record?
228
- @oauth_registration = true
229
- set_random_password
271
+ handle_new_resource
230
272
  end
231
273
 
232
274
  # sync user info with provider, update/generate auth token
233
275
  assign_provider_attrs(@resource, auth_hash)
234
276
 
235
277
  # assign any additional (whitelisted) attributes
236
- extra_params = whitelisted_params
237
- @resource.assign_attributes(extra_params) if extra_params
278
+ if assign_whitelisted_params?
279
+ extra_params = whitelisted_params
280
+ @resource.assign_attributes(extra_params) if extra_params
281
+ end
238
282
 
239
283
  @resource
240
284
  end
241
-
242
285
  end
286
+
243
287
  end
@@ -1,43 +1,25 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module DeviseTokenAuth
2
4
  class PasswordsController < DeviseTokenAuth::ApplicationController
3
- before_action :set_user_by_token, :only => [:update]
4
- skip_after_action :update_auth_header, :only => [:create, :edit]
5
+ before_action :validate_redirect_url_param, only: [:create, :edit]
6
+ skip_after_action :update_auth_header, only: [:create, :edit]
5
7
 
6
- # this action is responsible for generating password reset tokens and
7
- # sending emails
8
+ # this action is responsible for generating password reset tokens and sending emails
8
9
  def create
9
- unless resource_params[:email]
10
- return render_create_error_missing_email
11
- end
12
-
13
- # give redirect value from params priority
14
- @redirect_url = params[:redirect_url]
15
-
16
- # fall back to default value if provided
17
- @redirect_url ||= DeviseTokenAuth.default_password_reset_url
18
-
19
- unless @redirect_url
20
- return render_create_error_missing_redirect_url
21
- end
22
-
23
- # if whitelist is set, validate redirect_url against whitelist
24
- if DeviseTokenAuth.redirect_whitelist
25
- unless DeviseTokenAuth::Url.whitelisted?(@redirect_url)
26
- return render_create_error_not_allowed_redirect_url
27
- end
28
- end
10
+ return render_create_error_missing_email unless resource_params[:email]
29
11
 
30
12
  @email = get_case_insensitive_field_from_resource_params(:email)
31
13
  @resource = find_resource(:uid, @email)
32
14
 
33
15
  if @resource
34
16
  yield @resource if block_given?
35
- @resource.send_reset_password_instructions({
17
+ @resource.send_reset_password_instructions(
36
18
  email: @email,
37
19
  provider: 'email',
38
20
  redirect_url: @redirect_url,
39
21
  client_config: params[:config_name]
40
- })
22
+ )
41
23
 
42
24
  if @resource.errors.empty?
43
25
  return render_create_success
@@ -52,14 +34,13 @@ module DeviseTokenAuth
52
34
  # this is where users arrive after visiting the password reset confirmation link
53
35
  def edit
54
36
  # if a user is not found, return nil
55
- @resource = with_reset_password_token(resource_params[:reset_password_token])
37
+ @resource = resource_class.with_reset_password_token(resource_params[:reset_password_token])
56
38
 
57
39
  if @resource && @resource.reset_password_period_valid?
58
- client_id, token = @resource.create_token
40
+ token = @resource.create_token unless require_client_password_reset_token?
59
41
 
60
42
  # ensure that user is confirmed
61
43
  @resource.skip_confirmation! if confirmable_enabled? && !@resource.confirmed_at
62
-
63
44
  # allow user to change password once without current_password
64
45
  @resource.allow_password_change = true if recoverable_enabled?
65
46
 
@@ -67,12 +48,16 @@ module DeviseTokenAuth
67
48
 
68
49
  yield @resource if block_given?
69
50
 
70
- redirect_header_options = {reset_password: true}
71
- redirect_headers = build_redirect_headers(token,
72
- client_id,
73
- redirect_header_options)
74
- redirect_to(@resource.build_auth_url(params[:redirect_url],
75
- 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
76
61
  else
77
62
  render_edit_error
78
63
  end
@@ -80,10 +65,17 @@ module DeviseTokenAuth
80
65
 
81
66
  def update
82
67
  # make sure user is authorized
83
- unless @resource
84
- return render_update_error_unauthorized
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
85
75
  end
86
76
 
77
+ return render_update_error_unauthorized unless @resource
78
+
87
79
  # make sure account doesn't use oauth2 provider
88
80
  unless @resource.provider == 'email'
89
81
  return render_update_error_password_not_required
@@ -108,47 +100,47 @@ module DeviseTokenAuth
108
100
  protected
109
101
 
110
102
  def resource_update_method
111
- 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?
112
104
  if DeviseTokenAuth.check_current_password_before_update == false || allow_password_change
113
- "update_attributes"
105
+ 'update'
114
106
  else
115
- "update_with_password"
107
+ 'update_with_password'
116
108
  end
117
109
  end
118
110
 
119
111
  def render_create_error_missing_email
120
- render_error(401, I18n.t("devise_token_auth.passwords.missing_email"))
112
+ render_error(401, I18n.t('devise_token_auth.passwords.missing_email'))
121
113
  end
122
114
 
123
115
  def render_create_error_missing_redirect_url
124
- render_error(401, I18n.t("devise_token_auth.passwords.missing_redirect_url"))
116
+ render_error(401, I18n.t('devise_token_auth.passwords.missing_redirect_url'))
125
117
  end
126
118
 
127
- def render_create_error_not_allowed_redirect_url
119
+ def render_error_not_allowed_redirect_url
128
120
  response = {
129
121
  status: 'error',
130
122
  data: resource_data
131
123
  }
132
- message = I18n.t("devise_token_auth.passwords.not_allowed_redirect_url", redirect_url: @redirect_url)
124
+ message = I18n.t('devise_token_auth.passwords.not_allowed_redirect_url', redirect_url: @redirect_url)
133
125
  render_error(422, message, response)
134
126
  end
135
127
 
136
128
  def render_create_success
137
129
  render json: {
138
130
  success: true,
139
- message: I18n.t("devise_token_auth.passwords.sended", email: @email)
131
+ message: success_message('passwords', @email)
140
132
  }
141
133
  end
142
134
 
143
135
  def render_create_error(errors)
144
136
  render json: {
145
137
  success: false,
146
- errors: errors,
138
+ errors: errors
147
139
  }, status: 400
148
140
  end
149
141
 
150
142
  def render_edit_error
151
- raise ActionController::RoutingError.new('Not Found')
143
+ raise ActionController::RoutingError, 'Not Found'
152
144
  end
153
145
 
154
146
  def render_update_error_unauthorized
@@ -156,23 +148,23 @@ module DeviseTokenAuth
156
148
  end
157
149
 
158
150
  def render_update_error_password_not_required
159
- render_error(422, I18n.t("devise_token_auth.passwords.password_not_required", provider: @resource.provider.humanize))
151
+ render_error(422, I18n.t('devise_token_auth.passwords.password_not_required', provider: @resource.provider.humanize))
160
152
  end
161
153
 
162
154
  def render_update_error_missing_password
163
- render_error(422, I18n.t("devise_token_auth.passwords.missing_passwords"))
155
+ render_error(422, I18n.t('devise_token_auth.passwords.missing_passwords'))
164
156
  end
165
157
 
166
158
  def render_update_success
167
159
  render json: {
168
160
  success: true,
169
161
  data: resource_data,
170
- message: I18n.t("devise_token_auth.passwords.successfully_updated")
162
+ message: I18n.t('devise_token_auth.passwords.successfully_updated')
171
163
  }
172
164
  end
173
165
 
174
166
  def render_update_error
175
- return render json: {
167
+ render json: {
176
168
  success: false,
177
169
  errors: resource_errors
178
170
  }, status: 422
@@ -188,15 +180,31 @@ module DeviseTokenAuth
188
180
  params.permit(*params_for_resource(:account_update))
189
181
  end
190
182
 
191
- def with_reset_password_token token
192
- recoverable = resource_class.with_reset_password_token(token)
183
+ def render_not_found_error
184
+ if Devise.paranoid
185
+ render_error(404, I18n.t('devise_token_auth.passwords.sended_paranoid'))
186
+ else
187
+ render_error(404, I18n.t('devise_token_auth.passwords.user_not_found', email: @email))
188
+ end
189
+ end
190
+
191
+ def validate_redirect_url_param
192
+ # give redirect value from params priority
193
+ @redirect_url = params.fetch(
194
+ :redirect_url,
195
+ DeviseTokenAuth.default_password_reset_url
196
+ )
193
197
 
194
- recoverable.reset_password_token = token if recoverable && recoverable.reset_password_token.present?
195
- recoverable
198
+ return render_create_error_missing_redirect_url unless @redirect_url
199
+ return render_error_not_allowed_redirect_url if blacklisted_redirect_url?(@redirect_url)
196
200
  end
197
201
 
198
- def render_not_found_error
199
- render_error(404, I18n.t("devise_token_auth.passwords.user_not_found", email: @email))
202
+ def reset_password_token_as_raw?(recoverable)
203
+ recoverable && recoverable.reset_password_token.present? && !require_client_password_reset_token?
204
+ end
205
+
206
+ def require_client_password_reset_token?
207
+ DeviseTokenAuth.require_client_password_reset_token
200
208
  end
201
209
  end
202
210
  end