From d1e3a4fa2123133e2265da5e86ae09156f755aa6 Mon Sep 17 00:00:00 2001 From: Bryce Kwon Date: Fri, 16 Oct 2026 22:14:44 -1000 Subject: End a session when its account's hash changes A session stayed good for its whole week after the password changed or the account went away, which is when ending it matters most. --- tests/extensions/test-auth.lua | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'tests/extensions/test-auth.lua') diff --git a/tests/extensions/test-auth.lua b/tests/extensions/test-auth.lua index eb402da..92e82eb 100644 --- a/tests/extensions/test-auth.lua +++ b/tests/extensions/test-auth.lua @@ -28,6 +28,7 @@ if variant == "file" then local users_file = io.open("auth-users", "w") users_file:write("Alice:" .. stored_hash .. "\r\n") users_file:write("not a parsable line\n") + users_file:write("carol:" .. stored_hash .. "\n") users_file:close() local groups_file = io.open("auth-groups", "w") groups_file:write("devs:Alice, bob\n") @@ -50,7 +51,8 @@ if variant == "inline" then "\t[\"empty-repo\"] = {},\n" .. "\t[\"bare-repo\"] = {},\n" }, { "local users = {\n", "local users = {\n" .. - "\tAlice = \"" .. stored_hash .. "\",\n" }, + "\tAlice = \"" .. stored_hash .. "\",\n" .. + "\tcarol = \"" .. stored_hash .. "\",\n" }, }) else h.load(script) @@ -228,14 +230,28 @@ h.equals("a public repository needs no cookie", ret, 1) out, ret = run_action("authenticate-cookie", { repo = "secret-repo" }) h.equals("a protected repository turns a bare request away", ret, 0) -local session = secure_value("username", "Alice", now + 3600) +local session = secure_value("username", "Alice", now + 3600, stored_hash) out, ret = run_action("authenticate-cookie", { repo = "secret-repo", cookie = "cgitauth=" .. session }) h.equals("a signed session for a member is let through", ret, 1) +-- A session is signed with its account's hash, so a new password or a +-- removed account ends it. +local stale = secure_value("username", "Alice", now + 3600, "$6$rounds=300000$old$hash") +out, ret = run_action("authenticate-cookie", { repo = "secret-repo", cookie = "cgitauth=" .. stale }) +h.equals("a session from before a password change is turned away", ret, 0) + +local orphan = secure_value("username", "bob", now + 3600, stored_hash) +out, ret = run_action("authenticate-cookie", { repo = "secret-repo", cookie = "cgitauth=" .. orphan }) +h.equals("a session for a member with no account is turned away", ret, 0) + +local unbound = secure_value("username", "Alice", now + 3600) +h.equals("a session signed without its binding does not verify", + validate_value("username", unbound, account_hash), nil) + out, ret = run_action("authenticate-cookie", { repo = "empty-repo", cookie = "cgitauth=" .. session }) h.equals("a memberless repository denies even a valid session", ret, 0) -local outsider = secure_value("username", "carol", now + 3600) +local outsider = secure_value("username", "carol", now + 3600, stored_hash) out, ret = run_action("authenticate-cookie", { repo = "secret-repo", cookie = "cgitauth=" .. outsider }) h.equals("a signed session for an outsider is turned away", ret, 0) @@ -265,7 +281,7 @@ out, ret = run_action("authenticate-post", { h.contains("a good login redirects back", out, "Status: 302") h.contains("to where the form said", out, "Location: /repo/\n") local granted = out:match("Set%-Cookie: cgitauth=([^;]*);") -h.equals("and grants a session that verifies", granted and validate_value("username", granted), "Alice") +h.equals("and grants a session that verifies", granted and validate_value("username", granted, account_hash), "Alice") out, ret = run_action("authenticate-post", { method = "POST", -- cgit