fix(desktop): token validation and cookie parsing (#5569)
This fixes desktop app auth failures where users encounter "Session expired" errors when creating environments or saving requests despite being logged in. The issue occurred because token verify/validation works on web (cookie-based auth) but fails on desktop (bearer token auth). The desktop implementation had flaky response parsing in `verifyAuthTokens()`. Includes some future proofing work around cookie parsing in `setAuthCookies()`, for Set-Cookie headers contain commas or are concatenated with newlines (see #5394).
This commit is contained in:
parent
f8cb75895f
commit
eee92bbeeb
2 changed files with 14 additions and 20 deletions
|
|
@ -143,8 +143,6 @@ declare module 'vue' {
|
||||||
HoppSmartProgressRing: typeof import('@hoppscotch/ui')['HoppSmartProgressRing']
|
HoppSmartProgressRing: typeof import('@hoppscotch/ui')['HoppSmartProgressRing']
|
||||||
HoppSmartRadio: typeof import('@hoppscotch/ui')['HoppSmartRadio']
|
HoppSmartRadio: typeof import('@hoppscotch/ui')['HoppSmartRadio']
|
||||||
HoppSmartRadioGroup: typeof import('@hoppscotch/ui')['HoppSmartRadioGroup']
|
HoppSmartRadioGroup: typeof import('@hoppscotch/ui')['HoppSmartRadioGroup']
|
||||||
HoppSmartSelect: typeof import('@hoppscotch/ui')['HoppSmartSelect']
|
|
||||||
HoppSmartSelectOption: typeof import('@hoppscotch/ui')['HoppSmartSelectOption']
|
|
||||||
HoppSmartSelectWrapper: typeof import('@hoppscotch/ui')['HoppSmartSelectWrapper']
|
HoppSmartSelectWrapper: typeof import('@hoppscotch/ui')['HoppSmartSelectWrapper']
|
||||||
HoppSmartSlideOver: typeof import('@hoppscotch/ui')['HoppSmartSlideOver']
|
HoppSmartSlideOver: typeof import('@hoppscotch/ui')['HoppSmartSlideOver']
|
||||||
HoppSmartSpinner: typeof import('@hoppscotch/ui')['HoppSmartSpinner']
|
HoppSmartSpinner: typeof import('@hoppscotch/ui')['HoppSmartSpinner']
|
||||||
|
|
@ -214,11 +212,9 @@ declare module 'vue' {
|
||||||
IconLucideArrowLeft: typeof import('~icons/lucide/arrow-left')['default']
|
IconLucideArrowLeft: typeof import('~icons/lucide/arrow-left')['default']
|
||||||
IconLucideArrowUpRight: typeof import('~icons/lucide/arrow-up-right')['default']
|
IconLucideArrowUpRight: typeof import('~icons/lucide/arrow-up-right')['default']
|
||||||
IconLucideBrush: typeof import('~icons/lucide/brush')['default']
|
IconLucideBrush: typeof import('~icons/lucide/brush')['default']
|
||||||
IconLucideCheck: typeof import('~icons/lucide/check')['default']
|
|
||||||
IconLucideCheckCircle: typeof import('~icons/lucide/check-circle')['default']
|
IconLucideCheckCircle: typeof import('~icons/lucide/check-circle')['default']
|
||||||
IconLucideChevronRight: typeof import('~icons/lucide/chevron-right')['default']
|
IconLucideChevronRight: typeof import('~icons/lucide/chevron-right')['default']
|
||||||
IconLucideCircleCheck: typeof import('~icons/lucide/circle-check')['default']
|
IconLucideCircleCheck: typeof import('~icons/lucide/circle-check')['default']
|
||||||
IconLucideCopy: typeof import('~icons/lucide/copy')['default']
|
|
||||||
IconLucideGlobe: typeof import('~icons/lucide/globe')['default']
|
IconLucideGlobe: typeof import('~icons/lucide/globe')['default']
|
||||||
IconLucideHelpCircle: typeof import('~icons/lucide/help-circle')['default']
|
IconLucideHelpCircle: typeof import('~icons/lucide/help-circle')['default']
|
||||||
IconLucideInbox: typeof import('~icons/lucide/inbox')['default']
|
IconLucideInbox: typeof import('~icons/lucide/inbox')['default']
|
||||||
|
|
|
||||||
|
|
@ -171,9 +171,6 @@ export async function setInitialUser() {
|
||||||
isGettingInitialUser.value = true
|
isGettingInitialUser.value = true
|
||||||
const res = await getInitialUserDetails()
|
const res = await getInitialUserDetails()
|
||||||
|
|
||||||
// NOTE: This is required for further diagnosis,
|
|
||||||
// to be removed after patch confirmation.
|
|
||||||
console.info("Auth response structure:", JSON.stringify(res, null, 2))
|
|
||||||
if ("error" in res) {
|
if ("error" in res) {
|
||||||
await setUser(null)
|
await setUser(null)
|
||||||
isGettingInitialUser.value = false
|
isGettingInitialUser.value = false
|
||||||
|
|
@ -291,19 +288,16 @@ async function sendMagicLink(email: string) {
|
||||||
|
|
||||||
async function setAuthCookies(headers: Headers) {
|
async function setAuthCookies(headers: Headers) {
|
||||||
const cookieHeader = headers.get("set-cookie")
|
const cookieHeader = headers.get("set-cookie")
|
||||||
const cookies = cookieHeader ? cookieHeader.split(",") : []
|
if (!cookieHeader) return
|
||||||
|
|
||||||
const accessTokenMatch = cookies.join(",").match(/access_token=([^;]+)/)
|
const accessTMatch = cookieHeader.match(/access_token=([^;,\s]+)/)
|
||||||
const refreshTokenMatch = cookies.join(",").match(/refresh_token=([^;]+)/)
|
const refreshTMatch = cookieHeader.match(/refresh_token=([^;,\s]+)/)
|
||||||
|
|
||||||
if (accessTokenMatch) {
|
if (accessTMatch) {
|
||||||
const accessToken = accessTokenMatch[1]
|
await persistenceService.setLocalConfig("access_token", accessTMatch[1])
|
||||||
await persistenceService.setLocalConfig("access_token", accessToken)
|
|
||||||
}
|
}
|
||||||
|
if (refreshTMatch) {
|
||||||
if (refreshTokenMatch) {
|
await persistenceService.setLocalConfig("refresh_token", refreshTMatch[1])
|
||||||
const refreshToken = refreshTokenMatch[1]
|
|
||||||
await persistenceService.setLocalConfig("refresh_token", refreshToken)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -551,10 +545,14 @@ export const def: AuthPlatformDef = {
|
||||||
})
|
})
|
||||||
|
|
||||||
const res = await response
|
const res = await response
|
||||||
if (E.isLeft(res)) {
|
if (E.isLeft(res)) return false
|
||||||
return false
|
|
||||||
|
const parsed = parseBodyAsJSON<{ isValid: boolean }>(res.right.body)
|
||||||
|
if (parsed._tag === "Some" && parsed.value.isValid) {
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.right.isValid
|
const refreshed = await refreshToken()
|
||||||
|
return refreshed ?? false
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue