From bd584902e0ea0cfd5ba9b85369252bbe4783db99 Mon Sep 17 00:00:00 2001 From: Eli Bosley Date: Mon, 20 Jan 2025 13:54:47 -0500 Subject: [PATCH] feat: use state passing to validate requests --- web/components/SsoButton.ce.vue | 34 +++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/web/components/SsoButton.ce.vue b/web/components/SsoButton.ce.vue index c5508964e..d1a10f2e1 100644 --- a/web/components/SsoButton.ce.vue +++ b/web/components/SsoButton.ce.vue @@ -24,31 +24,41 @@ const enterCallbackTokenIntoField = (token: string) => { } }; -const search = new URLSearchParams(window.location.search); -const token = search.get('token') ?? ''; -if (token) { - enterCallbackTokenIntoField(token); - // Clear the token from the URL - window.history.replaceState({}, document.title, window.location.pathname); - window.location.search = ''; -} +const getStateToken = (): string | null => { + const state = sessionStorage.getItem('sso_state'); + return state ?? null; +}; -watch(queryParams, (newVal) => { - if (newVal?.token) { - enterCallbackTokenIntoField(newVal.token); +const generateStateToken = (): string => { + const state = + Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15); + sessionStorage.setItem('sso_state', state); + return state; +}; + +onMounted(() => { + const search = new URLSearchParams(window.location.search); + const token = search.get('token') ?? ''; + const state = search.get('state') ?? ''; + const sessionState = getStateToken(); + if (token && state === sessionState) { + enterCallbackTokenIntoField(token); // Clear the token from the URL window.history.replaceState({}, document.title, window.location.pathname); window.location.search = ''; } }); -const externalSSOUrl = computed(() => { +const externalSSOUrl = computed(() => { if (props.subids === undefined) { return ''; } const url = new URL('sso', ACCOUNT); url.searchParams.append('uids', props.subids); const callbackUrlLogin = new URL('login', window.location.origin); + const state = generateStateToken(); + callbackUrlLogin.searchParams.append('state', state); + url.searchParams.append('serverUrl', callbackUrlLogin.toString()); return url.toString(); });