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.

Files changed (83) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +4 -2
  3. data/app/controllers/devise_token_auth/application_controller.rb +0 -1
  4. data/app/controllers/devise_token_auth/concerns/resource_finder.rb +11 -12
  5. data/app/controllers/devise_token_auth/concerns/set_user_by_token.rb +39 -55
  6. data/app/controllers/devise_token_auth/confirmations_controller.rb +62 -20
  7. data/app/controllers/devise_token_auth/omniauth_callbacks_controller.rb +51 -26
  8. data/app/controllers/devise_token_auth/passwords_controller.rb +19 -23
  9. data/app/controllers/devise_token_auth/registrations_controller.rb +32 -40
  10. data/app/controllers/devise_token_auth/sessions_controller.rb +5 -5
  11. data/app/controllers/devise_token_auth/unlocks_controller.rb +4 -4
  12. data/app/models/devise_token_auth/concerns/active_record_support.rb +16 -0
  13. data/app/models/devise_token_auth/concerns/mongoid_support.rb +19 -0
  14. data/app/models/devise_token_auth/concerns/tokens_serialization.rb +19 -0
  15. data/app/models/devise_token_auth/concerns/user.rb +44 -67
  16. data/app/models/devise_token_auth/concerns/user_omniauth_callbacks.rb +2 -2
  17. data/app/validators/{email_validator.rb → devise_token_auth_email_validator.rb} +1 -1
  18. data/config/locales/en.yml +5 -0
  19. data/config/locales/he.yml +50 -0
  20. data/config/locales/ja.yml +1 -1
  21. data/lib/devise_token_auth/blacklist.rb +2 -0
  22. data/lib/devise_token_auth/engine.rb +2 -0
  23. data/lib/devise_token_auth/rails/routes.rb +1 -1
  24. data/lib/devise_token_auth/token_factory.rb +126 -0
  25. data/lib/devise_token_auth/version.rb +1 -1
  26. data/lib/devise_token_auth.rb +6 -3
  27. data/lib/generators/devise_token_auth/install_generator.rb +3 -87
  28. data/lib/generators/devise_token_auth/install_generator_helpers.rb +98 -0
  29. data/lib/generators/devise_token_auth/install_mongoid_generator.rb +46 -0
  30. data/lib/generators/devise_token_auth/templates/devise_token_auth.rb +5 -0
  31. data/lib/generators/devise_token_auth/templates/devise_token_auth_create_users.rb.erb +0 -7
  32. data/lib/generators/devise_token_auth/templates/user_mongoid.rb.erb +56 -0
  33. data/test/controllers/custom/custom_confirmations_controller_test.rb +1 -1
  34. data/test/controllers/demo_user_controller_test.rb +2 -2
  35. data/test/controllers/devise_token_auth/confirmations_controller_test.rb +79 -19
  36. data/test/controllers/devise_token_auth/omniauth_callbacks_controller_test.rb +2 -0
  37. data/test/controllers/devise_token_auth/passwords_controller_test.rb +115 -94
  38. data/test/controllers/devise_token_auth/registrations_controller_test.rb +31 -4
  39. data/test/controllers/devise_token_auth/sessions_controller_test.rb +0 -38
  40. data/test/controllers/devise_token_auth/token_validations_controller_test.rb +2 -1
  41. data/test/dummy/app/{models → active_record}/scoped_user.rb +2 -2
  42. data/test/dummy/app/{models → active_record}/unconfirmable_user.rb +1 -2
  43. data/test/dummy/app/{models → active_record}/unregisterable_user.rb +3 -3
  44. data/test/dummy/app/active_record/user.rb +6 -0
  45. data/test/dummy/app/controllers/overrides/confirmations_controller.rb +3 -3
  46. data/test/dummy/app/controllers/overrides/passwords_controller.rb +3 -3
  47. data/test/dummy/app/controllers/overrides/registrations_controller.rb +1 -1
  48. data/test/dummy/app/controllers/overrides/sessions_controller.rb +2 -2
  49. data/test/dummy/app/models/{user.rb → concerns/favorite_color.rb} +7 -8
  50. data/test/dummy/app/mongoid/lockable_user.rb +38 -0
  51. data/test/dummy/app/mongoid/mang.rb +46 -0
  52. data/test/dummy/app/mongoid/only_email_user.rb +33 -0
  53. data/test/dummy/app/mongoid/scoped_user.rb +50 -0
  54. data/test/dummy/app/mongoid/unconfirmable_user.rb +44 -0
  55. data/test/dummy/app/mongoid/unregisterable_user.rb +47 -0
  56. data/test/dummy/app/mongoid/user.rb +49 -0
  57. data/test/dummy/config/application.rb +23 -1
  58. data/test/dummy/config/boot.rb +4 -0
  59. data/test/dummy/config/initializers/devise.rb +285 -0
  60. data/test/dummy/config/initializers/devise_token_auth.rb +35 -4
  61. data/test/dummy/db/migrate/20140715061447_devise_token_auth_create_users.rb +0 -7
  62. data/test/dummy/db/migrate/20140715061805_devise_token_auth_create_mangs.rb +0 -7
  63. data/test/dummy/db/migrate/20141222035835_devise_token_auth_create_only_email_users.rb +0 -7
  64. data/test/dummy/db/migrate/20141222053502_devise_token_auth_create_unregisterable_users.rb +0 -7
  65. data/test/dummy/db/migrate/20150708104536_devise_token_auth_create_unconfirmable_users.rb +0 -7
  66. data/test/dummy/db/migrate/20160103235141_devise_token_auth_create_scoped_users.rb +0 -7
  67. data/test/dummy/db/migrate/20160629184441_devise_token_auth_create_lockable_users.rb +0 -7
  68. data/test/dummy/db/schema.rb +1 -28
  69. data/test/factories/users.rb +1 -1
  70. data/test/lib/devise_token_auth/blacklist_test.rb +11 -0
  71. data/test/lib/devise_token_auth/token_factory_test.rb +191 -0
  72. data/test/lib/generators/devise_token_auth/install_generator_test.rb +51 -31
  73. data/test/lib/generators/devise_token_auth/install_generator_with_namespace_test.rb +51 -31
  74. data/test/models/concerns/mongoid_support_test.rb +31 -0
  75. data/test/models/concerns/tokens_serialization_test.rb +70 -0
  76. data/test/models/only_email_user_test.rb +0 -8
  77. data/test/models/user_test.rb +1 -33
  78. data/test/test_helper.rb +12 -2
  79. metadata +105 -25
  80. data/config/initializers/devise.rb +0 -198
  81. /data/test/dummy/app/{models → active_record}/lockable_user.rb +0 -0
  82. /data/test/dummy/app/{models → active_record}/mang.rb +0 -0
  83. /data/test/dummy/app/{models → active_record}/only_email_user.rb +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 916c84285bb6b805d3a70a5adc8e86d83efb348e
