I am using devise invitable in my app and for some reason I cannot accept the invitation. When inspecting the logs I keep seeing the message:
Filter chain halted as :resource_from_invitation_token rendered or redirected
When inspecting the Devise code, I see the function is:
def resource_from_invitation_token
unless params[:invitation_token] && self.resource = resource_class.find_by_invitation_token(params[:invitation_token], true)
set_flash_message(:alert, :invitation_token_invalid) if is_flashing_format?
redirect_to after_sign_out_path_for(resource_name)
end
end
The part causing the issue is the resource_class.find_by_invitation_token(params[:invitation_token], true) becuase when I attempt to run User.find_by_invitation_token(TOKEN, true), it comes up as nil in my console.
When I pull up the user in question and check it's :invitation_token it is not equal to the value being checked when attempting to accept the invitation
# User that is attempting to accept the invitation
> #<User id: 20786, email: "email_goes_here", created_at: "2018-11-06 19:39:29", updated_at: "2018-11-06 19:39:29", admin: false, employee: false, is_client: true, user_type: 5.0, location_id: 1, auth_token: nil, unlock: nil, deleted_at: nil, user_types_id: nil>
# Token from activation email
2.3.4 :003 > token = "GajU3sLy3r5exmzfqWKw"
=> "GajU3sLy3r5exmzfqWKw"
# Should return the user, but instead returns nil
2.3.4 :004 > User.find_by_invitation_token(token, true)
User Load (4.8ms) SELECT "users".* FROM "users" WHERE "users"."invitation_token" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["invitation_token", "b821be248a157559b10b7e5b908effd9fa13ec158cfb26b8d908cbad7f57f59e"], ["LIMIT", 1]]
=> nil
# Should return value being used in find_by_invitation_token "b821be248a1..." but returns something else
2.3.4 :006 > User.last.invitation_token
User Load (1.1ms) SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT $1 [["LIMIT", 1]]
=> "fc56c527eba7fcf0b821a1289bf9083563527cd41612057521e173f26930f7f4"
Just in case anyone runs into this question in the future, this is my understanding of Devise Invitable:
On the initial INVITE of a user it creates a raw token value (temporary accessor value of
raw_invitation_tokenon the invitable object and then hashes that into theinvitation_tokenfield on the model.So, the value in the url is the 'raw' token and then Devise Invitable does a one way hash lookup, for security purposes, to see if
raw_invitation_token-> one way hash algorithm -> model'sinvitation_tokenvalue in database returns anything.If it does NOT find any values based on that lookup, it silently fails.