devise_token_auth 1.0.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.
- checksums.yaml +5 -5
- data/README.md +4 -2
- data/app/controllers/devise_token_auth/application_controller.rb +2 -3
- data/app/controllers/devise_token_auth/concerns/resource_finder.rb +11 -12
- data/app/controllers/devise_token_auth/concerns/set_user_by_token.rb +41 -57
- data/app/controllers/devise_token_auth/confirmations_controller.rb +63 -20
- data/app/controllers/devise_token_auth/omniauth_callbacks_controller.rb +77 -29
- data/app/controllers/devise_token_auth/passwords_controller.rb +44 -30
- data/app/controllers/devise_token_auth/registrations_controller.rb +33 -40
- data/app/controllers/devise_token_auth/sessions_controller.rb +5 -5
- data/app/controllers/devise_token_auth/unlocks_controller.rb +4 -4
- data/app/models/devise_token_auth/concerns/active_record_support.rb +14 -0
- data/app/models/devise_token_auth/concerns/confirmable_support.rb +28 -0
- data/app/models/devise_token_auth/concerns/mongoid_support.rb +19 -0
- data/app/models/devise_token_auth/concerns/tokens_serialization.rb +31 -0
- data/app/models/devise_token_auth/concerns/user.rb +51 -70
- data/app/models/devise_token_auth/concerns/user_omniauth_callbacks.rb +6 -3
- data/app/validators/{email_validator.rb → devise_token_auth_email_validator.rb} +2 -2
- data/config/locales/da-DK.yml +2 -0
- data/config/locales/de.yml +2 -0
- data/config/locales/en.yml +7 -0
- data/config/locales/es.yml +2 -0
- data/config/locales/fr.yml +2 -0
- data/config/locales/he.yml +52 -0
- data/config/locales/it.yml +2 -0
- data/config/locales/ja.yml +4 -2
- data/config/locales/ko.yml +51 -0
- data/config/locales/nl.yml +2 -0
- data/config/locales/pl.yml +6 -3
- data/config/locales/pt-BR.yml +2 -0
- data/config/locales/pt.yml +6 -3
- data/config/locales/ro.yml +2 -0
- data/config/locales/ru.yml +2 -0
- data/config/locales/sq.yml +2 -0
- data/config/locales/sv.yml +2 -0
- data/config/locales/uk.yml +2 -0
- data/config/locales/vi.yml +2 -0
- data/config/locales/zh-CN.yml +2 -0
- data/config/locales/zh-HK.yml +2 -0
- data/config/locales/zh-TW.yml +2 -0
- data/lib/devise_token_auth/blacklist.rb +2 -0
- data/lib/devise_token_auth/controllers/helpers.rb +5 -9
- data/lib/devise_token_auth/engine.rb +7 -1
- data/lib/devise_token_auth/rails/routes.rb +16 -11
- data/lib/devise_token_auth/token_factory.rb +126 -0
- data/lib/devise_token_auth/url.rb +3 -0
- data/lib/devise_token_auth/version.rb +1 -1
- data/lib/devise_token_auth.rb +6 -3
- data/lib/generators/devise_token_auth/USAGE +1 -1
- data/lib/generators/devise_token_auth/install_generator.rb +7 -91
- data/lib/generators/devise_token_auth/install_generator_helpers.rb +98 -0
- data/lib/generators/devise_token_auth/install_mongoid_generator.rb +46 -0
- data/lib/generators/devise_token_auth/templates/devise_token_auth.rb +10 -0
- data/lib/generators/devise_token_auth/templates/devise_token_auth_create_users.rb.erb +1 -8
- data/lib/generators/devise_token_auth/templates/user.rb.erb +2 -2
- data/lib/generators/devise_token_auth/templates/user_mongoid.rb.erb +56 -0
- data/test/controllers/custom/custom_confirmations_controller_test.rb +1 -1
- data/test/controllers/demo_user_controller_test.rb +2 -2
- data/test/controllers/devise_token_auth/confirmations_controller_test.rb +83 -19
- data/test/controllers/devise_token_auth/omniauth_callbacks_controller_test.rb +109 -42
- data/test/controllers/devise_token_auth/passwords_controller_test.rb +227 -102
- data/test/controllers/devise_token_auth/registrations_controller_test.rb +34 -7
- data/test/controllers/devise_token_auth/sessions_controller_test.rb +0 -38
- data/test/controllers/devise_token_auth/token_validations_controller_test.rb +2 -1
- data/test/dummy/app/active_record/confirmable_user.rb +11 -0
- data/test/dummy/app/{models → active_record}/scoped_user.rb +2 -2
- data/test/dummy/app/{models → active_record}/unconfirmable_user.rb +1 -2
- data/test/dummy/app/{models → active_record}/unregisterable_user.rb +3 -3
- data/test/dummy/app/active_record/user.rb +6 -0
- data/test/dummy/app/controllers/overrides/confirmations_controller.rb +3 -3
- data/test/dummy/app/controllers/overrides/passwords_controller.rb +3 -3
- data/test/dummy/app/controllers/overrides/registrations_controller.rb +1 -1
- data/test/dummy/app/controllers/overrides/sessions_controller.rb +2 -2
- data/test/dummy/app/models/{user.rb → concerns/favorite_color.rb} +7 -8
- data/test/dummy/app/mongoid/confirmable_user.rb +52 -0
- data/test/dummy/app/mongoid/lockable_user.rb +38 -0
- data/test/dummy/app/mongoid/mang.rb +46 -0
- data/test/dummy/app/mongoid/only_email_user.rb +33 -0
- data/test/dummy/app/mongoid/scoped_user.rb +50 -0
- data/test/dummy/app/mongoid/unconfirmable_user.rb +44 -0
- data/test/dummy/app/mongoid/unregisterable_user.rb +47 -0
- data/test/dummy/app/mongoid/user.rb +49 -0
- data/test/dummy/app/views/layouts/application.html.erb +0 -2
- data/test/dummy/config/application.rb +22 -1
- data/test/dummy/config/boot.rb +4 -0
- data/test/dummy/config/environments/development.rb +0 -10
- data/test/dummy/config/environments/production.rb +0 -16
- data/test/dummy/config/initializers/devise.rb +285 -0
- data/test/dummy/config/initializers/devise_token_auth.rb +35 -4
- data/test/dummy/config/initializers/figaro.rb +1 -1
- data/test/dummy/config/initializers/omniauth.rb +1 -0
- data/test/dummy/config/routes.rb +2 -0
- data/test/dummy/db/migrate/20140715061447_devise_token_auth_create_users.rb +0 -7
- data/test/dummy/db/migrate/20140715061805_devise_token_auth_create_mangs.rb +0 -7
- data/test/dummy/db/migrate/20141222035835_devise_token_auth_create_only_email_users.rb +0 -7
- data/test/dummy/db/migrate/20141222053502_devise_token_auth_create_unregisterable_users.rb +0 -7
- data/test/dummy/db/migrate/20150708104536_devise_token_auth_create_unconfirmable_users.rb +0 -7
- data/test/dummy/db/migrate/20160103235141_devise_token_auth_create_scoped_users.rb +0 -7
- data/test/dummy/db/migrate/20160629184441_devise_token_auth_create_lockable_users.rb +0 -7
- data/test/dummy/db/migrate/20190924101113_devise_token_auth_create_confirmable_users.rb +49 -0
- data/test/dummy/db/schema.rb +26 -28
- data/test/dummy/tmp/generators/app/models/azpire/v1/human_resource/user.rb +9 -0
- data/test/dummy/tmp/generators/config/initializers/devise_token_auth.rb +60 -0
- data/test/dummy/tmp/generators/db/migrate/20210126004321_devise_token_auth_create_azpire_v1_human_resource_users.rb +49 -0
- data/test/factories/users.rb +3 -2
- data/test/lib/devise_token_auth/blacklist_test.rb +11 -0
- data/test/lib/devise_token_auth/rails/custom_routes_test.rb +29 -0
- data/test/lib/devise_token_auth/rails/routes_test.rb +87 -0
- data/test/lib/devise_token_auth/token_factory_test.rb +191 -0
- data/test/lib/devise_token_auth/url_test.rb +2 -2
- data/test/lib/generators/devise_token_auth/install_generator_test.rb +51 -31
- data/test/lib/generators/devise_token_auth/install_generator_with_namespace_test.rb +51 -31
- data/test/models/concerns/mongoid_support_test.rb +31 -0
- data/test/models/concerns/tokens_serialization_test.rb +104 -0
- data/test/models/confirmable_user_test.rb +35 -0
- data/test/models/only_email_user_test.rb +0 -8
- data/test/models/user_test.rb +1 -33
- data/test/test_helper.rb +13 -3
- metadata +125 -32
- data/config/initializers/devise.rb +0 -198
- data/test/dummy/config/initializers/assets.rb +0 -10
- data/test/dummy/tmp/generators/app/views/devise/mailer/confirmation_instructions.html.erb +0 -5
- data/test/dummy/tmp/generators/app/views/devise/mailer/reset_password_instructions.html.erb +0 -8
- /data/test/dummy/app/{models → active_record}/lockable_user.rb +0 -0
- /data/test/dummy/app/{models → active_record}/mang.rb +0 -0
- /data/test/dummy/app/{models → active_record}/only_email_user.rb +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7a64d8fc927471b28cec59b5191e06ef4d2fd7152dadcc9f49b5c512611ba4e6
|
4
|
+
data.tar.gz: 3ac708a845da1df134975f293a7db9e8977cd116c0d8dbdc7650e249bb99df82
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 51a73c32d0debfc772ff7f7b8b5a524a67fde1676bb66a1d77d243c451a3ca5b375c593287bfb1be2abff7ff881947e39470a6d46421c73f112d4a5b1d774858
|
7
|
+
data.tar.gz: a79f4e32938818a92fddbcb88eb918da3c53afe8bf304769fa9d02f1841ed67093ab0bf7b004263094737da15d3dae222b785c70ef233e1b6f43a07a7f49f2b5
|
data/README.md
CHANGED
@@ -19,7 +19,7 @@ Also, it maintains a session for each client/device, so you can have as many ses
|
|
19
19
|
|
20
20
|
* Seamless integration with:
|
21
21
|
* [ng-token-auth](https://github.com/lynndylanhurley/ng-token-auth) for [AngularJS](https://github.com/angular/angular.js)
|
22
|
-
* [
|
22
|
+
* [Angular-Token](https://github.com/neroniaky/angular-token) for [Angular](https://github.com/angular/angular)
|
23
23
|
* [redux-token-auth](https://github.com/kylecorbelli/redux-token-auth) for [React with Redux](https://github.com/reactjs/react-redux)
|
24
24
|
* [jToker](https://github.com/lynndylanhurley/j-toker) for [jQuery](https://jquery.com/)
|
25
25
|
* Oauth2 authentication using [OmniAuth](https://github.com/intridea/omniauth).
|
@@ -65,11 +65,13 @@ Please read the [issue template](https://github.com/lynndylanhurley/devise_token
|
|
65
65
|
|
66
66
|
See our [Contribution Guidelines](https://github.com/lynndylanhurley/devise_token_auth/blob/master/.github/CONTRIBUTING.md). Feel free to submit pull requests, review pull requests, or review open issues. If you'd like to get in contact, [Zach Feldman](https://github.com/zachfeldman) has been wrangling this effort, you can reach him with his name @gmail. Further discussion of this in [this issue](https://github.com/lynndylanhurley/devise_token_auth/issues/969).
|
67
67
|
|
68
|
+
We have some bounties for some issues, [check them out](https://github.com/lynndylanhurley/devise_token_auth/issues?q=is%3Aopen+is%3Aissue+label%3Abounty)!
|
69
|
+
|
68
70
|
## Live Demos
|
69
71
|
|
70
72
|
[Here is a demo](http://ng-token-auth-demo.herokuapp.com/) of this app running with the [ng-token-auth](https://github.com/lynndylanhurley/ng-token-auth) module and [AngularJS](https://github.com/angular/angular.js).
|
71
73
|
|
72
|
-
[Here is a demo](https://
|
74
|
+
[Here is a demo](https://stackblitz.com/github/neroniaky/angular-token) of this app running with the [Angular-Token](https://github.com/neroniaky/angular-token) service and [Angular](https://github.com/angular/angular).
|
73
75
|
|
74
76
|
[Here is a demo](https://j-toker-demo.herokuapp.com/) of this app using the [jToker](https://github.com/lynndylanhurley/j-toker) plugin and [React](http://facebook.github.io/react/).
|
75
77
|
|
@@ -3,7 +3,6 @@
|
|
3
3
|
module DeviseTokenAuth
|
4
4
|
class ApplicationController < DeviseController
|
5
5
|
include DeviseTokenAuth::Concerns::SetUserByToken
|
6
|
-
include DeviseTokenAuth::Concerns::ResourceFinder
|
7
6
|
|
8
7
|
def resource_data(opts = {})
|
9
8
|
response_data = opts[:resource_json] || @resource.as_json
|
@@ -17,8 +16,8 @@ module DeviseTokenAuth
|
|
17
16
|
|
18
17
|
protected
|
19
18
|
|
20
|
-
def blacklisted_redirect_url?
|
21
|
-
DeviseTokenAuth.redirect_whitelist && !DeviseTokenAuth::Url.whitelisted?(
|
19
|
+
def blacklisted_redirect_url?(redirect_url)
|
20
|
+
DeviseTokenAuth.redirect_whitelist && !DeviseTokenAuth::Url.whitelisted?(redirect_url)
|
22
21
|
end
|
23
22
|
|
24
23
|
def build_redirect_headers(access_token, client, redirect_header_options = {})
|
@@ -20,21 +20,20 @@ module DeviseTokenAuth::Concerns::ResourceFinder
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def find_resource(field, value)
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
@resource = resource_class.where(q, value).first
|
23
|
+
@resource = if resource_class.try(:connection_config).try(:[], :adapter).try(:include?, 'mysql')
|
24
|
+
# fix for mysql default case insensitivity
|
25
|
+
resource_class.where("BINARY #{field} = ? AND provider= ?", value, provider).first
|
26
|
+
else
|
27
|
+
resource_class.dta_find_by(field => value, 'provider' => provider)
|
28
|
+
end
|
30
29
|
end
|
31
30
|
|
32
31
|
def resource_class(m = nil)
|
33
|
-
if m
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
32
|
+
mapping = if m
|
33
|
+
Devise.mappings[m]
|
34
|
+
else
|
35
|
+
Devise.mappings[resource_name] || Devise.mappings.values.first
|
36
|
+
end
|
38
37
|
|
39
38
|
mapping.to
|
40
39
|
end
|
@@ -17,24 +17,11 @@ module DeviseTokenAuth::Concerns::SetUserByToken
|
|
17
17
|
@used_auth_by_token = true
|
18
18
|
|
19
19
|
# initialize instance variables
|
20
|
-
@
|
20
|
+
@token ||= DeviseTokenAuth::TokenFactory.new
|
21
21
|
@resource ||= nil
|
22
|
-
@token ||= nil
|
23
22
|
@is_batch_request ||= nil
|
24
23
|
end
|
25
24
|
|
26
|
-
def ensure_pristine_resource
|
27
|
-
if @resource.changed?
|
28
|
-
# Stash pending changes in the resource before reloading.
|
29
|
-
changes = @resource.changes
|
30
|
-
@resource.reload
|
31
|
-
end
|
32
|
-
yield
|
33
|
-
ensure
|
34
|
-
# Reapply pending changes
|
35
|
-
@resource.assign_attributes(changes) if changes
|
36
|
-
end
|
37
|
-
|
38
25
|
# user auth
|
39
26
|
def set_user_by_token(mapping = nil)
|
40
27
|
# determine target authentication class
|
@@ -49,17 +36,18 @@ module DeviseTokenAuth::Concerns::SetUserByToken
|
|
49
36
|
client_name = DeviseTokenAuth.headers_names[:'client']
|
50
37
|
|
51
38
|
# parse header for values necessary for authentication
|
52
|
-
uid
|
53
|
-
@token
|
54
|
-
@
|
39
|
+
uid = request.headers[uid_name] || params[uid_name]
|
40
|
+
@token = DeviseTokenAuth::TokenFactory.new unless @token
|
41
|
+
@token.token ||= request.headers[access_token_name] || params[access_token_name]
|
42
|
+
@token.client ||= request.headers[client_name] || params[client_name]
|
55
43
|
|
56
|
-
#
|
57
|
-
@
|
44
|
+
# client isn't required, set to 'default' if absent
|
45
|
+
@token.client ||= 'default'
|
58
46
|
|
59
47
|
# check for an existing user, authenticated via warden/devise, if enabled
|
60
48
|
if DeviseTokenAuth.enable_standard_devise_support
|
61
|
-
devise_warden_user = warden.user(
|
62
|
-
if devise_warden_user && devise_warden_user.tokens[@
|
49
|
+
devise_warden_user = warden.user(mapping)
|
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,53 +59,51 @@ module DeviseTokenAuth::Concerns::SetUserByToken
|
|
71
59
|
# user has already been found and authenticated
|
72
60
|
return @resource if @resource && @resource.is_a?(rc)
|
73
61
|
|
74
|
-
# ensure we clear the
|
75
|
-
unless @token
|
76
|
-
@
|
62
|
+
# ensure we clear the client
|
63
|
+
unless @token.present?
|
64
|
+
@token.client = nil
|
77
65
|
return
|
78
66
|
end
|
79
67
|
|
80
|
-
return false unless @token
|
81
|
-
|
82
68
|
# mitigate timing attacks by finding by uid instead of auth token
|
83
|
-
user = uid && rc.
|
69
|
+
user = uid && rc.dta_find_by(uid: uid)
|
70
|
+
scope = rc.to_s.underscore.to_sym
|
84
71
|
|
85
|
-
if user && user.valid_token?(@token, @
|
72
|
+
if user && user.valid_token?(@token.token, @token.client)
|
86
73
|
# sign_in with bypass: true will be deprecated in the next version of Devise
|
87
74
|
if respond_to?(:bypass_sign_in) && DeviseTokenAuth.bypass_sign_in
|
88
|
-
bypass_sign_in(user, scope:
|
75
|
+
bypass_sign_in(user, scope: scope)
|
89
76
|
else
|
90
|
-
sign_in(
|
77
|
+
sign_in(scope, user, store: false, event: :fetch, bypass: DeviseTokenAuth.bypass_sign_in)
|
91
78
|
end
|
92
79
|
return @resource = user
|
93
80
|
else
|
94
81
|
# zero all values previously set values
|
95
|
-
@
|
82
|
+
@token.client = nil
|
96
83
|
return @resource = nil
|
97
84
|
end
|
98
85
|
end
|
99
86
|
|
100
87
|
def update_auth_header
|
101
88
|
# cannot save object if model has invalid params
|
89
|
+
return unless @resource && @token.client
|
102
90
|
|
103
|
-
|
104
|
-
|
105
|
-
# Generate new client_id with existing authentication
|
106
|
-
@client_id = nil unless @used_auth_by_token
|
91
|
+
# Generate new client with existing authentication
|
92
|
+
@token.client = nil unless @used_auth_by_token
|
107
93
|
|
108
94
|
if @used_auth_by_token && !DeviseTokenAuth.change_headers_on_each_request
|
109
95
|
# should not append auth header if @resource related token was
|
110
96
|
# cleared by sign out in the meantime
|
111
|
-
return if @resource.reload.tokens[@
|
97
|
+
return if @resource.reload.tokens[@token.client].nil?
|
112
98
|
|
113
|
-
auth_header = @resource.build_auth_header(@token, @
|
99
|
+
auth_header = @resource.build_auth_header(@token.token, @token.client)
|
114
100
|
|
115
101
|
# update the response header
|
116
102
|
response.headers.merge!(auth_header)
|
117
103
|
|
118
104
|
else
|
119
105
|
unless @resource.reload.valid?
|
120
|
-
@resource =
|
106
|
+
@resource = @resource.class.find(@resource.to_param) # errors remain after reload
|
121
107
|
# if we left the model in a bad state, something is wrong in our app
|
122
108
|
unless @resource.valid?
|
123
109
|
raise DeviseTokenAuth::Errors::InvalidModel, "Cannot set auth token in invalid model. Errors: #{@resource.errors.full_messages}"
|
@@ -130,37 +116,35 @@ module DeviseTokenAuth::Concerns::SetUserByToken
|
|
130
116
|
private
|
131
117
|
|
132
118
|
def refresh_headers
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
@resource
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
end # end lock
|
144
|
-
end # end ensure_pristine_resource
|
119
|
+
# Lock the user record during any auth_header updates to ensure
|
120
|
+
# we don't have write contention from multiple threads
|
121
|
+
@resource.with_lock do
|
122
|
+
# should not append auth header if @resource related token was
|
123
|
+
# cleared by sign out in the meantime
|
124
|
+
return if @used_auth_by_token && @resource.tokens[@token.client].nil?
|
125
|
+
|
126
|
+
# update the response header
|
127
|
+
response.headers.merge!(auth_header_from_batch_request)
|
128
|
+
end # end lock
|
145
129
|
end
|
146
130
|
|
147
|
-
def is_batch_request?(user,
|
131
|
+
def is_batch_request?(user, client)
|
148
132
|
!params[:unbatch] &&
|
149
|
-
user.tokens[
|
150
|
-
user.tokens[
|
151
|
-
|
133
|
+
user.tokens[client] &&
|
134
|
+
user.tokens[client]['updated_at'] &&
|
135
|
+
user.tokens[client]['updated_at'].to_time > @request_started_at - DeviseTokenAuth.batch_request_buffer_throttle
|
152
136
|
end
|
153
137
|
|
154
138
|
def auth_header_from_batch_request
|
155
139
|
# determine batch request status after request processing, in case
|
156
140
|
# another processes has updated it during that processing
|
157
|
-
@is_batch_request = is_batch_request?(@resource, @
|
141
|
+
@is_batch_request = is_batch_request?(@resource, @token.client)
|
158
142
|
|
159
143
|
auth_header = {}
|
160
144
|
# extend expiration of batch buffer to account for the duration of
|
161
145
|
# this request
|
162
146
|
if @is_batch_request
|
163
|
-
auth_header = @resource.extend_batch_buffer(@token, @
|
147
|
+
auth_header = @resource.extend_batch_buffer(@token.token, @token.client)
|
164
148
|
|
165
149
|
# Do not return token for batch requests to avoid invalidated
|
166
150
|
# tokens returned to the client in case of race conditions.
|
@@ -171,7 +155,7 @@ module DeviseTokenAuth::Concerns::SetUserByToken
|
|
171
155
|
auth_header[DeviseTokenAuth.headers_names[:"expiry"]] = ' '
|
172
156
|
else
|
173
157
|
# update Authorization response header with new token
|
174
|
-
auth_header = @resource.create_new_auth_token(@
|
158
|
+
auth_header = @resource.create_new_auth_token(@token.client)
|
175
159
|
end
|
176
160
|
auth_header
|
177
161
|
end
|
@@ -2,38 +2,81 @@
|
|
2
2
|
|
3
3
|
module DeviseTokenAuth
|
4
4
|
class ConfirmationsController < DeviseTokenAuth::ApplicationController
|
5
|
-
def show
|
6
|
-
@resource = resource_class.confirm_by_token(params[:confirmation_token])
|
7
|
-
|
8
|
-
if @resource && @resource.id
|
9
|
-
expiry = nil
|
10
|
-
if defined?(@resource.sign_in_count) && @resource.sign_in_count > 0
|
11
|
-
expiry = (Time.zone.now + 1.second).to_i
|
12
|
-
end
|
13
|
-
|
14
|
-
client_id, token = @resource.create_token expiry: expiry
|
15
5
|
|
16
|
-
|
17
|
-
|
6
|
+
def show
|
7
|
+
@resource = resource_class.confirm_by_token(resource_params[:confirmation_token])
|
18
8
|
|
9
|
+
if @resource.errors.empty?
|
19
10
|
yield @resource if block_given?
|
20
11
|
|
21
12
|
redirect_header_options = { account_confirmation_success: true }
|
22
|
-
redirect_headers = build_redirect_headers(token,
|
23
|
-
client_id,
|
24
|
-
redirect_header_options)
|
25
13
|
|
26
|
-
|
27
|
-
|
14
|
+
if signed_in?(resource_name)
|
15
|
+
token = signed_in_resource.create_token
|
16
|
+
signed_in_resource.save!
|
28
17
|
|
29
|
-
|
30
|
-
|
18
|
+
redirect_headers = build_redirect_headers(token.token,
|
19
|
+
token.client,
|
20
|
+
redirect_header_options)
|
31
21
|
|
22
|
+
redirect_to_link = signed_in_resource.build_auth_url(redirect_url, redirect_headers)
|
23
|
+
else
|
24
|
+
redirect_to_link = DeviseTokenAuth::Url.generate(redirect_url, redirect_header_options)
|
25
|
+
end
|
32
26
|
|
33
|
-
redirect_to(
|
27
|
+
redirect_to(redirect_to_link)
|
34
28
|
else
|
35
29
|
raise ActionController::RoutingError, 'Not Found'
|
36
30
|
end
|
37
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
|
+
|
38
81
|
end
|
39
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
|
|
@@ -12,11 +15,8 @@ module DeviseTokenAuth
|
|
12
15
|
|
13
16
|
# derive target redirect route from 'resource_class' param, which was set
|
14
17
|
# before authentication.
|
15
|
-
devise_mapping =
|
16
|
-
|
17
|
-
path = "#{Devise.mappings[devise_mapping.to_sym].fullpath}/#{params[:provider]}/callback"
|
18
|
-
klass = request.scheme == 'https' ? URI::HTTPS : URI::HTTP
|
19
|
-
redirect_route = klass.build(host: request.host, port: request.port, path: path).to_s
|
18
|
+
devise_mapping = get_devise_mapping
|
19
|
+
redirect_route = get_redirect_route(devise_mapping)
|
20
20
|
|
21
21
|
# preserve omniauth info for success route. ignore 'extra' in twitter
|
22
22
|
# auth response to avoid CookieOverflow.
|
@@ -26,6 +26,34 @@ module DeviseTokenAuth
|
|
26
26
|
redirect_to redirect_route
|
27
27
|
end
|
28
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
|
+
|
29
57
|
def omniauth_success
|
30
58
|
get_resource_from_auth_hash
|
31
59
|
set_token_on_resource
|
@@ -50,6 +78,11 @@ module DeviseTokenAuth
|
|
50
78
|
render_data_or_redirect('authFailure', error: @error)
|
51
79
|
end
|
52
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
|
+
|
53
86
|
protected
|
54
87
|
|
55
88
|
# this will be determined differently depending on the action that calls
|
@@ -79,7 +112,8 @@ module DeviseTokenAuth
|
|
79
112
|
|
80
113
|
# break out provider attribute assignment for easy method extension
|
81
114
|
def assign_provider_attrs(user, auth_hash)
|
82
|
-
attrs = auth_hash['info'].
|
115
|
+
attrs = auth_hash['info'].to_hash
|
116
|
+
attrs = attrs.slice(*user.attribute_names)
|
83
117
|
user.assign_attributes(attrs)
|
84
118
|
end
|
85
119
|
|
@@ -112,10 +146,18 @@ module DeviseTokenAuth
|
|
112
146
|
omniauth_params['omniauth_window_type']
|
113
147
|
end
|
114
148
|
|
115
|
-
def
|
149
|
+
def unsafe_auth_origin_url
|
116
150
|
omniauth_params['auth_origin_url'] || omniauth_params['origin']
|
117
151
|
end
|
118
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
|
+
|
119
161
|
# in the success case, omniauth_window_type is in the omniauth_params.
|
120
162
|
# in the failure case, it is in a query param. See monkey patch above
|
121
163
|
def omniauth_window_type
|
@@ -136,16 +178,6 @@ module DeviseTokenAuth
|
|
136
178
|
true
|
137
179
|
end
|
138
180
|
|
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
181
|
def set_random_password
|
150
182
|
# set crazy password for new oauth users. this is only used to prevent
|
151
183
|
# access via email sign-in.
|
@@ -156,11 +188,11 @@ module DeviseTokenAuth
|
|
156
188
|
|
157
189
|
def create_auth_params
|
158
190
|
@auth_params = {
|
159
|
-
auth_token:
|
160
|
-
client_id:
|
161
|
-
uid:
|
162
|
-
expiry:
|
163
|
-
config:
|
191
|
+
auth_token: @token.token,
|
192
|
+
client_id: @token.client,
|
193
|
+
uid: @resource.uid,
|
194
|
+
expiry: @token.expiry,
|
195
|
+
config: @config
|
164
196
|
}
|
165
197
|
@auth_params.merge!(oauth_registration: true) if @oauth_registration
|
166
198
|
@auth_params
|
@@ -168,11 +200,16 @@ module DeviseTokenAuth
|
|
168
200
|
|
169
201
|
def set_token_on_resource
|
170
202
|
@config = omniauth_params['config_name']
|
171
|
-
@
|
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)
|
172
209
|
end
|
173
210
|
|
174
211
|
def render_data(message, data)
|
175
|
-
@data = data.merge(message: message)
|
212
|
+
@data = data.merge(message: ActionController::Base.helpers.sanitize(message))
|
176
213
|
render layout: nil, template: 'devise_token_auth/omniauth_external_window'
|
177
214
|
end
|
178
215
|
|
@@ -209,11 +246,20 @@ module DeviseTokenAuth
|
|
209
246
|
<html>
|
210
247
|
<head></head>
|
211
248
|
<body>
|
212
|
-
#{text}
|
249
|
+
#{ActionController::Base.helpers.sanitize(text)}
|
213
250
|
</body>
|
214
251
|
</html>)
|
215
252
|
end
|
216
253
|
|
254
|
+
def handle_new_resource
|
255
|
+
@oauth_registration = true
|
256
|
+
set_random_password
|
257
|
+
end
|
258
|
+
|
259
|
+
def assign_whitelisted_params?
|
260
|
+
true
|
261
|
+
end
|
262
|
+
|
217
263
|
def get_resource_from_auth_hash
|
218
264
|
# find or create user by provider and provider uid
|
219
265
|
@resource = resource_class.where(
|
@@ -222,18 +268,20 @@ module DeviseTokenAuth
|
|
222
268
|
).first_or_initialize
|
223
269
|
|
224
270
|
if @resource.new_record?
|
225
|
-
|
226
|
-
set_random_password
|
271
|
+
handle_new_resource
|
227
272
|
end
|
228
273
|
|
229
274
|
# sync user info with provider, update/generate auth token
|
230
275
|
assign_provider_attrs(@resource, auth_hash)
|
231
276
|
|
232
277
|
# assign any additional (whitelisted) attributes
|
233
|
-
|
234
|
-
|
278
|
+
if assign_whitelisted_params?
|
279
|
+
extra_params = whitelisted_params
|
280
|
+
@resource.assign_attributes(extra_params) if extra_params
|
281
|
+
end
|
235
282
|
|
236
283
|
@resource
|
237
284
|
end
|
238
285
|
end
|
286
|
+
|
239
287
|
end
|