devise_token_auth 1.0.0 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +6 -3
  3. data/app/controllers/devise_token_auth/application_controller.rb +23 -3
  4. data/app/controllers/devise_token_auth/concerns/resource_finder.rb +24 -11
  5. data/app/controllers/devise_token_auth/concerns/set_user_by_token.rb +78 -57
  6. data/app/controllers/devise_token_auth/confirmations_controller.rb +69 -19
  7. data/app/controllers/devise_token_auth/omniauth_callbacks_controller.rb +89 -44
  8. data/app/controllers/devise_token_auth/passwords_controller.rb +55 -31
  9. data/app/controllers/devise_token_auth/registrations_controller.rb +33 -40
  10. data/app/controllers/devise_token_auth/sessions_controller.rb +36 -14
  11. data/app/controllers/devise_token_auth/unlocks_controller.rb +12 -7
  12. data/app/models/devise_token_auth/concerns/active_record_support.rb +14 -0
  13. data/app/models/devise_token_auth/concerns/confirmable_support.rb +28 -0
  14. data/app/models/devise_token_auth/concerns/mongoid_support.rb +19 -0
  15. data/app/models/devise_token_auth/concerns/tokens_serialization.rb +31 -0
  16. data/app/models/devise_token_auth/concerns/user.rb +79 -80
  17. data/app/models/devise_token_auth/concerns/user_omniauth_callbacks.rb +12 -5
  18. data/app/validators/{email_validator.rb → devise_token_auth_email_validator.rb} +11 -3
  19. data/app/views/devise_token_auth/omniauth_external_window.html.erb +1 -1
  20. data/config/locales/da-DK.yml +2 -0
  21. data/config/locales/de.yml +2 -0
  22. data/config/locales/en.yml +10 -0
  23. data/config/locales/es.yml +2 -0
  24. data/config/locales/fr.yml +2 -0
  25. data/config/locales/he.yml +52 -0
  26. data/config/locales/it.yml +2 -0
  27. data/config/locales/ja.yml +16 -2
  28. data/config/locales/ko.yml +51 -0
  29. data/config/locales/nl.yml +2 -0
  30. data/config/locales/pl.yml +6 -3
  31. data/config/locales/pt-BR.yml +2 -0
  32. data/config/locales/pt.yml +6 -3
  33. data/config/locales/ro.yml +2 -0
  34. data/config/locales/ru.yml +2 -0
  35. data/config/locales/sq.yml +2 -0
  36. data/config/locales/sv.yml +2 -0
  37. data/config/locales/uk.yml +2 -0
  38. data/config/locales/vi.yml +2 -0
  39. data/config/locales/zh-CN.yml +2 -0
  40. data/config/locales/zh-HK.yml +2 -0
  41. data/config/locales/zh-TW.yml +2 -0
  42. data/lib/devise_token_auth/blacklist.rb +6 -0
  43. data/lib/devise_token_auth/controllers/helpers.rb +5 -9
  44. data/lib/devise_token_auth/engine.rb +17 -2
  45. data/lib/devise_token_auth/rails/routes.rb +22 -16
  46. data/lib/devise_token_auth/token_factory.rb +126 -0
  47. data/lib/devise_token_auth/url.rb +3 -0
  48. data/lib/devise_token_auth/version.rb +1 -1
  49. data/lib/devise_token_auth.rb +6 -3
  50. data/lib/generators/devise_token_auth/USAGE +1 -1
  51. data/lib/generators/devise_token_auth/install_generator.rb +7 -91
  52. data/lib/generators/devise_token_auth/install_generator_helpers.rb +98 -0
  53. data/lib/generators/devise_token_auth/install_mongoid_generator.rb +46 -0
  54. data/lib/generators/devise_token_auth/templates/devise_token_auth.rb +21 -5
  55. data/lib/generators/devise_token_auth/templates/devise_token_auth_create_users.rb.erb +1 -8
  56. data/lib/generators/devise_token_auth/templates/user.rb.erb +2 -2
  57. data/lib/generators/devise_token_auth/templates/user_mongoid.rb.erb +56 -0
  58. data/test/controllers/custom/custom_confirmations_controller_test.rb +2 -2
  59. data/test/controllers/custom/custom_omniauth_callbacks_controller_test.rb +1 -1
  60. data/test/controllers/demo_mang_controller_test.rb +37 -8
  61. data/test/controllers/demo_user_controller_test.rb +39 -10
  62. data/test/controllers/devise_token_auth/confirmations_controller_test.rb +170 -22
  63. data/test/controllers/devise_token_auth/omniauth_callbacks_controller_test.rb +117 -53
  64. data/test/controllers/devise_token_auth/passwords_controller_test.rb +299 -122
  65. data/test/controllers/devise_token_auth/registrations_controller_test.rb +56 -16
  66. data/test/controllers/devise_token_auth/sessions_controller_test.rb +139 -75
  67. data/test/controllers/devise_token_auth/token_validations_controller_test.rb +43 -2
  68. data/test/controllers/devise_token_auth/unlocks_controller_test.rb +44 -5
  69. data/test/controllers/overrides/confirmations_controller_test.rb +1 -1
  70. data/test/controllers/overrides/omniauth_callbacks_controller_test.rb +1 -1
  71. data/test/dummy/app/active_record/confirmable_user.rb +11 -0
  72. data/test/dummy/app/{models → active_record}/scoped_user.rb +2 -2
  73. data/test/dummy/app/{models → active_record}/unconfirmable_user.rb +1 -2
  74. data/test/dummy/app/{models → active_record}/unregisterable_user.rb +3 -3
  75. data/test/dummy/app/active_record/user.rb +6 -0
  76. data/test/dummy/app/controllers/application_controller.rb +2 -6
  77. data/test/dummy/app/controllers/overrides/confirmations_controller.rb +5 -4
  78. data/test/dummy/app/controllers/overrides/passwords_controller.rb +5 -4
  79. data/test/dummy/app/controllers/overrides/registrations_controller.rb +1 -1
  80. data/test/dummy/app/controllers/overrides/sessions_controller.rb +2 -2
  81. data/test/dummy/app/models/{user.rb → concerns/favorite_color.rb} +7 -8
  82. data/test/dummy/app/mongoid/confirmable_user.rb +52 -0
  83. data/test/dummy/app/mongoid/lockable_user.rb +38 -0
  84. data/test/dummy/app/mongoid/mang.rb +46 -0
  85. data/test/dummy/app/mongoid/only_email_user.rb +33 -0
  86. data/test/dummy/app/mongoid/scoped_user.rb +50 -0
  87. data/test/dummy/app/mongoid/unconfirmable_user.rb +44 -0
  88. data/test/dummy/app/mongoid/unregisterable_user.rb +47 -0
  89. data/test/dummy/app/mongoid/user.rb +49 -0
  90. data/test/dummy/app/views/layouts/application.html.erb +0 -2
  91. data/test/dummy/config/application.rb +22 -1
  92. data/test/dummy/config/boot.rb +4 -0
  93. data/test/dummy/config/environments/development.rb +0 -10
  94. data/test/dummy/config/environments/production.rb +0 -16
  95. data/test/dummy/config/environments/test.rb +6 -2
  96. data/test/dummy/config/initializers/devise.rb +285 -0
  97. data/test/dummy/config/initializers/devise_token_auth.rb +35 -4
  98. data/test/dummy/config/initializers/figaro.rb +1 -1
  99. data/test/dummy/config/initializers/omniauth.rb +1 -0
  100. data/test/dummy/config/routes.rb +2 -0
  101. data/test/dummy/db/migrate/20140715061447_devise_token_auth_create_users.rb +0 -7
  102. data/test/dummy/db/migrate/20140715061805_devise_token_auth_create_mangs.rb +0 -7
  103. data/test/dummy/db/migrate/20141222035835_devise_token_auth_create_only_email_users.rb +0 -7
  104. data/test/dummy/db/migrate/20141222053502_devise_token_auth_create_unregisterable_users.rb +0 -7
  105. data/test/dummy/db/migrate/20150708104536_devise_token_auth_create_unconfirmable_users.rb +0 -7
  106. data/test/dummy/db/migrate/20160103235141_devise_token_auth_create_scoped_users.rb +0 -7
  107. data/test/dummy/db/migrate/20160629184441_devise_token_auth_create_lockable_users.rb +0 -7
  108. data/test/dummy/db/migrate/20190924101113_devise_token_auth_create_confirmable_users.rb +49 -0
  109. data/test/dummy/db/schema.rb +31 -33
  110. data/test/dummy/tmp/generators/app/models/user.rb +9 -0
  111. data/test/dummy/tmp/generators/config/initializers/devise_token_auth.rb +66 -0
  112. data/test/dummy/tmp/generators/db/migrate/20230415183419_devise_token_auth_create_users.rb +49 -0
  113. data/test/factories/users.rb +3 -2
  114. data/test/lib/devise_token_auth/blacklist_test.rb +19 -0
  115. data/test/lib/devise_token_auth/rails/custom_routes_test.rb +29 -0
  116. data/test/lib/devise_token_auth/rails/routes_test.rb +87 -0
  117. data/test/lib/devise_token_auth/token_factory_test.rb +191 -0
  118. data/test/lib/devise_token_auth/url_test.rb +2 -2
  119. data/test/lib/generators/devise_token_auth/install_generator_test.rb +51 -31
  120. data/test/lib/generators/devise_token_auth/install_generator_with_namespace_test.rb +51 -31
  121. data/test/models/concerns/mongoid_support_test.rb +31 -0
  122. data/test/models/concerns/tokens_serialization_test.rb +104 -0
  123. data/test/models/confirmable_user_test.rb +35 -0
  124. data/test/models/only_email_user_test.rb +0 -8
  125. data/test/models/user_test.rb +13 -23
  126. data/test/test_helper.rb +45 -4
  127. metadata +190 -97
  128. data/config/initializers/devise.rb +0 -198
  129. data/test/dummy/config/initializers/assets.rb +0 -10
  130. data/test/dummy/tmp/generators/app/views/devise/mailer/confirmation_instructions.html.erb +0 -5
  131. data/test/dummy/tmp/generators/app/views/devise/mailer/reset_password_instructions.html.erb +0 -8
  132. /data/test/dummy/app/{models → active_record}/lockable_user.rb +0 -0
  133. /data/test/dummy/app/{models → active_record}/mang.rb +0 -0
  134. /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: 135b5088d17b20d187a6ffe314356dd2a2474d9bd98898bc9e36bc931e6c9fef
