fix(auth): не отдавать SSO с просроченным JWT и не бить /me
Build and Push Auth Portal Docker Image / build-and-push (push) Successful in 1m38s
Build and Push Auth Portal Docker Image / create-release (push) Skipped

getToken чистит expired; при плохом return_to остаёмся на login без /me.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Denozordec
2026-07-18 16:08:50 +07:00
co-authored by Cursor
parent e2c45cf0fa
commit c23eb5ead0
4 changed files with 32 additions and 1 deletions
+20
View File
@@ -187,6 +187,26 @@ function isPrivateHostname(hostname: string): boolean {
return false
}
/** Decode JWT `exp` without verifying signature. Returns null if missing/invalid. */
export function readJwtExp(token: string): number | null {
try {
const parts = token.split('.')
if (parts.length < 2) return null
const json = atob(parts[1]!.replace(/-/g, '+').replace(/_/g, '/'))
const payload = JSON.parse(json) as { exp?: unknown }
return typeof payload.exp === 'number' ? payload.exp : null
} catch {
return null
}
}
/** True when token is missing exp or exp is in the past (30s clock-skew grace). */
export function isJwtExpired(token: string, nowMs: number = Date.now()): boolean {
const exp = readJwtExp(token)
if (exp == null) return true
return exp * 1000 < nowMs - 30_000
}
export function buildSsoRedirectUrl(
returnTo: string,
accessToken: string,