AuthLogic perishable_token resets on every request
perishable_token_valid_for
isn't doing what you think it is. It's intended to work in tandem with find_using_perishable_token
which is intended for things like account validation and resetting a forgotten password. The default timeout is 10 minutes.
The token is supposed to update on every request like it's doing. You can just remove the column if you don't want it. It's completely optional with authlogic.
If you really do want to keep the perishable token but update it completely by hand, you can do disable_perishable_token_maintenance = true
Authlogic Perishable Token Resetting on Failed Login
So we eventually figured out a way around this.
First move was to disable the automatic perishable token handling:
#############
## Authlogic
acts_as_authentic do |c|
.....
c.disable_perishable_token_maintenance = true
.....
end
Then we created our own before_filter on user to mimic the same functionality as the auto handler but ignore changes to the failed_login_count field:
before_save :handle_perishable_token
def handle_perishable_token
unless failed_login_count_changed?
reset_perishable_token
end
end
This basically allows a user to fail at logging in and not reset the perishable token.
Authlogic: How to find if a user was not logged in because the user was not logged in
Rather than check for the actual error, I was able to check for the conditions that cause it using @user_session.attempted_record && !@user_session.invalid_password? &&
!@user_session.attempted_record.active?
Here's my full solution to resending activation emails (after setting up activation using matthook's tutorial):
# /app/controllers/users_sessions_controler.rb
def create
@user_session = UserSession.new(params[:user_session])
if @user_session.save
redirect_back_or_default root_path
elsif @user_session.attempted_record &&
!@user_session.invalid_password? &&
!@user_session.attempted_record.active?
flash[:notice] = render_to_string(:partial => 'user_sessions/not_active.erb', :locals => { :user => @user_session.attempted_record })
redirect_to :action => :new
else
render :action => :new
end
end
# /app/views/user_sessions/_not_active.erb
Sorry, before you can sign in you need to confirm your email address. <%= link_to('Resend confirmation email', resend_activation_users_path(:login => user.login)) %>
# /app/controllers/users_controller.rb
def resend_activation
if params[:login]
@user = User.find_by_login params[:login]
if @user && !@user.active?
@user.deliver_activation_instructions!
flash[:notice] = "Please check your e-mail for your account activation instructions!"
redirect_to root_path
end
end
end
# /config/routes.rb
map.resources :users, :collection => { :resend_activation => :get }
Database write delayed in rails controller?
To answer my question, the problem was not a bad database write - it was that the authlogic library automatically updates the perishable token every time you save the database record. I was sending the token, then saving the user record which reset the token! There is a config setting that I needed:
disable_perishable_token_maintenance = true
That did the trick and fixed my bug
How do I get AuthLogic to skip Password validation?
Doesn't UserSession.create take a user object as it's first argument? If so, couldn't you just do:
UserSession.create(User.find_by_perishable_token(params[:token]))
@current_user_session = UserSession.find
Or is that where you're running into problems?
Authlogic and multiple sessions for the same user
Ok so the perishable token was absolutely not the right path ;)
We "just" need to reset the persistence token every time a user logs in or logs out.
With this in my UserSession model, every user gets logged off from any other session when logging in.
class UserSession < Authlogic::Session::Base
before_destroy :reset_persistence_token
before_create :reset_persistence_token
def reset_persistence_token
record.reset_persistence_token
end
end
Problem with forgot password and authlogic
If I'm reading that trace properly then it looks to me like password_reset_instructions
has been declared as a no-argument method. That's what the (1 for 0)
complaint is about. Can you check that you have included the user
argument in the definition, as below?
class Notifier < ActionMailer::Base
def password_reset_instructions(user)
end
end
If you've been staring at it for hours it's probably not that simple but worth making sure.
caching with memcached
Are you using the perishable token? This SO question says you can either remove that column, or set disable_perishable_token_maintenance = true
to prevent the update-db hit per page load.
As for caching -- in general you can cache non-personalized data for everyone, and personalized data for only that person. So yes, you could cache that block, but the key would need to have the user_id in it.
Related Topics
How to Reference a Method in Another Ruby Code File
Rails 5.0.0 When Installing "Nio4R":Failed to Build Gem Native Extension
Is Getting Converted as "\U0092" by Nokogiri in Ruby on Rails
Why Does a Simple Thin Server Stop Responding at 16500 Requests When Benchmarking
Ruby Elegant Way to Return Min/Max If Value Outside Range
Keyword for Exclusive or in Ruby
Using S3 Presigned-Url for Upload a File That Will Then Have Public-Read Access
Rails: Undefined Method 'Truncate' in Model
In Rails, How to Access Response.Body in a Action Before It Returns
How to Create a Charge and a Customer in Stripe (Rails)
Actioncable - Failed to Upgrade to Websocket in Production
How to Cleanly Verify If the User Input Is an Integer in Ruby
Catching Timeout Errors with Ruby Mechanize
How to Implement Yes/No Instead of Boolean for Certain Cases in Rails