4
+ data.tar.gz: cf3c3c6fc19564248bdcb22e3b99624bd25a027383649a45c7e7bf1fddfd5bbd
5
5
  SHA512:
6
- metadata.gz: 4b631710faf5afc08a2f0f0fc89a96e63c7fe07d0c7a985a19d3b5c0a18801401afe67525aa6e0a078195ca4d24c58b6a6651da667c2a7a7f40723d4974dc850
7
- data.tar.gz: 8707ad62656749fc88de275533456b93c17545f854e40f03920365c2ba9a11c170af44787118c4d8bc59ef593c5535ce8e09c512338c0de8af860c7e2500746f
6
+ metadata.gz: 5f6e88376261bcea31e98d8af66cc298755d2cbc2724c481a100d78273824b1dcfcc016bbc2af2b43d1dcac945fc6a4015d351f321da9a432ec4c5129f8c58f0
7
+ data.tar.gz: bde72417d1882c6f69076d3bfe8cebd077e39a681898fb0c5603643770a3d81eb0ac3d42dd46f8ae27aff4dae74a138159160974c1996ef4e28d252baf6b52ba
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Devise Token Auth
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/devise_token_auth.svg)](http://badge.fury.io/rb/devise_token_auth)
4
- [![Build Status](https://travis-ci.org/lynndylanhurley/devise_token_auth.svg?branch=master)](https://travis-ci.org/lynndylanhurley/devise_token_auth)
4
+ [![Build Status](https://github.com/lynndylanhurley/devise_token_auth/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/lynndylanhurley/devise_token_auth/actions/workflows/test.yml)
5
5
  [![Code Climate](https://codeclimate.com/github/lynndylanhurley/devise_token_auth/badges/gpa.svg)](https://codeclimate.com/github/lynndylanhurley/devise_token_auth)
6
6
  [![Test Coverage](https://codeclimate.com/github/lynndylanhurley/devise_token_auth/badges/coverage.svg)](https://codeclimate.com/github/lynndylanhurley/devise_token_auth/coverage)
7
7
  [![Downloads](https://img.shields.io/gem/dt/devise_token_auth.svg)](https://rubygems.org/gems/devise_token_auth)
@@ -19,9 +19,10 @@ 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
+ * [vanilla-token-auth](https://github.com/theblang/vanilla-token-auth) for an unopinionated client
25
26
  * Oauth2 authentication using [OmniAuth](https://github.com/intridea/omniauth).
26
27
  * Email authentication using [Devise](https://github.com/plataformatec/devise), including:
27
28
  * User registration, update and deletion
@@ -65,11 +66,13 @@ Please read the [issue template](https://github.com/lynndylanhurley/devise_token
65
66
 
66
67
  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
68
 
69
+ 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)!
70
+
68
71
  ## Live Demos
69
72
 
70
73
  [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
74
 
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).
75
+ [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
76
 
74
77
  [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
78
 
@@ -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?(@redirect_url)
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 = {})
@@ -76,5 +75,26 @@ module DeviseTokenAuth
76
75
  response = response.merge(data) if data
77
76
  render json: response, status: status
78
77
  end
78
+
79
+ def success_message(name, email)
80
+ if Devise.paranoid
81
+ I18n.t("devise_token_auth.#{name}.sended_paranoid")
82
+ else
83
+ I18n.t("devise_token_auth.#{name}.sended", email: email)
84
+ end
85
+ end
86
+
87
+ def redirect_options
88
+ {}
89
+ end
90
+
91
+ # When using a cookie to transport the auth token we can set it immediately in flows such as
92
+ # reset password and OmniAuth success, rather than making the client scrape the token from
93
+ # query params (to then send in the initial validate_token request).
94
+ # TODO: We should be able to stop exposing the token in query params when this method is used
95
+ def set_token_in_cookie(resource, token)
96
+ auth_header = resource.build_auth_headers(token.token, token.client)
97
+ cookies[DeviseTokenAuth.cookie_name] = DeviseTokenAuth.cookie_attributes.merge(value: auth_header.to_json)
98
+ end
79
99
  end
80
100
  end
@@ -20,21 +20,34 @@ 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
23
+ @resource = if database_adapter&.include?('mysql')
24
+ # fix for mysql default case insensitivity
25
+ field_sanitized = resource_class.connection.quote_column_name(field)
26
+ resource_class.where("BINARY #{field_sanitized} = ? AND provider= ?", value, provider).first
27
+ else
28
+ resource_class.dta_find_by(field => value, 'provider' => provider)
29
+ end
30
+ end
31
+
32
+ def database_adapter
33
+ @database_adapter ||= begin
34
+ rails_version = [Rails::VERSION::MAJOR, Rails::VERSION::MINOR].join(".")
28
35
 
29
- @resource = resource_class.where(q, value).first
36
+ adapter =
37
+ if rails_version >= "6.1"
38
+ resource_class.try(:connection_db_config)&.try(:adapter)
39
+ else
40
+ resource_class.try(:connection_config)&.try(:[], :adapter)
41
+ end
42
+ end
30
43
  end
31
44
 
32
45
  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
46
+ mapping = if m
47
+ Devise.mappings[m]
48
+ else
49
+ Devise.mappings[resource_name] || Devise.mappings.values.first
50
+ end
38
51
 
39
52
  mapping.to
40
53
  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
@@ -45,21 +32,37 @@ module DeviseTokenAuth::Concerns::SetUserByToken
45
32
 
46
33
  # gets the headers names, which was set in the initialize file
47
34
  uid_name = DeviseTokenAuth.headers_names[:'uid']
35
+ other_uid_name = DeviseTokenAuth.other_uid && DeviseTokenAuth.headers_names[DeviseTokenAuth.other_uid.to_sym]
48
36
  access_token_name = DeviseTokenAuth.headers_names[:'access-token']
49
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])
42
+
43
+ # gets values from cookie if configured and present
44
+ parsed_auth_cookie = {}
45
+ if DeviseTokenAuth.cookie_enabled
46
+ auth_cookie = request.cookies[DeviseTokenAuth.cookie_name]
47
+ if auth_cookie.present?
48
+ parsed_auth_cookie = JSON.parse(auth_cookie)
49
+ end
50
+ end
50
51
 
51
52
  # 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]
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]
55
+ @token = DeviseTokenAuth::TokenFactory.new unless @token
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]
55
58
 
56
- # client_id isn't required, set to 'default' if absent
57
- @client_id ||= 'default'
59
+ # client isn't required, set to 'default' if absent
60
+ @token.client ||= 'default'
58
61
 
59
62
  # check for an existing user, authenticated via warden/devise, if enabled
60
63
  if DeviseTokenAuth.enable_standard_devise_support
61
- devise_warden_user = warden.user(rc.to_s.underscore.to_sym)
62
- if devise_warden_user && devise_warden_user.tokens[@client_id].nil?
64
+ devise_warden_user = warden.user(mapping)
65
+ if devise_warden_user && devise_warden_user.tokens[@token.client].nil?
63
66
  @used_auth_by_token = false
64
67
  @resource = devise_warden_user
65
68
  # REVIEW: The following line _should_ be safe to remove;
@@ -71,53 +74,55 @@ module DeviseTokenAuth::Concerns::SetUserByToken
71
74
  # user has already been found and authenticated
72
75
  return @resource if @resource && @resource.is_a?(rc)
73
76
 
74
- # ensure we clear the client_id
75
- unless @token
76
- @client_id = nil
77
+ # ensure we clear the client
78
+ unless @token.present?
79
+ @token.client = nil
77
80
  return
78
81
  end
79
82
 
80
- return false unless @token
81
-
82
83
  # mitigate timing attacks by finding by uid instead of auth token
83
- user = uid && rc.find_by(uid: uid)
84
+ user = (uid && rc.dta_find_by(uid: uid)) || (other_uid && rc.dta_find_by("#{DeviseTokenAuth.other_uid}": other_uid))
85
+ scope = rc.to_s.underscore.to_sym
84
86
 
85
- if user && user.valid_token?(@token, @client_id)
87
+ if user && user.valid_token?(@token.token, @token.client)
86
88
  # sign_in with bypass: true will be deprecated in the next version of Devise
87
89
  if respond_to?(:bypass_sign_in) && DeviseTokenAuth.bypass_sign_in
88
- bypass_sign_in(user, scope: :user)
90
+ bypass_sign_in(user, scope: scope)
89
91
  else
90
- sign_in(:user, user, store: false, event: :fetch, bypass: DeviseTokenAuth.bypass_sign_in)
92
+ sign_in(scope, user, store: false, event: :fetch, bypass: DeviseTokenAuth.bypass_sign_in)
91
93
  end
92
94
  return @resource = user
93
95
  else
94
96
  # zero all values previously set values
95
- @client_id = nil
97
+ @token.client = nil
96
98
  return @resource = nil
97
99
  end
98
100
  end
99
101
 
100
102
  def update_auth_header
101
103
  # cannot save object if model has invalid params
104
+ return unless @resource && @token.client
102
105
 
103
- return unless @resource && @client_id
104
-
105
- # Generate new client_id with existing authentication
106
- @client_id = nil unless @used_auth_by_token
106
+ # Generate new client with existing authentication
107
+ @token.client = nil unless @used_auth_by_token
107
108
 
108
109
  if @used_auth_by_token && !DeviseTokenAuth.change_headers_on_each_request
109
110
  # should not append auth header if @resource related token was
110
111
  # cleared by sign out in the meantime
111
- return if @resource.reload.tokens[@client_id].nil?
112
+ return if @resource.reload.tokens[@token.client].nil?
112
113
 
113
- auth_header = @resource.build_auth_header(@token, @client_id)
114
+ auth_header = @resource.build_auth_headers(@token.token, @token.client)
114
115
 
115
116
  # update the response header
116
117
  response.headers.merge!(auth_header)
117
118
 
119
+ # set a server cookie if configured
120
+ if DeviseTokenAuth.cookie_enabled
121
+ set_cookie(auth_header)
122
+ end
118
123
  else
119
124
  unless @resource.reload.valid?
120
- @resource = resource_class.find(@resource.to_param) # errors remain after reload
125
+ @resource = @resource.class.find(@resource.to_param) # errors remain after reload
121
126
  # if we left the model in a bad state, something is wrong in our app
122
127
  unless @resource.valid?
123
128
  raise DeviseTokenAuth::Errors::InvalidModel, "Cannot set auth token in invalid model. Errors: #{@resource.errors.full_messages}"
@@ -129,38 +134,54 @@ module DeviseTokenAuth::Concerns::SetUserByToken
129
134
 
130
135
  private
131
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
+
132
144
  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
145
+ # Lock the user record during any auth_header updates to ensure
146
+ # we don't have write contention from multiple threads
147
+ @resource.with_lock do
148
+ # should not append auth header if @resource related token was
149
+ # cleared by sign out in the meantime
150
+ return if @used_auth_by_token && @resource.tokens[@token.client].nil?
151
+
152
+ _auth_header_from_batch_request = auth_header_from_batch_request
153
+
154
+ # update the response header
155
+ response.headers.merge!(_auth_header_from_batch_request)
156
+
157
+ # set a server cookie if configured and is not a batch request
158
+ if DeviseTokenAuth.cookie_enabled && !@is_batch_request
159
+ set_cookie(_auth_header_from_batch_request)
160
+ end
161
+ end # end lock
162
+ end
163
+
164
+ def set_cookie(auth_header)
165
+ cookies[DeviseTokenAuth.cookie_name] = DeviseTokenAuth.cookie_attributes.merge(value: auth_header.to_json)
145
166
  end
146
167
 
147
- def is_batch_request?(user, client_id)
168
+ def is_batch_request?(user, client)
148
169
  !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
170
+ user.tokens[client] &&
171
+ user.tokens[client]['updated_at'] &&
172
+ user.tokens[client]['updated_at'].to_time > @request_started_at - DeviseTokenAuth.batch_request_buffer_throttle
152
173
  end
153
174
 
154
175
  def auth_header_from_batch_request
155
176
  # determine batch request status after request processing, in case
156
177
  # another processes has updated it during that processing
157
- @is_batch_request = is_batch_request?(@resource, @client_id)
178
+ @is_batch_request = is_batch_request?(@resource, @token.client)
158
179
 
159
180
  auth_header = {}
160
181
  # extend expiration of batch buffer to account for the duration of
161
182
  # this request
162
183
  if @is_batch_request
163
- auth_header = @resource.extend_batch_buffer(@token, @client_id)
184
+ auth_header = @resource.extend_batch_buffer(@token.token, @token.client)
164
185
 
165
186
  # Do not return token for batch requests to avoid invalidated
166
187
  # tokens returned to the client in case of race conditions.
@@ -171,7 +192,7 @@ module DeviseTokenAuth::Concerns::SetUserByToken
171
192
  auth_header[DeviseTokenAuth.headers_names[:"expiry"]] = ' '
172
193
  else
173
194
  # update Authorization response header with new token
174
- auth_header = @resource.create_new_auth_token(@client_id)
195
+ auth_header = @resource.create_new_auth_token(@token.client)
175
196
  end
176
197
  auth_header
177
198
  end
@@ -2,38 +2,88 @@
2
2
 
3
3
  module DeviseTokenAuth
4
4
  class ConfirmationsController < DeviseTokenAuth::ApplicationController
5
+
5
6
  def show
6
- @resource = resource_class.confirm_by_token(params[:confirmation_token])
7
+ @resource = resource_class.confirm_by_token(resource_params[:confirmation_token])
8
+
9
+ if @resource.errors.empty?
10
+ yield @resource if block_given?
11
+
12
+ redirect_header_options = { account_confirmation_success: true }
13
+
14
+ if signed_in?(resource_name)
15
+ token = signed_in_resource.create_token
16
+ signed_in_resource.save!
7
17
 
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
18
+ redirect_headers = build_redirect_headers(token.token,
19
+ token.client,
20
+ redirect_header_options)
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)
12
25
  end
13
26
 
14
- client_id, token = @resource.create_token expiry: expiry
27
+ redirect_to(redirect_to_link, redirect_options)
28
+ else
29
+ if redirect_url
30
+ redirect_to DeviseTokenAuth::Url.generate(redirect_url, account_confirmation_success: false)
31
+ else
32
+ raise ActionController::RoutingError, 'Not Found'
33
+ end
34
+ end
35
+ end
15
36
 
16
- sign_in(@resource)
17
- @resource.save!
37
+ def create
38
+ return render_create_error_missing_email if resource_params[:email].blank?
18
39
 
19
- yield @resource if block_given?
40
+ @email = get_case_insensitive_field_from_resource_params(:email)
20
41
 
21
- redirect_header_options = { account_confirmation_success: true }
22
- redirect_headers = build_redirect_headers(token,
23
- client_id,
24
- redirect_header_options)
42
+ @resource = resource_class.dta_find_by(uid: @email, provider: provider)
43
+
44
+ return render_not_found_error unless @resource
45
+
46
+ @resource.send_confirmation_instructions({
47
+ redirect_url: redirect_url,
48
+ client_config: resource_params[:config_name]
49
+ })
25
50
 
26
- # give redirect value from params priority
27
- @redirect_url = params[:redirect_url]
51
+ return render_create_success
52
+ end
53
+
54
+ protected
28
55
 
29
- # fall back to default value if provided
30
- @redirect_url ||= DeviseTokenAuth.default_confirm_success_url
56
+ def render_create_error_missing_email
57
+ render_error(401, I18n.t('devise_token_auth.confirmations.missing_email'))
58
+ end
31
59
 
60
+ def render_create_success
61
+ render json: {
62
+ success: true,
63
+ message: success_message('confirmations', @email)
64
+ }
65
+ end
32
66
 
33
- redirect_to(@resource.build_auth_url(@redirect_url, redirect_headers))
67
+ def render_not_found_error
68
+ if Devise.paranoid
69
+ render_create_success
34
70
  else
35
- raise ActionController::RoutingError, 'Not Found'
71
+ render_error(404, I18n.t('devise_token_auth.confirmations.user_not_found', email: @email))
36
72
  end
37
73
  end
74
+
75
+ private
76
+
77
+ def resource_params
78
+ params.permit(:email, :confirmation_token, :config_name)
79
+ end
80
+
81
+ # give redirect value from params priority or fall back to default value if provided
82
+ def redirect_url
83
+ params.fetch(
84
+ :redirect_url,
85
+ DeviseTokenAuth.default_confirm_success_url
86
+ )
87
+ end
38
88
  end
39
89
  end