Search code examples
ruby-on-railsrubydevisedevise-invitable

Different hashed value for same invitation token


I'm using Devise in my Rails for auth and devise_invitable to send out invitations to users.

I've run into a weird issue on my staging and production environments. This is something that has not come up in our local environments or in our development environment. A significant difference between the environments is that staging and production environments have load balancers in front of the app servers but the rest of the setup is similar.

When the user clicks on the invite link (which contains the raw token as a param), seemingly randomly, the raw token will get hashed to a completely different value before the lookup which results in it failing. Here are some sample logs.

Token in DB:

5d44e5c9175eebbd93737ad9db2bc83fe252c89218e6767a42c1ff8b85dd8029

Request 1 (Failed)

Started GET "/organizations/7/invitation/accept?invitation_token=FopqamFqA7zhXgXkQXQ7" for 50.156.8.77 at 2014-10-03 17:40:28 +0000
Processing by InvitationsController#edit as HTML
Parameters: {"invitation_token"=>"FopqamFqA7zhXgXkQXQ7", "id"=>"7"}
User Load (1.6ms)  SELECT  `users`.* FROM `users`  WHERE `users`.`invitation_token` = 'cf7f5029d134035c196739e8c5be9a9cdc54ad3fb9ae349f6567d29aea8b7165'  ORDER BY `users`.`id` ASC LIMIT 1
Filter chain halted as :resource_from_invitation_token rendered or redirected

Request 2 (Success)

Started GET "/organizations/7/invitation/accept?invitation_token=FopqamFqA7zhXgXkQXQ7" for 50.156.8.77 at 2014-10-03 17:49:41 +0000
Processing by InvitationsController#edit as HTML
Parameters: {"invitation_token"=>"FopqamFqA7zhXgXkQXQ7", "id"=>"7"}
User Load (1.5ms)  SELECT  `users`.* FROM `users`  WHERE `users`.`invitation_token` = '5d44e5c9175eebbd93737ad9db2bc83fe252c89218e6767a42c1ff8b85dd8029'  ORDER BY `users`.`id` ASC LIMIT 1

Request 3 (Failed)

Started GET "/organizations/7/invitation/accept?invitation_token=FopqamFqA7zhXgXkQXQ7" for 50.156.8.77 at 2014-10-03 17:54:58 +0000
Processing by InvitationsController#edit as HTML
Parameters: {"invitation_token"=>"FopqamFqA7zhXgXkQXQ7", "id"=>"7"}
User Load (1.2ms)  SELECT  `users`.* FROM `users`  WHERE `users`.`invitation_token` = '69e87f81483b22c5be1a1b93dcb6fcebcd8396b172b7a85cbf17cb0ba5784cc8'  ORDER BY `users`.`id` ASC LIMIT 1
Filter chain halted as :resource_from_invitation_token rendered or redirected

Here is what my Invitations Controller's edit method looks like:

def edit
    if resource.present? && resource.organization.present?
      @guest_organization = resource.organization
    end
    super
end

Relevant Versions: ruby 2.1.2, rails 4.1.0, devise 3.2.4, devise_invitable 1.3.4

As is visible in the logs, the raw token in the params are identical but the hashed value is different each time. I (unfortunately) cannot replicate this in dev or locally.

Has anybody run into something like this?


Solution

  • Devise uses the app's secret_key_base to to generate the digest.

    I had mine set to this:

    Ginseng::Application.config.secret_token = "#{SecureRandom.hex(64)}"
    Ginseng::Application.config.secret_key_base = "#{SecureRandom.hex(64)}"
    

    So the secret_key_base changed with every deploy / restart and was different on each app server - resulting in the hashed token mismatch.

    Changing secret_token.rb to this:

    Ginseng::Application.config.secret_token = ENV['secret_token']
    Ginseng::Application.config.secret_key_base = ENV['secret_key_base']
    

    solved the problem.