devise_token_auth 1.2.0 → 1.2.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.
- checksums.yaml +4 -4
- data/app/controllers/devise_token_auth/application_controller.rb +9 -0
- data/app/controllers/devise_token_auth/concerns/set_user_by_token.rb +17 -4
- data/app/controllers/devise_token_auth/confirmations_controller.rb +1 -1
- data/app/controllers/devise_token_auth/omniauth_callbacks_controller.rb +8 -4
- data/app/controllers/devise_token_auth/passwords_controller.rb +5 -1
- data/app/controllers/devise_token_auth/sessions_controller.rb +14 -2
- data/app/controllers/devise_token_auth/unlocks_controller.rb +1 -1
- data/app/models/devise_token_auth/concerns/user.rb +27 -6
- data/app/models/devise_token_auth/concerns/user_omniauth_callbacks.rb +9 -5
- data/app/validators/devise_token_auth_email_validator.rb +9 -1
- data/config/locales/ja.yml +12 -0
- data/lib/devise_token_auth/engine.rb +5 -2
- data/lib/devise_token_auth/rails/routes.rb +2 -2
- data/lib/devise_token_auth/version.rb +1 -1
- data/lib/generators/devise_token_auth/templates/devise_token_auth.rb +3 -0
- data/test/controllers/demo_mang_controller_test.rb +37 -8
- data/test/controllers/demo_user_controller_test.rb +37 -8
- data/test/controllers/devise_token_auth/confirmations_controller_test.rb +12 -3
- data/test/controllers/devise_token_auth/passwords_controller_test.rb +6 -6
- data/test/controllers/devise_token_auth/token_validations_controller_test.rb +41 -1
- data/test/controllers/devise_token_auth/unlocks_controller_test.rb +28 -6
- data/test/dummy/db/schema.rb +5 -5
- data/test/dummy/tmp/generators/app/models/user.rb +11 -0
- data/test/dummy/tmp/generators/db/migrate/20220822003050_devise_token_auth_create_users.rb +49 -0
- data/test/models/user_test.rb +22 -0
- metadata +10 -10
- data/test/dummy/tmp/generators/app/controllers/application_controller.rb +0 -6
- data/test/dummy/tmp/generators/app/models/azpire/v1/human_resource/user.rb +0 -56
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: be08ae7f01121ebe8c6b9b8fe04bcc2bdc83a2c8108452ffc986f1865278e85f
|
4
|
+
data.tar.gz: 272f45dc6f28fba16b6a523f47cbb9ecf3be9c05d4aa644ee0d0998fa5272f43
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc54c90eee4fdf43e6d9b72ca905fc58e4338f1310b289bbede651978bd4f407556392d3d4c61cfaeabf6d4fba179768e02ec9c00bc245b33ba629972676c676
|
7
|
+
data.tar.gz: 00e139ae99fe395580ef8f846cca46516792b68cda0e0201e551e90ca9c70679fcf9519d3682ea82095588e78a93bb2def3db2bebe670a0e96f933e7087fee4b
|
@@ -83,5 +83,14 @@ module DeviseTokenAuth
|
|
83
83
|
I18n.t("devise_token_auth.#{name}.sended", email: email)
|
84
84
|
end
|
85
85
|
end
|
86
|
+
|
87
|
+
# When using a cookie to transport the auth token we can set it immediately in flows such as
|
88
|
+
# reset password and OmniAuth success, rather than making the client scrape the token from
|
89
|
+
# query params (to then send in the initial validate_token request).
|
90
|
+
# TODO: We should be able to stop exposing the token in query params when this method is used
|
91
|
+
def set_token_in_cookie(resource, token)
|
92
|
+
auth_header = resource.build_auth_header(token.token, token.client)
|
93
|
+
cookies[DeviseTokenAuth.cookie_name] = DeviseTokenAuth.cookie_attributes.merge(value: auth_header.to_json)
|
94
|
+
end
|
86
95
|
end
|
87
96
|
end
|
@@ -32,8 +32,13 @@ module DeviseTokenAuth::Concerns::SetUserByToken
|
|
32
32
|
|
33
33
|
# gets the headers names, which was set in the initialize file
|
34
34
|
uid_name = DeviseTokenAuth.headers_names[:'uid']
|
35
|
+
other_uid_name = DeviseTokenAuth.other_uid && DeviseTokenAuth.headers_names[DeviseTokenAuth.other_uid.to_sym]
|
35
36
|
access_token_name = DeviseTokenAuth.headers_names[:'access-token']
|
36
37
|
client_name = DeviseTokenAuth.headers_names[:'client']
|
38
|
+
authorization_name = DeviseTokenAuth.headers_names[:"authorization"]
|
39
|
+
|
40
|
+
# Read Authorization token and decode it if present
|
41
|
+
decoded_authorization_token = decode_bearer_token(request.headers[authorization_name])
|
37
42
|
|
38
43
|
# gets values from cookie if configured and present
|
39
44
|
parsed_auth_cookie = {}
|
@@ -45,10 +50,11 @@ module DeviseTokenAuth::Concerns::SetUserByToken
|
|
45
50
|
end
|
46
51
|
|
47
52
|
# parse header for values necessary for authentication
|
48
|
-
uid = request.headers[uid_name] || params[uid_name] || parsed_auth_cookie[uid_name]
|
53
|
+
uid = request.headers[uid_name] || params[uid_name] || parsed_auth_cookie[uid_name] || decoded_authorization_token[uid_name]
|
54
|
+
other_uid = other_uid_name && request.headers[other_uid_name] || params[other_uid_name] || parsed_auth_cookie[other_uid_name]
|
49
55
|
@token = DeviseTokenAuth::TokenFactory.new unless @token
|
50
|
-
@token.token ||= request.headers[access_token_name] || params[access_token_name] || parsed_auth_cookie[access_token_name]
|
51
|
-
@token.client ||= request.headers[client_name] || params[client_name] || parsed_auth_cookie[client_name]
|
56
|
+
@token.token ||= request.headers[access_token_name] || params[access_token_name] || parsed_auth_cookie[access_token_name] || decoded_authorization_token[access_token_name]
|
57
|
+
@token.client ||= request.headers[client_name] || params[client_name] || parsed_auth_cookie[client_name] || decoded_authorization_token[client_name]
|
52
58
|
|
53
59
|
# client isn't required, set to 'default' if absent
|
54
60
|
@token.client ||= 'default'
|
@@ -75,7 +81,7 @@ module DeviseTokenAuth::Concerns::SetUserByToken
|
|
75
81
|
end
|
76
82
|
|
77
83
|
# mitigate timing attacks by finding by uid instead of auth token
|
78
|
-
user = uid && rc.dta_find_by(uid: uid)
|
84
|
+
user = (uid && rc.dta_find_by(uid: uid)) || (other_uid && rc.dta_find_by("#{DeviseTokenAuth.other_uid}": other_uid))
|
79
85
|
scope = rc.to_s.underscore.to_sym
|
80
86
|
|
81
87
|
if user && user.valid_token?(@token.token, @token.client)
|
@@ -128,6 +134,13 @@ module DeviseTokenAuth::Concerns::SetUserByToken
|
|
128
134
|
|
129
135
|
private
|
130
136
|
|
137
|
+
def decode_bearer_token(bearer_token)
|
138
|
+
return {} if bearer_token.blank?
|
139
|
+
|
140
|
+
encoded_token = bearer_token.split.last # Removes the 'Bearer' from the string
|
141
|
+
JSON.parse(Base64.strict_decode64(encoded_token)) rescue {}
|
142
|
+
end
|
143
|
+
|
131
144
|
def refresh_headers
|
132
145
|
# Lock the user record during any auth_header updates to ensure
|
133
146
|
# we don't have write contention from multiple threads
|
@@ -62,7 +62,7 @@ module DeviseTokenAuth
|
|
62
62
|
|
63
63
|
def render_not_found_error
|
64
64
|
if Devise.paranoid
|
65
|
-
|
65
|
+
render_create_success
|
66
66
|
else
|
67
67
|
render_error(404, I18n.t('devise_token_auth.confirmations.user_not_found', email: @email))
|
68
68
|
end
|
@@ -23,7 +23,7 @@ module DeviseTokenAuth
|
|
23
23
|
session['dta.omniauth.auth'] = request.env['omniauth.auth'].except('extra')
|
24
24
|
session['dta.omniauth.params'] = request.env['omniauth.params']
|
25
25
|
|
26
|
-
redirect_to redirect_route
|
26
|
+
redirect_to redirect_route, status: 307
|
27
27
|
end
|
28
28
|
|
29
29
|
def get_redirect_route(devise_mapping)
|
@@ -45,7 +45,7 @@ module DeviseTokenAuth
|
|
45
45
|
# find the mapping in `omniauth.params`.
|
46
46
|
#
|
47
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
|
48
|
+
# case, there will have been no initial request in which to save
|
49
49
|
# the devise mapping. If you are in a situation like that, and
|
50
50
|
# your app allows for you to determine somehow what the devise
|
51
51
|
# mapping should be (because, for example, it is always the same),
|
@@ -70,6 +70,10 @@ module DeviseTokenAuth
|
|
70
70
|
|
71
71
|
yield @resource if block_given?
|
72
72
|
|
73
|
+
if DeviseTokenAuth.cookie_enabled
|
74
|
+
set_token_in_cookie(@resource, @token)
|
75
|
+
end
|
76
|
+
|
73
77
|
render_data_or_redirect('deliverCredentials', @auth_params.as_json, @resource.as_json)
|
74
78
|
end
|
75
79
|
|
@@ -78,10 +82,10 @@ module DeviseTokenAuth
|
|
78
82
|
render_data_or_redirect('authFailure', error: @error)
|
79
83
|
end
|
80
84
|
|
81
|
-
def validate_auth_origin_url_param
|
85
|
+
def validate_auth_origin_url_param
|
82
86
|
return render_error_not_allowed_auth_origin_url if auth_origin_url && blacklisted_redirect_url?(auth_origin_url)
|
83
87
|
end
|
84
|
-
|
88
|
+
|
85
89
|
|
86
90
|
protected
|
87
91
|
|
@@ -51,6 +51,10 @@ module DeviseTokenAuth
|
|
51
51
|
if require_client_password_reset_token?
|
52
52
|
redirect_to DeviseTokenAuth::Url.generate(@redirect_url, reset_password_token: resource_params[:reset_password_token])
|
53
53
|
else
|
54
|
+
if DeviseTokenAuth.cookie_enabled
|
55
|
+
set_token_in_cookie(@resource, token)
|
56
|
+
end
|
57
|
+
|
54
58
|
redirect_header_options = { reset_password: true }
|
55
59
|
redirect_headers = build_redirect_headers(token.token,
|
56
60
|
token.client,
|
@@ -182,7 +186,7 @@ module DeviseTokenAuth
|
|
182
186
|
|
183
187
|
def render_not_found_error
|
184
188
|
if Devise.paranoid
|
185
|
-
|
189
|
+
render_create_success
|
186
190
|
else
|
187
191
|
render_error(404, I18n.t('devise_token_auth.passwords.user_not_found', email: @email))
|
188
192
|
end
|
@@ -26,8 +26,8 @@ module DeviseTokenAuth
|
|
26
26
|
if (@resource.respond_to?(:valid_for_authentication?) && !@resource.valid_for_authentication? { valid_password }) || !valid_password
|
27
27
|
return render_create_error_bad_credentials
|
28
28
|
end
|
29
|
-
|
30
|
-
|
29
|
+
|
30
|
+
create_and_assign_token
|
31
31
|
|
32
32
|
sign_in(:user, @resource, store: false, bypass: false)
|
33
33
|
|
@@ -133,5 +133,17 @@ module DeviseTokenAuth
|
|
133
133
|
def resource_params
|
134
134
|
params.permit(*params_for_resource(:sign_in))
|
135
135
|
end
|
136
|
+
|
137
|
+
def create_and_assign_token
|
138
|
+
if @resource.respond_to?(:with_lock)
|
139
|
+
@resource.with_lock do
|
140
|
+
@token = @resource.create_token
|
141
|
+
@resource.save!
|
142
|
+
end
|
143
|
+
else
|
144
|
+
@token = @resource.create_token
|
145
|
+
@resource.save!
|
146
|
+
end
|
147
|
+
end
|
136
148
|
end
|
137
149
|
end
|
@@ -80,7 +80,7 @@ module DeviseTokenAuth
|
|
80
80
|
|
81
81
|
def render_not_found_error
|
82
82
|
if Devise.paranoid
|
83
|
-
|
83
|
+
render_create_success
|
84
84
|
else
|
85
85
|
render_error(404, I18n.t('devise_token_auth.unlocks.user_not_found', email: @email))
|
86
86
|
end
|
@@ -120,6 +120,7 @@ module DeviseTokenAuth::Concerns::User
|
|
120
120
|
# ghetto HashWithIndifferentAccess
|
121
121
|
expiry = tokens[client]['expiry'] || tokens[client][:expiry]
|
122
122
|
token_hash = tokens[client]['token'] || tokens[client][:token]
|
123
|
+
previous_token_hash = tokens[client]['previous_token'] || tokens[client][:previous_token]
|
123
124
|
|
124
125
|
return true if (
|
125
126
|
# ensure that expiry and token are set
|
@@ -129,11 +130,24 @@ module DeviseTokenAuth::Concerns::User
|
|
129
130
|
DateTime.strptime(expiry.to_s, '%s') > Time.zone.now &&
|
130
131
|
|
131
132
|
# ensure that the token is valid
|
132
|
-
|
133
|
+
(
|
134
|
+
# check if the latest token matches
|
135
|
+
does_token_match?(token_hash, token) ||
|
136
|
+
|
137
|
+
# check if the previous token matches
|
138
|
+
does_token_match?(previous_token_hash, token)
|
139
|
+
)
|
133
140
|
)
|
134
141
|
end
|
135
142
|
|
136
|
-
#
|
143
|
+
# check if the hash of received token matches the stored token
|
144
|
+
def does_token_match?(token_hash, token)
|
145
|
+
return false if token_hash.nil?
|
146
|
+
|
147
|
+
DeviseTokenAuth::Concerns::User.tokens_match?(token_hash, token)
|
148
|
+
end
|
149
|
+
|
150
|
+
# allow batch requests to use the last token
|
137
151
|
def token_can_be_reused?(token, client)
|
138
152
|
# ghetto HashWithIndifferentAccess
|
139
153
|
updated_at = tokens[client]['updated_at'] || tokens[client][:updated_at]
|
@@ -143,7 +157,7 @@ module DeviseTokenAuth::Concerns::User
|
|
143
157
|
# ensure that the last token and its creation time exist
|
144
158
|
updated_at && last_token_hash &&
|
145
159
|
|
146
|
-
# ensure that
|
160
|
+
# ensure that last token falls within the batch buffer throttle time of the last request
|
147
161
|
updated_at.to_time > Time.zone.now - DeviseTokenAuth.batch_request_buffer_throttle &&
|
148
162
|
|
149
163
|
# ensure that the token is valid
|
@@ -157,7 +171,8 @@ module DeviseTokenAuth::Concerns::User
|
|
157
171
|
|
158
172
|
token = create_token(
|
159
173
|
client: client,
|
160
|
-
|
174
|
+
previous_token: tokens.fetch(client, {})['token'],
|
175
|
+
last_token: tokens.fetch(client, {})['previous_token'],
|
161
176
|
updated_at: now
|
162
177
|
)
|
163
178
|
|
@@ -168,14 +183,20 @@ module DeviseTokenAuth::Concerns::User
|
|
168
183
|
# client may use expiry to prevent validation request if expired
|
169
184
|
# must be cast as string or headers will break
|
170
185
|
expiry = tokens[client]['expiry'] || tokens[client][:expiry]
|
171
|
-
|
172
|
-
{
|
186
|
+
headers = {
|
173
187
|
DeviseTokenAuth.headers_names[:"access-token"] => token,
|
174
188
|
DeviseTokenAuth.headers_names[:"token-type"] => 'Bearer',
|
175
189
|
DeviseTokenAuth.headers_names[:"client"] => client,
|
176
190
|
DeviseTokenAuth.headers_names[:"expiry"] => expiry.to_s,
|
177
191
|
DeviseTokenAuth.headers_names[:"uid"] => uid
|
178
192
|
}
|
193
|
+
headers.merge!(build_bearer_token(headers))
|
194
|
+
end
|
195
|
+
|
196
|
+
def build_bearer_token(auth)
|
197
|
+
encoded_token = Base64.strict_encode64(auth.to_json)
|
198
|
+
bearer_token = "Bearer #{encoded_token}"
|
199
|
+
{DeviseTokenAuth.headers_names[:"authorization"] => bearer_token}
|
179
200
|
end
|
180
201
|
|
181
202
|
def update_auth_header(token, client = 'default')
|
@@ -4,12 +4,12 @@ module DeviseTokenAuth::Concerns::UserOmniauthCallbacks
|
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
included do
|
7
|
-
validates :email, presence: true,if:
|
8
|
-
validates :email, :devise_token_auth_email => true, allow_nil: true, allow_blank: true, if:
|
9
|
-
validates_presence_of :uid,
|
7
|
+
validates :email, presence: true, if: lambda { uid_and_provider_defined? && email_provider? }
|
8
|
+
validates :email, :devise_token_auth_email => true, allow_nil: true, allow_blank: true, if: lambda { uid_and_provider_defined? && email_provider? }
|
9
|
+
validates_presence_of :uid, if: lambda { uid_and_provider_defined? && !email_provider? }
|
10
10
|
|
11
11
|
# only validate unique emails among email registration users
|
12
|
-
validates :email, uniqueness: { case_sensitive: false, scope: :provider }, on: :create, if:
|
12
|
+
validates :email, uniqueness: { case_sensitive: false, scope: :provider }, on: :create, if: lambda { uid_and_provider_defined? && email_provider? }
|
13
13
|
|
14
14
|
# keep uid in sync with email
|
15
15
|
before_save :sync_uid
|
@@ -18,6 +18,10 @@ module DeviseTokenAuth::Concerns::UserOmniauthCallbacks
|
|
18
18
|
|
19
19
|
protected
|
20
20
|
|
21
|
+
def uid_and_provider_defined?
|
22
|
+
defined?(provider) && defined?(uid)
|
23
|
+
end
|
24
|
+
|
21
25
|
def email_provider?
|
22
26
|
provider == 'email'
|
23
27
|
end
|
@@ -26,6 +30,6 @@ module DeviseTokenAuth::Concerns::UserOmniauthCallbacks
|
|
26
30
|
unless self.new_record?
|
27
31
|
return if devise_modules.include?(:confirmable) && !@bypass_confirmation_postpone && postpone_email_change?
|
28
32
|
end
|
29
|
-
self.uid = email if email_provider?
|
33
|
+
self.uid = email if uid_and_provider_defined? && email_provider?
|
30
34
|
end
|
31
35
|
end
|
@@ -1,8 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class DeviseTokenAuthEmailValidator < ActiveModel::EachValidator
|
4
|
+
EMAIL_REGEXP = /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def validate?(email)
|
8
|
+
email =~ EMAIL_REGEXP
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
4
12
|
def validate_each(record, attribute, value)
|
5
|
-
unless value
|
13
|
+
unless DeviseTokenAuthEmailValidator.validate?(value)
|
6
14
|
record.errors.add(attribute, email_invalid_message)
|
7
15
|
end
|
8
16
|
end
|
data/config/locales/ja.yml
CHANGED
@@ -21,10 +21,22 @@ ja:
|
|
21
21
|
missing_redirect_url: "リダイレクト URL が与えられていません。"
|
22
22
|
not_allowed_redirect_url: "'%{redirect_url}' へのリダイレクトは許可されていません。"
|
23
23
|
sended: "'%{email}' にパスワードリセットの案内が送信されました。"
|
24
|
+
sended_paranoid: "すでにメールアドレスがデータベースに登録されている場合、 数分後にパスワード再発行用のリンクを記載したメールをお送りします。"
|
24
25
|
user_not_found: "メールアドレス '%{email}' のユーザーが見つかりません。"
|
25
26
|
password_not_required: "このアカウントはパスワードを要求していません。'%{provider}' を利用してログインしてください。"
|
26
27
|
missing_passwords: "'Password', 'Password confirmation' パラメータが与えられていません。"
|
27
28
|
successfully_updated: "パスワードの更新に成功しました。"
|
29
|
+
unlocks:
|
30
|
+
missing_email: "メールアドレスが与えられていません。"
|
31
|
+
sended: "%{email}' にアカウントのロックを解除する方法を記載したメールが送信されました。"
|
32
|
+
sended_paranoid: "アカウントが存在する場合、数分後にロックを解除する方法を記載したメールをお送りします。"
|
33
|
+
user_not_found: "メールアドレス '%{email}' を持つユーザーが見つかりません。"
|
34
|
+
confirmations:
|
35
|
+
sended: "'%{email}' にアカウントの確認方法を記載したメールが送信されました。"
|
36
|
+
sended_paranoid: "すでにメールアドレスがデータベースに登録されている場合、数分後にメールアドレスの確認方法を記載したメールをお送りします。"
|
37
|
+
user_not_found: "メールアドレス '%{email}' を持つユーザーが見つかりません。"
|
38
|
+
missing_email: "メールアドレスが与えられていません。"
|
39
|
+
|
28
40
|
errors:
|
29
41
|
messages:
|
30
42
|
validate_sign_up_params: "リクエストボディに適切なアカウント新規登録データを送信してください。"
|
@@ -30,7 +30,8 @@ module DeviseTokenAuth
|
|
30
30
|
:cookie_attributes,
|
31
31
|
:bypass_sign_in,
|
32
32
|
:send_confirmation_email,
|
33
|
-
:require_client_password_reset_token
|
33
|
+
:require_client_password_reset_token,
|
34
|
+
:other_uid
|
34
35
|
|
35
36
|
self.change_headers_on_each_request = true
|
36
37
|
self.max_number_of_devices = 10
|
@@ -45,7 +46,8 @@ module DeviseTokenAuth
|
|
45
46
|
self.enable_standard_devise_support = false
|
46
47
|
self.remove_tokens_after_password_reset = false
|
47
48
|
self.default_callbacks = true
|
48
|
-
self.headers_names = { '
|
49
|
+
self.headers_names = { 'authorization': 'Authorization',
|
50
|
+
'access-token': 'access-token',
|
49
51
|
'client': 'client',
|
50
52
|
'expiry': 'expiry',
|
51
53
|
'uid': 'uid',
|
@@ -56,6 +58,7 @@ module DeviseTokenAuth
|
|
56
58
|
self.bypass_sign_in = true
|
57
59
|
self.send_confirmation_email = false
|
58
60
|
self.require_client_password_reset_token = false
|
61
|
+
self.other_uid = nil
|
59
62
|
|
60
63
|
def self.setup(&block)
|
61
64
|
yield self
|
@@ -73,7 +73,7 @@ module ActionDispatch::Routing
|
|
73
73
|
|
74
74
|
# preserve the resource class thru oauth authentication by setting name of
|
75
75
|
# resource as "resource_class" param
|
76
|
-
match "#{full_path}/:provider", to: redirect{ |params, request|
|
76
|
+
match "#{full_path}/:provider", to: redirect(status: 307) { |params, request|
|
77
77
|
# get the current querystring
|
78
78
|
qs = CGI::parse(request.env['QUERY_STRING'])
|
79
79
|
|
@@ -99,7 +99,7 @@ module ActionDispatch::Routing
|
|
99
99
|
|
100
100
|
# re-construct the path for omniauth
|
101
101
|
"#{::OmniAuth.config.path_prefix}/#{params[:provider]}?#{redirect_params.to_param}"
|
102
|
-
}, via: [:get]
|
102
|
+
}, via: [:get, :post]
|
103
103
|
end
|
104
104
|
end
|
105
105
|
end
|
@@ -48,6 +48,9 @@ DeviseTokenAuth.setup do |config|
|
|
48
48
|
# :'uid' => 'uid',
|
49
49
|
# :'token-type' => 'token-type' }
|
50
50
|
|
51
|
+
# Makes it possible to use custom uid column
|
52
|
+
# config.other_uid = "foo"
|
53
|
+
|
51
54
|
# By default, only Bearer Token authentication is implemented out of the box.
|
52
55
|
# If, however, you wish to integrate with legacy Devise authentication, you can
|
53
56
|
# do so by enabling this flag. NOTE: This feature is highly experimental!
|
@@ -235,7 +235,7 @@ class DemoMangControllerTest < ActionDispatch::IntegrationTest
|
|
235
235
|
@resource.reload
|
236
236
|
age_token(@resource, @client_id)
|
237
237
|
|
238
|
-
# use
|
238
|
+
# use previous auth header
|
239
239
|
get '/demo/members_only_mang',
|
240
240
|
params: {},
|
241
241
|
headers: @auth_headers
|
@@ -244,38 +244,67 @@ class DemoMangControllerTest < ActionDispatch::IntegrationTest
|
|
244
244
|
@second_user = assigns(:resource)
|
245
245
|
@second_access_token = response.headers['access-token']
|
246
246
|
@second_response_status = response.status
|
247
|
+
|
248
|
+
@resource.reload
|
249
|
+
age_token(@resource, @client_id)
|
250
|
+
|
251
|
+
# use expired auth headers
|
252
|
+
get '/demo/members_only_mang',
|
253
|
+
params: {},
|
254
|
+
headers: @auth_headers
|
255
|
+
|
256
|
+
@third_is_batch_request = assigns(:is_batch_request)
|
257
|
+
@third_user = assigns(:resource)
|
258
|
+
@third_access_token = response.headers['access-token']
|
259
|
+
@third_response_status = response.status
|
247
260
|
end
|
248
261
|
|
249
262
|
it 'should allow the first request through' do
|
250
263
|
assert_equal 200, @first_response_status
|
251
264
|
end
|
252
265
|
|
266
|
+
it 'should allow the second request through' do
|
267
|
+
assert_equal 200, @second_response_status
|
268
|
+
end
|
269
|
+
|
253
270
|
it 'should not allow the second request through' do
|
254
|
-
assert_equal 401, @
|
271
|
+
assert_equal 401, @third_response_status
|
255
272
|
end
|
256
273
|
|
257
274
|
it 'should not treat first request as batch request' do
|
275
|
+
refute @first_is_batch_request
|
276
|
+
end
|
277
|
+
|
278
|
+
it 'should not treat second request as batch request' do
|
258
279
|
refute @second_is_batch_request
|
259
280
|
end
|
260
281
|
|
282
|
+
it 'should not treat third request as batch request' do
|
283
|
+
refute @third_is_batch_request
|
284
|
+
end
|
285
|
+
|
261
286
|
it 'should return auth headers from the first request' do
|
262
287
|
assert @first_access_token
|
263
288
|
end
|
264
289
|
|
265
|
-
it 'should
|
266
|
-
|
290
|
+
it 'should return auth headers from the second request' do
|
291
|
+
assert @second_access_token
|
267
292
|
end
|
268
293
|
|
269
|
-
it 'should not return auth headers from the
|
270
|
-
refute @
|
294
|
+
it 'should not return auth headers from the third request' do
|
295
|
+
refute @third_access_token
|
271
296
|
end
|
272
297
|
|
273
298
|
it 'should define user during first request' do
|
274
299
|
assert @first_user
|
275
300
|
end
|
276
301
|
|
277
|
-
it 'should
|
278
|
-
|
302
|
+
it 'should define user during second request' do
|
303
|
+
assert @second_user
|
304
|
+
end
|
305
|
+
|
306
|
+
it 'should not define user during third request' do
|
307
|
+
refute @third_user
|
279
308
|
end
|
280
309
|
end
|
281
310
|
end
|
@@ -265,7 +265,7 @@ class DemoUserControllerTest < ActionDispatch::IntegrationTest
|
|
265
265
|
@resource.reload
|
266
266
|
age_token(@resource, @client_id)
|
267
267
|
|
268
|
-
# use
|
268
|
+
# use previous auth header
|
269
269
|
get '/demo/members_only',
|
270
270
|
params: {},
|
271
271
|
headers: @auth_headers
|
@@ -274,38 +274,67 @@ class DemoUserControllerTest < ActionDispatch::IntegrationTest
|
|
274
274
|
@second_user = assigns(:resource)
|
275
275
|
@second_access_token = response.headers['access-token']
|
276
276
|
@second_response_status = response.status
|
277
|
+
|
278
|
+
@resource.reload
|
279
|
+
age_token(@resource, @client_id)
|
280
|
+
|
281
|
+
# use expired auth headers
|
282
|
+
get '/demo/members_only_mang',
|
283
|
+
params: {},
|
284
|
+
headers: @auth_headers
|
285
|
+
|
286
|
+
@third_is_batch_request = assigns(:is_batch_request)
|
287
|
+
@third_user = assigns(:resource)
|
288
|
+
@third_access_token = response.headers['access-token']
|
289
|
+
@third_response_status = response.status
|
277
290
|
end
|
278
291
|
|
279
292
|
it 'should allow the first request through' do
|
280
293
|
assert_equal 200, @first_response_status
|
281
294
|
end
|
282
295
|
|
296
|
+
it 'should allow the second request through' do
|
297
|
+
assert_equal 200, @second_response_status
|
298
|
+
end
|
299
|
+
|
283
300
|
it 'should not allow the second request through' do
|
284
|
-
assert_equal 401, @
|
301
|
+
assert_equal 401, @third_response_status
|
285
302
|
end
|
286
303
|
|
287
304
|
it 'should not treat first request as batch request' do
|
305
|
+
refute @first_is_batch_request
|
306
|
+
end
|
307
|
+
|
308
|
+
it 'should not treat second request as batch request' do
|
288
309
|
refute @second_is_batch_request
|
289
310
|
end
|
290
311
|
|
312
|
+
it 'should not treat third request as batch request' do
|
313
|
+
refute @third_is_batch_request
|
314
|
+
end
|
315
|
+
|
291
316
|
it 'should return auth headers from the first request' do
|
292
317
|
assert @first_access_token
|
293
318
|
end
|
294
319
|
|
295
|
-
it 'should
|
296
|
-
|
320
|
+
it 'should return auth headers from the second request' do
|
321
|
+
assert @second_access_token
|
297
322
|
end
|
298
323
|
|
299
|
-
it 'should not return auth headers from the
|
300
|
-
refute @
|
324
|
+
it 'should not return auth headers from the third request' do
|
325
|
+
refute @third_access_token
|
301
326
|
end
|
302
327
|
|
303
328
|
it 'should define user during first request' do
|
304
329
|
assert @first_user
|
305
330
|
end
|
306
331
|
|
307
|
-
it 'should
|
308
|
-
|
332
|
+
it 'should define user during second request' do
|
333
|
+
assert @second_user
|
334
|
+
end
|
335
|
+
|
336
|
+
it 'should not define user during third request' do
|
337
|
+
refute @third_user
|
309
338
|
end
|
310
339
|
end
|
311
340
|
end
|
@@ -171,21 +171,30 @@ class DeviseTokenAuth::ConfirmationsControllerTest < ActionController::TestCase
|
|
171
171
|
test 'response should contain message' do
|
172
172
|
assert_equal @data['message'], I18n.t('devise_token_auth.confirmations.sended_paranoid', email: @resource.email)
|
173
173
|
end
|
174
|
+
|
175
|
+
test 'response should return success status' do
|
176
|
+
assert_equal 200, response.status
|
177
|
+
end
|
174
178
|
end
|
175
179
|
|
176
180
|
describe 'on failure' do
|
177
181
|
before do
|
178
182
|
swap Devise, paranoid: true do
|
183
|
+
@email = 'chester@cheet.ah'
|
179
184
|
post :create,
|
180
|
-
params: { email:
|
185
|
+
params: { email: @email,
|
181
186
|
redirect_url: @redirect_url },
|
182
187
|
xhr: true
|
183
188
|
@data = JSON.parse(response.body)
|
184
189
|
end
|
185
190
|
end
|
186
191
|
|
187
|
-
test 'response should contain errors' do
|
188
|
-
assert_equal @data['
|
192
|
+
test 'response should not contain errors' do
|
193
|
+
assert_equal @data['message'], I18n.t('devise_token_auth.confirmations.sended_paranoid', email: @email)
|
194
|
+
end
|
195
|
+
|
196
|
+
test 'response should return success status' do
|
197
|
+
assert_equal 200, response.status
|
189
198
|
end
|
190
199
|
end
|
191
200
|
end
|
@@ -116,14 +116,14 @@ class DeviseTokenAuth::PasswordsControllerTest < ActionController::TestCase
|
|
116
116
|
end
|
117
117
|
end
|
118
118
|
|
119
|
-
test '
|
120
|
-
assert_equal
|
119
|
+
test 'response should return success status' do
|
120
|
+
assert_equal 200, response.status
|
121
121
|
end
|
122
122
|
|
123
|
-
test '
|
124
|
-
|
125
|
-
|
126
|
-
|
123
|
+
test 'response should contain message' do
|
124
|
+
assert_equal \
|
125
|
+
@data['message'],
|
126
|
+
I18n.t('devise_token_auth.passwords.sended_paranoid')
|
127
127
|
end
|
128
128
|
end
|
129
129
|
end
|
@@ -18,11 +18,51 @@ class DeviseTokenAuth::TokenValidationsControllerTest < ActionDispatch::Integrat
|
|
18
18
|
@token = @auth_headers['access-token']
|
19
19
|
@client_id = @auth_headers['client']
|
20
20
|
@expiry = @auth_headers['expiry']
|
21
|
-
|
21
|
+
@authorization_header = @auth_headers.slice('Authorization')
|
22
22
|
# ensure that request is not treated as batch request
|
23
23
|
age_token(@resource, @client_id)
|
24
24
|
end
|
25
25
|
|
26
|
+
describe 'using only Authorization header' do
|
27
|
+
describe 'using valid Authorization header' do
|
28
|
+
before do
|
29
|
+
get '/auth/validate_token', params: {}, headers: @authorization_header
|
30
|
+
end
|
31
|
+
|
32
|
+
test 'token valid' do
|
33
|
+
assert_equal 200, response.status
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe 'using invalid Authorization header' do
|
38
|
+
describe 'with invalid base64' do
|
39
|
+
before do
|
40
|
+
get '/auth/validate_token', params: {}, headers: {'Authorization': 'Bearer invalidtoken=='}
|
41
|
+
end
|
42
|
+
|
43
|
+
test 'returns access denied' do
|
44
|
+
assert_equal 401, response.status
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe 'with valid base64' do
|
49
|
+
before do
|
50
|
+
valid_base64 = Base64.strict_encode64({
|
51
|
+
"access-token": 'invalidtoken',
|
52
|
+
"token-type": 'Bearer',
|
53
|
+
"client": 'client',
|
54
|
+
"expiry": '1234567'
|
55
|
+
}.to_json)
|
56
|
+
get '/auth/validate_token', params: {}, headers: {'Authorization': "Bearer #{valid_base64}"}
|
57
|
+
end
|
58
|
+
|
59
|
+
test 'returns access denied' do
|
60
|
+
assert_equal 401, response.status
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
26
66
|
describe 'vanilla user' do
|
27
67
|
before do
|
28
68
|
get '/auth/validate_token', params: {}, headers: @auth_headers
|
@@ -81,17 +81,19 @@ class DeviseTokenAuth::UnlocksControllerTest < ActionController::TestCase
|
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
84
|
-
test '
|
85
|
-
assert_equal
|
84
|
+
test 'should always return success' do
|
85
|
+
assert_equal 200, response.status
|
86
86
|
end
|
87
87
|
|
88
|
-
test 'errors should be returned' do
|
89
|
-
assert @data['
|
90
|
-
assert_equal
|
88
|
+
test 'errors should not be returned' do
|
89
|
+
assert @data['success']
|
90
|
+
assert_equal \
|
91
|
+
@data['message'],
|
92
|
+
I18n.t('devise_token_auth.unlocks.sended_paranoid')
|
91
93
|
end
|
92
94
|
end
|
93
95
|
|
94
|
-
describe 'successfully requested unlock' do
|
96
|
+
describe 'successfully requested unlock without paranoid mode' do
|
95
97
|
before do
|
96
98
|
post :create, params: { email: @resource.email }
|
97
99
|
|
@@ -103,6 +105,26 @@ class DeviseTokenAuth::UnlocksControllerTest < ActionController::TestCase
|
|
103
105
|
end
|
104
106
|
end
|
105
107
|
|
108
|
+
describe 'successfully requested unlock with paranoid mode' do
|
109
|
+
before do
|
110
|
+
swap Devise, paranoid: true do
|
111
|
+
post :create, params: { email: @resource.email }
|
112
|
+
@data = JSON.parse(response.body)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
test 'should always return success' do
|
117
|
+
assert_equal 200, response.status
|
118
|
+
end
|
119
|
+
|
120
|
+
test 'errors should not be returned' do
|
121
|
+
assert @data['success']
|
122
|
+
assert_equal \
|
123
|
+
@data['message'],
|
124
|
+
I18n.t('devise_token_auth.unlocks.sended_paranoid')
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
106
128
|
describe 'case-sensitive email' do
|
107
129
|
before do
|
108
130
|
post :create, params: { email: @resource.email }
|
data/test/dummy/db/schema.rb
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
# of editing this file, please use the migrations feature of Active Record to
|
3
3
|
# incrementally modify your database, and then regenerate this schema definition.
|
4
4
|
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
# from scratch.
|
9
|
-
#
|
5
|
+
# This file is the source Rails uses to define your schema when running `bin/rails
|
6
|
+
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
|
7
|
+
# be faster and is potentially less error prone than running all of your
|
8
|
+
# migrations from scratch. Old migrations may fail to apply correctly if those
|
9
|
+
# migrations use external dependencies or application code.
|
10
10
|
#
|
11
11
|
# It's strongly recommended that you check this file into your version control system.
|
12
12
|
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class User < ApplicationRecord
|
2
|
+
# Include default devise modules.
|
3
|
+
devise :database_authenticatable, :registerable,
|
4
|
+
:recoverable, :rememberable, :trackable, :validatable,
|
5
|
+
:confirmable, :omniauthable
|
6
|
+
include DeviseTokenAuth::Concerns::User
|
7
|
+
|
8
|
+
def whatever
|
9
|
+
puts 'whatever'
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
class DeviseTokenAuthCreateUsers < ActiveRecord::Migration[5.2]
|
2
|
+
def change
|
3
|
+
|
4
|
+
create_table(:users) do |t|
|
5
|
+
## Required
|
6
|
+
t.string :provider, :null => false, :default => "email"
|
7
|
+
t.string :uid, :null => false, :default => ""
|
8
|
+
|
9
|
+
## Database authenticatable
|
10
|
+
t.string :encrypted_password, :null => false, :default => ""
|
11
|
+
|
12
|
+
## Recoverable
|
13
|
+
t.string :reset_password_token
|
14
|
+
t.datetime :reset_password_sent_at
|
15
|
+
t.boolean :allow_password_change, :default => false
|
16
|
+
|
17
|
+
## Rememberable
|
18
|
+
t.datetime :remember_created_at
|
19
|
+
|
20
|
+
## Confirmable
|
21
|
+
t.string :confirmation_token
|
22
|
+
t.datetime :confirmed_at
|
23
|
+
t.datetime :confirmation_sent_at
|
24
|
+
t.string :unconfirmed_email # Only if using reconfirmable
|
25
|
+
|
26
|
+
## Lockable
|
27
|
+
# t.integer :failed_attempts, :default => 0, :null => false # Only if lock strategy is :failed_attempts
|
28
|
+
# t.string :unlock_token # Only if unlock strategy is :email or :both
|
29
|
+
# t.datetime :locked_at
|
30
|
+
|
31
|
+
## User Info
|
32
|
+
t.string :name
|
33
|
+
t.string :nickname
|
34
|
+
t.string :image
|
35
|
+
t.string :email
|
36
|
+
|
37
|
+
## Tokens
|
38
|
+
t.text :tokens
|
39
|
+
|
40
|
+
t.timestamps
|
41
|
+
end
|
42
|
+
|
43
|
+
add_index :users, :email, unique: true
|
44
|
+
add_index :users, [:uid, :provider], unique: true
|
45
|
+
add_index :users, :reset_password_token, unique: true
|
46
|
+
add_index :users, :confirmation_token, unique: true
|
47
|
+
# add_index :users, :unlock_token, unique: true
|
48
|
+
end
|
49
|
+
end
|
data/test/models/user_test.rb
CHANGED
@@ -76,6 +76,28 @@ class UserTest < ActiveSupport::TestCase
|
|
76
76
|
end
|
77
77
|
end
|
78
78
|
|
79
|
+
describe 'previous token' do
|
80
|
+
before do
|
81
|
+
@resource = create(:user, :confirmed)
|
82
|
+
|
83
|
+
@auth_headers1 = @resource.create_new_auth_token
|
84
|
+
end
|
85
|
+
|
86
|
+
test 'should properly indicate whether previous token is current' do
|
87
|
+
assert @resource.token_is_current?(@auth_headers1['access-token'], @auth_headers1['client'])
|
88
|
+
# create another token, emulating a new request
|
89
|
+
@auth_headers2 = @resource.create_new_auth_token
|
90
|
+
|
91
|
+
# should work for previous token
|
92
|
+
assert @resource.token_is_current?(@auth_headers1['access-token'], @auth_headers1['client'])
|
93
|
+
# should work for latest token as well
|
94
|
+
assert @resource.token_is_current?(@auth_headers2['access-token'], @auth_headers2['client'])
|
95
|
+
|
96
|
+
# after using latest token, previous token should not work
|
97
|
+
assert @resource.token_is_current?(@auth_headers1['access-token'], @auth_headers1['client'])
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
79
101
|
describe 'expired tokens are destroyed on save' do
|
80
102
|
before do
|
81
103
|
@resource = create(:user, :confirmed)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: devise_token_auth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lynn Hurley
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-09-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -19,7 +19,7 @@ dependencies:
|
|
19
19
|
version: 4.2.0
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: '
|
22
|
+
version: '7.1'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -29,7 +29,7 @@ dependencies:
|
|
29
29
|
version: 4.2.0
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: '
|
32
|
+
version: '7.1'
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: devise
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -319,9 +319,9 @@ files:
|
|
319
319
|
- test/dummy/db/migrate/20190924101113_devise_token_auth_create_confirmable_users.rb
|
320
320
|
- test/dummy/db/schema.rb
|
321
321
|
- test/dummy/lib/migration_database_helper.rb
|
322
|
-
- test/dummy/tmp/generators/app/
|
323
|
-
- test/dummy/tmp/generators/app/models/azpire/v1/human_resource/user.rb
|
322
|
+
- test/dummy/tmp/generators/app/models/user.rb
|
324
323
|
- test/dummy/tmp/generators/config/initializers/devise_token_auth.rb
|
324
|
+
- test/dummy/tmp/generators/db/migrate/20220822003050_devise_token_auth_create_users.rb
|
325
325
|
- test/factories/users.rb
|
326
326
|
- test/lib/devise_token_auth/blacklist_test.rb
|
327
327
|
- test/lib/devise_token_auth/rails/custom_routes_test.rb
|
@@ -350,14 +350,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
350
350
|
requirements:
|
351
351
|
- - ">="
|
352
352
|
- !ruby/object:Gem::Version
|
353
|
-
version: 2.
|
353
|
+
version: 2.3.0
|
354
354
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
355
355
|
requirements:
|
356
356
|
- - ">="
|
357
357
|
- !ruby/object:Gem::Version
|
358
358
|
version: '0'
|
359
359
|
requirements: []
|
360
|
-
rubygems_version: 3.1.
|
360
|
+
rubygems_version: 3.1.6
|
361
361
|
signing_key:
|
362
362
|
specification_version: 4
|
363
363
|
summary: Token based authentication for rails. Uses Devise + OmniAuth.
|
@@ -431,9 +431,9 @@ test_files:
|
|
431
431
|
- test/dummy/db/migrate/20140715061447_devise_token_auth_create_users.rb
|
432
432
|
- test/dummy/db/migrate/20140715061805_devise_token_auth_create_mangs.rb
|
433
433
|
- test/dummy/db/migrate/20190924101113_devise_token_auth_create_confirmable_users.rb
|
434
|
-
- test/dummy/tmp/generators/app/models/
|
435
|
-
- test/dummy/tmp/generators/app/controllers/application_controller.rb
|
434
|
+
- test/dummy/tmp/generators/app/models/user.rb
|
436
435
|
- test/dummy/tmp/generators/config/initializers/devise_token_auth.rb
|
436
|
+
- test/dummy/tmp/generators/db/migrate/20220822003050_devise_token_auth_create_users.rb
|
437
437
|
- test/dummy/README.rdoc
|
438
438
|
- test/models/only_email_user_test.rb
|
439
439
|
- test/models/confirmable_user_test.rb
|
@@ -1,56 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Azpire::V1::HumanResource::User
|
4
|
-
include Mongoid::Document
|
5
|
-
include Mongoid::Timestamps
|
6
|
-
include Mongoid::Locker
|
7
|
-
|
8
|
-
field :locker_locked_at, type: Time
|
9
|
-
field :locker_locked_until, type: Time
|
10
|
-
|
11
|
-
locker locked_at_field: :locker_locked_at,
|
12
|
-
locked_until_field: :locker_locked_until
|
13
|
-
|
14
|
-
## Database authenticatable
|
15
|
-
field :email, type: String, default: ''
|
16
|
-
field :encrypted_password, type: String, default: ''
|
17
|
-
|
18
|
-
## Recoverable
|
19
|
-
field :reset_password_token, type: String
|
20
|
-
field :reset_password_sent_at, type: Time
|
21
|
-
field :reset_password_redirect_url, type: String
|
22
|
-
field :allow_password_change, type: Boolean, default: false
|
23
|
-
|
24
|
-
## Rememberable
|
25
|
-
field :remember_created_at, type: Time
|
26
|
-
|
27
|
-
## Confirmable
|
28
|
-
field :confirmation_token, type: String
|
29
|
-
field :confirmed_at, type: Time
|
30
|
-
field :confirmation_sent_at, type: Time
|
31
|
-
field :unconfirmed_email, type: String # Only if using reconfirmable
|
32
|
-
|
33
|
-
## Lockable
|
34
|
-
# field :failed_attempts, type: Integer, default: 0 # Only if lock strategy is :failed_attempts
|
35
|
-
# field :unlock_token, type: String # Only if unlock strategy is :email or :both
|
36
|
-
# field :locked_at, type: Time
|
37
|
-
|
38
|
-
## Required
|
39
|
-
field :provider, type: String
|
40
|
-
field :uid, type: String, default: ''
|
41
|
-
|
42
|
-
## Tokens
|
43
|
-
field :tokens, type: Hash, default: {}
|
44
|
-
|
45
|
-
# Include default devise modules. Others available are:
|
46
|
-
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
|
47
|
-
devise :database_authenticatable, :registerable,
|
48
|
-
:recoverable, :rememberable, :validatable
|
49
|
-
include DeviseTokenAuth::Concerns::User
|
50
|
-
|
51
|
-
index({ email: 1 }, { name: 'email_index', unique: true, background: true })
|
52
|
-
index({ reset_password_token: 1 }, { name: 'reset_password_token_index', unique: true, sparse: true, background: true })
|
53
|
-
index({ confirmation_token: 1 }, { name: 'confirmation_token_index', unique: true, sparse: true, background: true })
|
54
|
-
index({ uid: 1, provider: 1}, { name: 'uid_provider_index', unique: true, background: true })
|
55
|
-
# index({ unlock_token: 1 }, { name: 'unlock_token_index', unique: true, sparse: true, background: true })
|
56
|
-
end
|