fix: harden SSO ticket flow and revoke tickets on logout
Reuse the outstanding auth_ticket instead of minting a fresh one on every /client load, so reloading the page or opening a second tab no longer invalidates a game session that is still connecting. New tickets are minted with a guard against the previously-read value so concurrent launches converge on the same ticket. Revoke the auth_ticket when signing out (toolbar, header and sign-out everywhere) so a leaked ticket can no longer be replayed against the emulator, and prevent SSO leakage via referral by setting no-referrer on the client iframe. Strip all whitespace from the ticket prefix and build the launch URL through a tested helper that handles query strings, existing sso params and URL fragments correctly.
This commit is contained in:
1 parent
ca59a1065f
commit
7f39ba4257
7 files changed
+231
-28
No files matched your search
@@ -0,0 +1,49 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { buildClientLoginUrl } from "./client-url";
|
||||
|
||||
describe("buildClientLoginUrl", () => {
|
||||
it("appends sso to a clean URL", () => {
|
||||
expect(buildClientLoginUrl("https://game.hotel.nl", "Hotel-uuid")).toBe(
|
||||
"https://game.hotel.nl?sso=Hotel-uuid",
|
||||
);
|
||||
});
|
||||
|
||||
it("uses & when a query string already exists", () => {
|
||||
expect(
|
||||
buildClientLoginUrl(
|
||||
"https://game.hotel.nl/nitro?mode=nostrip&debug=1",
|
||||
"Hotel-uuid",
|
||||
),
|
||||
).toBe("https://game.hotel.nl/nitro?mode=nostrip&debug=1&sso=Hotel-uuid");
|
||||
});
|
||||
|
||||
it("replaces an existing sso param", () => {
|
||||
expect(
|
||||
buildClientLoginUrl("https://game.hotel.nl/nitro?sso=old&mode=1", "new"),
|
||||
).toBe("https://game.hotel.nl/nitro?mode=1&sso=new");
|
||||
expect(
|
||||
buildClientLoginUrl("https://game.hotel.nl/nitro?sso=old", "new"),
|
||||
).toBe("https://game.hotel.nl/nitro?sso=new");
|
||||
});
|
||||
|
||||
it("keeps a fragment after the sso param", () => {
|
||||
expect(
|
||||
buildClientLoginUrl("https://game.hotel.nl/nitro#entry", "h-u"),
|
||||
).toBe("https://game.hotel.nl/nitro?sso=h-u#entry");
|
||||
expect(
|
||||
buildClientLoginUrl("https://game.hotel.nl/nitro?sso=old#entry", "h-u"),
|
||||
).toBe("https://game.hotel.nl/nitro?sso=h-u#entry");
|
||||
});
|
||||
|
||||
it("leaves any existing non-sso fragment intact", () => {
|
||||
expect(
|
||||
buildClientLoginUrl("https://game.hotel.nl/nitro?tok=1#frag", "th"),
|
||||
).toBe("https://game.hotel.nl/nitro?tok=1&sso=th#frag");
|
||||
});
|
||||
|
||||
it("encodes the ticket value", () => {
|
||||
expect(buildClientLoginUrl("https://game.hotel.nl/", "Ḟancy-ü")).toBe(
|
||||
"https://game.hotel.nl/?sso=%E1%B8%9Eancy-%C3%BC",
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user