Skip to content

Commit 76f3c74

Browse files
committed
Add method to refresh session auth hash upon changing a user's password
1 parent fbfeee5 commit 76f3c74

File tree

2 files changed

+35
-1
lines changed

2 files changed

+35
-1
lines changed

spec/marten_auth_spec.cr

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,27 @@ describe MartenAuth do
201201
end
202202
end
203203

204+
describe "::update_session_auth_hash" do
205+
it "updates the user session auth hash as expected" do
206+
user = create_user(email: "test@example.com", password: "insecure")
207+
208+
session_store = Marten::HTTP::Session::Store::Cookie.new("sessionkey")
209+
session_store["_auth_user_hash"] = "oldvalue"
210+
211+
request = Marten::HTTP::Request.new(
212+
method: "GET",
213+
resource: "/test/xyz",
214+
headers: HTTP::Headers{"Host" => "example.com"},
215+
)
216+
request.session = session_store
217+
request.user = user
218+
219+
MartenAuth.update_session_auth_hash(request, user)
220+
221+
session_store["_auth_user_hash"].should eq user.session_auth_hash
222+
end
223+
end
224+
204225
describe "::valid_password_reset_token?" do
205226
it "returns true for a valid password reset token" do
206227
user = create_user(email: "test@example.com", password: "insecure")

src/marten_auth.cr

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,19 @@ module MartenAuth
7171
request.user = nil
7272
end
7373

74+
# Refreshes the session auth hash for the current session.
75+
#
76+
# Calling this method may be necessary after changing a user's password, otherwise this user would be logged out of
77+
# all their sessions. This method ensures that the session auth hash of the user for the current session is refreshed
78+
# so that this user does not end up being logged out.
79+
def self.update_session_auth_hash(request : Marten::HTTP::Request, user : BaseUser) : Nil
80+
request.session.cycle_key
81+
82+
if request.session[USER_HASH_SESSION_KEY]? && request.user == user
83+
request.session[USER_HASH_SESSION_KEY] = user.session_auth_hash
84+
end
85+
end
86+
7487
# Returns a boolean indicating if the passed password reset token is valid for the considered `user`.
7588
def self.valid_password_reset_token?(user : BaseUser, token : String) : Bool
7689
decrypted = Hash(String, String).from_json(password_reset_token_encryptor.decrypt!(token))
@@ -84,7 +97,7 @@ module MartenAuth
8497
end
8598

8699
# Returns a boolean indicating if the authentication hash in the session corresponds to the passed `user`'s one.
87-
def self.valid_session_hash?(request, user)
100+
def self.valid_session_hash?(request : Marten::HTTP::Request, user : BaseUser)
88101
Crypto::Subtle.constant_time_compare(
89102
request.session[USER_HASH_SESSION_KEY]? || "",
90103
user.session_auth_hash

0 commit comments

Comments
 (0)