Files
once-campfire/app/controllers/sessions_controller.rb
T
Jeremy Daer 19319a1cff Refuse a session for a password that changed after it was checked
A password change ends every session, but a sign-in or sign-in link checked
against the old password just before the change could still save its session
just after, and that session outlived the change.

The session now checks, as it's saved, that the user's password is still the
one the request loaded. The save's transaction holds SQLite's write lock from
the start, so a change commits either before the check, which fails it, or
after the insert, and ends this session with the others. Sessions start
through the user's association so the check sees the user that was
authenticated, and a refused sign-in is answered like a wrong password.
2026-10-20 08:37:07 -07:00

43 lines
1.1 KiB
Ruby

class SessionsController < ApplicationController
allow_unauthenticated_access only: %i[ new create ]
rate_limit to: 10, within: 3.minutes, only: :create, with: -> { render_rejection :too_many_requests }
before_action :ensure_user_exists, only: :new
def new
end
def create
if user = User.active.authenticate_by(email_address: params[:email_address], password: params[:password])
start_new_session_for user
redirect_to post_authenticating_url
else
render_rejection :unauthorized
end
rescue ActiveRecord::RecordInvalid
render_rejection :unauthorized
end
def destroy
remove_push_subscription
terminate_current_session
redirect_to root_url
end
private
def ensure_user_exists
redirect_to first_run_url if User.none?
end
def render_rejection(status)
flash.now[:alert] = "Too many requests or unauthorized."
render :new, status: status
end
def remove_push_subscription
if endpoint = params[:push_subscription_endpoint]
Push::Subscription.destroy_by(endpoint: endpoint, user_id: Current.user.id)
end
end
end