So I've been playing around with authlogic in a new Rails 6 application just to see if I'd like to start using it to simplify the authentication in some other apps. I've basically set everything up as instructed on the github repo, about as barebones as you can get. Everything seems to work fine except user logout. In Chrome, everything seems to work as expected, the user is signed out as expected. But for some reason, accessing the /logout route doesn't actually log the user out - the web console shows the user_credentials cookie never gets deleted, user stays signed in (although the flash is displayed, so the correct route is being hit).
Oddly enough, if I add the logout_on_timeout feature and manually set current_user.last_request_at to say 20 minutes ago, I'm logged out in both browsers as expected.
I'll include all relevant code below, aside from an pages#index page with links to login/out and register, the only things not your standard new Rails app boilerplate is the authlogic stuff. I have tried current_user_session.destroy, the suggested alternative of session.destroy, and manually clearing the cookies with cookies.delete.
I have a feeling this is something basic, maybe a config option having to do with how the cookies are being sent? but I've just spent several hours trying to figure out what's going on. Any ideas?
Gemfile:
gem 'scrypt', '~> 3.0'
gem 'authlogic', '~> 6.0'
UserSessionsController
class UserSessionsController < ApplicationController
def new
@user_session = UserSession.new
end
def create
@user_session = UserSession.new(user_session_params.to_h)
if @user_session.save
flash[:success] = 'You have been logged in.'
redirect_to root_path
else
flash.now[:danger] = 'Unable to log you in'
render :new
end
end
def destroy
current_user_session.destroy
# session.destroy - tried this as well
flash[:success] = 'You have been logged out.'
redirect_to root_path
end
private
def user_session_params
params.require(:user_session).permit(:email, :password, :remember_me)
end
end
ApplicationController
class ApplicationController < ActionController::Base
helper_method :current_user_session, :current_user
private
def current_user_session
return @current_user_session if defined?(@current_user_session)
@current_user_session = UserSession.find
end
def current_user
return @current_user if defined?(@current_user)
@current_user = current_user_session && current_user_session.user
end
end
UserSession Model
class UserSession < Authlogic::Session::Base
logout_on_timeout true
end
User Model
class User < ApplicationRecord
acts_as_authentic do |c|
c.crypto_provider = ::Authlogic::CryptoProviders::SCrypt
end
validates :email,
format: {
with: /@/,
message: "should look like an email address"
},
length: { maximum: 100 },
uniqueness: {
case_sensitive: false,
if: :will_save_change_to_email?
}
validates :password,
confirmation: { if: :require_password? },
length: {
minimum: 8,
if: :require_password?
}
validates :password_confirmation,
length: {
minimum: 8,
if: :require_password?
}
end
Basic Index View
Just to test login/out functionality
<% if current_user %>
<p>Logged in as <strong><%= current_user.email %></strong>. <%= link_to 'Log Out', user_session_path, method: :delete %></p>
<% else %>
<p>You are not logged in. <%= link_to 'Log In', new_user_session_path %> or <%= link_to 'Register', new_user_path %></p>
<% end %>
Finally the CreateUsers migration
class CreateUsers < ActiveRecord::Migration[6.0]
def change
create_table :users do |t|
# Authlogic::ActsAsAuthentic::Email
t.string :email
t.index :email, unique: true
# Authlogic::ActsAsAuthentic::Password
t.string :crypted_password
t.string :password_salt
# Authlogic::ActsAsAuthentic::PersistenceToken
t.string :persistence_token
t.index :persistence_token, unique: true
# Authlogic::ActsAsAuthentic::SingleAccessToken
t.string :single_access_token
t.index :single_access_token, unique: true
# Authlogic::ActsAsAuthentic::PerishableToken
t.string :perishable_token
t.index :perishable_token, unique: true
# See "Magic Columns" in Authlogic::Session::Base
t.integer :login_count, default: 0, null: false
t.integer :failed_login_count, default: 0, null: false
t.datetime :last_request_at
t.datetime :current_login_at
t.datetime :last_login_at
t.string :current_login_ip
t.string :last_login_ip
# See "Magic States" in Authlogic::Session::Base
# t.boolean :active, default: false
# t.boolean :approved, default: false
# t.boolean :confirmed, default: false
# Additional
t.string :first_name
t.string :last_name
t.string :unconfirmed_email
t.index :unconfirmed_email, unique: true
t.timestamps
end
end
end
Does your problem arise on a non-SSL environment (i.e. local test)?
In that case I would recommend trying the following fix. I had a vaguely similar problem that was fixed by this:
Source: https://github.com/binarylogic/authlogic/issues/719#issuecomment-631509593