devise_token_auth 1.0.0 → 1.2.2

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.
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