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