4
- data.tar.gz: 38deed793c1466de04cd75ab4861627a5eb18447
2
+ SHA256:
3
+ metadata.gz: 25a0c261827b5f9e1f7dccc40b782a5321d34c50a730fac7bdf9f2c281c397d9
4
+ data.tar.gz: dfee96bd1789d025ea52a83573d90d0ae784e4c63723d2ea864d17eea8fdbaf3
5
5
  SHA512:
6
- metadata.gz: 4b631710faf5afc08a2f0f0fc89a96e63c7fe07d0c7a985a19d3b5c0a18801401afe67525aa6e0a078195ca4d24c58b6a6651da667c2a7a7f40723d4974dc850
7
- data.tar.gz: 8707ad62656749fc88de275533456b93c17545f854e40f03920365c2ba9a11c170af44787118c4d8bc59ef593c5535ce8e09c512338c0de8af860c7e2500746f
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
- * [Angular2-Token](https://github.com/neroniaky/angular2-token) for [Angular2](https://github.com/angular/angular)
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://angular2-token.herokuapp.com) of this app running with the [Angular2-Token](https://github.com/neroniaky/angular2-token) service and [Angular2](https://github.com/angular/angular).
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
- # fix for mysql default case insensitivity
24
- q = "#{field.to_s} = ? AND provider='#{provider.to_s}'"
25
- if ActiveRecord::Base.connection.adapter_name.downcase.starts_with? 'mysql'
26
- q = 'BINARY ' + q
27
- end
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
- mapping = Devise.mappings[m]
35
- else
36
- mapping = Devise.mappings[resource_name] || Devise.mappings.values.first
37
- end
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
- @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
 
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 = request.headers[uid_name] || params[uid_name]
53
- @token ||= request.headers[access_token_name] || params[access_token_name]
54
- @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]
55
43
 
56
- # client_id isn't required, set to 'default' if absent
57
- @client_id ||= 'default'
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[@client_id].nil?
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 client_id
75
- unless @token
76
- @client_id = nil
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.find_by(uid: uid)
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, @client_id)
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: :user)
75
+ bypass_sign_in(user, scope: scope)
89
76
  else
90
- sign_in(:user, user, store: false, event: :fetch, bypass: DeviseTokenAuth.bypass_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
- @client_id = nil
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
- return unless @resource && @client_id
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[@client_id].nil?
97
+ return if @resource.reload.tokens[@token.client].nil?
112
98
 
113
- auth_header = @resource.build_auth_header(@token, @client_id)
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
- ensure_pristine_resource do
134
- # Lock the user record during any auth_header updates to ensure
135
- # we don't have write contention from multiple threads
136
- @resource.with_lock do
137
- # should not append auth header if @resource related token was
138
- # cleared by sign out in the meantime
139
- return if @used_auth_by_token && @resource.tokens[@client_id].nil?
140
-
141
- # update the response header
142
- response.headers.merge!(auth_header_from_batch_request)
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, client_id)
131
+ def is_batch_request?(user, client)
148
132
  !params[:unbatch] &&
149
- user.tokens[client_id] &&
150
- user.tokens[client_id]['updated_at'] &&
151
- Time.parse(user.tokens[client_id]['updated_at']) > @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
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, @client_id)
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, @client_id)
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(@client_id)
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
- sign_in(@resource)
17
- @resource.save!
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
- # give redirect value from params priority
27
- @redirect_url = params[:redirect_url]
14
+ if signed_in?(resource_name)
15
+ token = signed_in_resource.create_token
28
16
 
29
- # fall back to default value if provided
30
- @redirect_url ||= DeviseTokenAuth.default_confirm_success_url
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(@resource.build_auth_url(@redirect_url, redirect_headers))
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 = [request.env['omniauth.params']['namespace_name'],
16
- request.env['omniauth.params']['resource_class'].underscore.gsub('/', '_')].compact.join('_')
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.attributes.keys)
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: @token,
160
- client_id: @client_id,
161
- uid: @resource.uid,
162
- expiry: @expiry,
163
- config: @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
- @client_id, @token, @expiry = @resource.create_token
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
- @oauth_registration = true
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
- extra_params = whitelisted_params
234
- @resource.assign_attributes(extra_params) if extra_params
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
- client_id, token = @resource.create_token
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
- client_id,
55
+ redirect_headers = build_redirect_headers(token.token,
56
+ token.client,
65
57
  redirect_header_options)
66
- redirect_to(@resource.build_auth_url(params[:redirect_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
- 'update_attributes'
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 render_create_error_not_allowed_redirect_url
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