Skip to content

undefined method '[]' for nil:NilClass when confirming email #1224

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
moray95 opened this issue Oct 5, 2018 · 9 comments
Closed

undefined method '[]' for nil:NilClass when confirming email #1224

moray95 opened this issue Oct 5, 2018 · 9 comments

Comments

@moray95
Copy link
Contributor

moray95 commented Oct 5, 2018

Hello,

I am getting a undefined method '[]' for nil:NilClass error when confirming an email. The issue appears very rarely and requires some luck to reproduce. I have noticed the issue appears because the user's tokens doesn't contain the given client id in the line tokens[args[:client_id]]['expiry']. I have been able to reproduce the issue locally (again with very low reproducibility rate) by clicking multiple times to the confirmation link sent by mail. You can find additional information below.

vendor/bundle/ruby/2.5.0/gems/devise_token_auth-0.2.0/app/models/devise_token_auth/concerns/user.rb:211:in `build_auth_url'
vendor/bundle/ruby/2.5.0/gems/devise_token_auth-0.2.0/app/controllers/devise_token_auth/confirmations_controller.rb:26:in `show'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/action_controller/metal/basic_implicit_render.rb:6:in `send_action'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/abstract_controller/base.rb:194:in `process_action'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/action_controller/metal/rendering.rb:30:in `process_action'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/abstract_controller/callbacks.rb:42:in `block in process_action'
vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.1/lib/active_support/callbacks.rb:109:in `block in run_callbacks'
vendor/bundle/ruby/2.5.0/gems/sentry-raven-2.7.4/lib/raven/integrations/rails/controller_transaction.rb:7:in `block in included'
vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.1/lib/active_support/callbacks.rb:118:in `instance_exec'
vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.1/lib/active_support/callbacks.rb:118:in `block in run_callbacks'
vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.1/lib/active_support/callbacks.rb:136:in `run_callbacks'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/abstract_controller/callbacks.rb:41:in `process_action'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/action_controller/metal/rescue.rb:22:in `process_action'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/action_controller/metal/instrumentation.rb:34:in `block in process_action'
vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.1/lib/active_support/notifications.rb:168:in `block in instrument'
vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.1/lib/active_support/notifications/instrumenter.rb:23:in `instrument'
vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.1/lib/active_support/notifications.rb:168:in `instrument'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/action_controller/metal/instrumentation.rb:32:in `process_action'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/action_controller/metal/params_wrapper.rb:256:in `process_action'
vendor/bundle/ruby/2.5.0/gems/activerecord-5.2.1/lib/active_record/railties/controller_runtime.rb:24:in `process_action'
vendor/bundle/ruby/2.5.0/gems/sql_queries_count-0.0.1/lib/sql_queries_count/controller_runtime.rb:14:in `process_action'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/abstract_controller/base.rb:134:in `process'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/action_controller/metal.rb:191:in `dispatch'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/action_controller/metal.rb:252:in `dispatch'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/action_dispatch/routing/route_set.rb:52:in `dispatch'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/action_dispatch/routing/route_set.rb:34:in `serve'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/action_dispatch/routing/mapper.rb:18:in `block in <class:Constraints>'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/action_dispatch/routing/mapper.rb:48:in `serve'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/action_dispatch/journey/router.rb:52:in `block in serve'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/action_dispatch/journey/router.rb:35:in `each'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/action_dispatch/journey/router.rb:35:in `serve'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/action_dispatch/routing/route_set.rb:840:in `call'
vendor/bundle/ruby/2.5.0/gems/scout_apm-2.4.19/lib/scout_apm/instant/middleware.rb:53:in `call'
vendor/bundle/ruby/2.5.0/gems/scout_apm-2.4.19/lib/scout_apm/middleware.rb:20:in `call'
vendor/bundle/ruby/2.5.0/gems/rack-cors-1.0.2/lib/rack/cors.rb:97:in `call'
vendor/bundle/ruby/2.5.0/gems/rack-attack-5.4.0/lib/rack/attack.rb:181:in `call'
vendor/bundle/ruby/2.5.0/gems/warden-1.2.7/lib/warden/manager.rb:36:in `block in call'
vendor/bundle/ruby/2.5.0/gems/warden-1.2.7/lib/warden/manager.rb:35:in `catch'
vendor/bundle/ruby/2.5.0/gems/warden-1.2.7/lib/warden/manager.rb:35:in `call'
vendor/bundle/ruby/2.5.0/gems/rack-2.0.5/lib/rack/etag.rb:25:in `call'
vendor/bundle/ruby/2.5.0/gems/rack-2.0.5/lib/rack/conditional_get.rb:25:in `call'
vendor/bundle/ruby/2.5.0/gems/rack-2.0.5/lib/rack/head.rb:12:in `call'
vendor/bundle/ruby/2.5.0/gems/activerecord-5.2.1/lib/active_record/migration.rb:559:in `call'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'
vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.1/lib/active_support/callbacks.rb:98:in `run_callbacks'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/action_dispatch/middleware/callbacks.rb:26:in `call'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/action_dispatch/middleware/executor.rb:14:in `call'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/action_dispatch/middleware/debug_exceptions.rb:61:in `call'
vendor/bundle/ruby/2.5.0/gems/web-console-3.7.0/lib/web_console/middleware.rb:135:in `call_app'
vendor/bundle/ruby/2.5.0/gems/web-console-3.7.0/lib/web_console/middleware.rb:30:in `block in call'
vendor/bundle/ruby/2.5.0/gems/web-console-3.7.0/lib/web_console/middleware.rb:20:in `catch'
vendor/bundle/ruby/2.5.0/gems/web-console-3.7.0/lib/web_console/middleware.rb:20:in `call'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
vendor/bundle/ruby/2.5.0/gems/railties-5.2.1/lib/rails/rack/logger.rb:38:in `call_app'
vendor/bundle/ruby/2.5.0/gems/railties-5.2.1/lib/rails/rack/logger.rb:26:in `block in call'
vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.1/lib/active_support/tagged_logging.rb:71:in `block in tagged'
vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.1/lib/active_support/tagged_logging.rb:28:in `tagged'
vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.1/lib/active_support/tagged_logging.rb:71:in `tagged'
vendor/bundle/ruby/2.5.0/gems/railties-5.2.1/lib/rails/rack/logger.rb:26:in `call'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/action_dispatch/middleware/request_id.rb:27:in `call'
vendor/bundle/ruby/2.5.0/gems/rack-2.0.5/lib/rack/runtime.rb:22:in `call'
vendor/bundle/ruby/2.5.0/gems/activesupport-5.2.1/lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/action_dispatch/middleware/executor.rb:14:in `call'
vendor/bundle/ruby/2.5.0/gems/actionpack-5.2.1/lib/action_dispatch/middleware/static.rb:127:in `call'
vendor/bundle/ruby/2.5.0/gems/rack-2.0.5/lib/rack/sendfile.rb:111:in `call'
vendor/bundle/ruby/2.5.0/gems/sentry-raven-2.7.4/lib/raven/integrations/rack.rb:51:in `call'
vendor/bundle/ruby/2.5.0/gems/railties-5.2.1/lib/rails/engine.rb:524:in `call'
vendor/bundle/ruby/2.5.0/gems/puma-3.12.0/lib/puma/configuration.rb:225:in `call'
vendor/bundle/ruby/2.5.0/gems/puma-3.12.0/lib/puma/server.rb:658:in `handle_request'
vendor/bundle/ruby/2.5.0/gems/puma-3.12.0/lib/puma/server.rb:472:in `process_client'
vendor/bundle/ruby/2.5.0/gems/puma-3.12.0/lib/puma/server.rb:332:in `block in run'
vendor/bundle/ruby/2.5.0/gems/puma-3.12.0/lib/puma/thread_pool.rb:133:in `block in spawn_thread'
  • Environmental Info:
    • Routes: default routes
    • Gems: pg
    • Custom Overrides: none
    • Custom Frontend: mobile app
@moray95 moray95 changed the title undefined method '[]' for nil:NilClass undefined method '[]' for nil:NilClass when confirming email Oct 5, 2018
@moray95 moray95 changed the title undefined method '[]' for nil:NilClass when confirming email undefined method '[]' for nil:NilClass when confirming email Oct 5, 2018
@VicenteFava
Copy link

VicenteFava commented Nov 21, 2018

I'm having the same issue. I'm not sure but IMO the issue is in the line 11 of the confirmations_controller.rb

expiry = (Time.zone.now + 1.second).to_i

It looks like one second is not enough. If this is correct, I can submit a pull request with a new time.

@MaicolBen
Copy link
Collaborator

This might be fixed in #1250, post here if it's still happening when you have this gem from the master branch, otherwise I will close this in 1 month

@moray95
Copy link
Contributor Author

moray95 commented Mar 26, 2019

@MaicolBen I am still seeing the same issue on the lasted commit on master (f929fb4). If it's of any use, I used the following script to test:

require 'faker'

user = User.new(email: Faker::Internet.email, password: '123456789')
user.save!

while true do
  response = HTTParty.get("http://localhost:3000/auth/confirmation", query: { config: :default, confirmation_token: user.confirmation_token, redirect_url: 'https://google.com' })
  if response.code > 299
    p response
    exit 1
  end
end

@dks17
Copy link
Contributor

dks17 commented Mar 27, 2019

You must provide provider attribute:

User.new(email: Faker::Internet.email, password: '123456789').valid?
=> false
User.new(email: Faker::Internet.email, password: '123456789', provider: 'email').valid?
=> true

@moray95
Copy link
Contributor Author

moray95 commented Mar 27, 2019

True, but I configured my User model to set the default provider as email.

@dks17
Copy link
Contributor

dks17 commented Mar 27, 2019

Checked. Works as expected.

200
#<HTTParty::Request:0x0000558df166c810
 @changed_hosts=true,
 @credentials_sent=false,
 @http_method=Net::HTTP::Get,
 @last_response=#<Net::HTTPOK 200 OK readbody=true>,
 @last_uri=
  #<URI::HTTPS https://www.google.com/?account_confirmation_success=true>,
 @options=
  {:limit=>3,
   :assume_utf16_is_big_endian=>true,
   :default_params=>{},
   :follow_redirects=>true,
   :parser=>HTTParty::Parser,
   :uri_adapter=>URI,
   :connection_adapter=>HTTParty::ConnectionAdapter,
   :query=>
    {:config=>:default,
     :confirmation_token=>"qNzEjKqat1-pzKzs1KA8",
     :redirect_url=>"https://google.com"}},
 @path=#<URI::HTTPS https://www.google.com/?account_confirmation_success=true>,
 @raw_request=#<Net::HTTP::Get GET>,
 @redirect=true>

You do something wrong. You need to know confirmation_token value until you make a request. I think you create user in one environment after try to get request to another one (test and development).

Once again. Create user in a database. Copy confirmation_token. Paste the token into you script.

Play with it:

  1. run rails s in terminal.
  2. run rails c in another terminal and paste there this code:
require 'httparty'

User.delete_all
user = User.new(email: '[email protected]', password: '123456789', provider: 'email')
user.valid?
user.save

response = HTTParty.get("http://localhost:3000/auth/confirmation",
   query: {
     config: :default,
     confirmation_token: user.confirmation_token,
     redirect_url: 'https://google.com' }); nil

response.request

@moray95
Copy link
Contributor Author

moray95 commented Mar 28, 2019

@dks17 I have checked and I am sure that during testing I am using the same environment, I am even seeing this issue in production (only by user interaction) and this is my attempt at reproducing it. Your attempt may have worked because the issue is not 100% reproducible as I stated in the original description, that's why I am sending requests in a loop. I will try to setup a blank project and try to reproduce the issue when I have some time.

@dks17
Copy link
Contributor

dks17 commented Mar 28, 2019

With every reply you give a new small peace of a puzzle. Try to collect all you can and put here at once: user attributes, controller params, request and e.t.c. Don't invent new code that loose relates with you issue like Faker::Internet.email. Because Faker::Internet.email does not provide unique email address and sometimes the tests are failed because of it.

If params[:confirmation_token] contain a token that is not persisted in a database this code returns new user object:

def show
@resource = resource_class.confirm_by_token(params[:confirmation_token])
if @resource.errors.empty?

@resource = resource_class.confirm_by_token('23')
#=> #<User id: nil, email: nil, reset_password_redirect_url: nil, allow_password_change: false, name: nil, nickname: nil, image: nil, provider: nil, uid: "", created_at: nil, updated_at: nil, operating_thetan: nil, favorite_color: nil>
@resource.valid?
#=> false

And the last. Update the stack trace you provided in the top message after update to the new version of the gem.

@moray95
Copy link
Contributor Author

moray95 commented Mar 28, 2019

I am currently unable to reproduce the issue against the current master, probably done something wrong during my last test. Therefore, I am closing the issue. Just as a side note, the issue seems to be even fixed in 1.1.0, which doesn't seem to include #1250. Thanks for the help you provided.

@moray95 moray95 closed this as completed Mar 28, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants