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.
21 lines
778 B
TypeScript
21 lines
778 B
TypeScript
/**
|
|
* Build the Nitro launch URL with the SSO ticket as the final query param.
|
|
*
|
|
* Any existing `sso` param is removed first (both from the query string and
|
|
* from a `#fragment`), the ticket is appended as the last query param, and a
|
|
* `#fragment` is kept after it so the ticket always reaches the server.
|
|
*/
|
|
export function buildClientLoginUrl(clientUrl: string, ticket: string): string {
|
|
const [pathPart = "", ...fragments] = clientUrl.split("#");
|
|
const fragment = fragments.join("#");
|
|
|
|
const path = pathPart
|
|
.replace(/([?&])sso=[^&#]*/gi, "$1")
|
|
.replace(/([?&])&+/g, "$1")
|
|
.replace(/[?&]$/, "");
|
|
|
|
const sep = path.includes("?") ? "&" : "?";
|
|
const query = `${path}${sep}sso=${encodeURIComponent(ticket)}`;
|
|
return fragment ? `${query}#${fragment}` : query;
|
|
}
|