fix(pda): revoke expired sessions before completing logout
This commit is contained in:
+20
-3
@@ -1,8 +1,9 @@
|
||||
import { refresh as refreshRequest } from '@/api/auth.js'
|
||||
import { isAccessTokenExpiring, session, signOut, updateTokenPair } from '@/stores/session.js'
|
||||
import { isAccessTokenExpiring, session, signOut, updateTokenPair, getSessionRevision } from '@/stores/session.js'
|
||||
import { requireOnline } from '@/utils/network.js'
|
||||
|
||||
let refreshPromise = null
|
||||
let refreshRevision = null
|
||||
let redirectingToLogin = false
|
||||
|
||||
function responseCode(response) {
|
||||
@@ -66,14 +67,21 @@ function rawRequest(options, accessToken) {
|
||||
})
|
||||
}
|
||||
|
||||
function requireSameSession(revision) {
|
||||
if (getSessionRevision() !== revision) throw new Error('登录会话已变更,请重新操作')
|
||||
}
|
||||
|
||||
async function refreshAccessToken() {
|
||||
const revision = getSessionRevision()
|
||||
const observedRefreshToken = session.refreshToken
|
||||
if (!observedRefreshToken) return expireSession(null, observedRefreshToken)
|
||||
if (!refreshPromise) {
|
||||
if (!refreshPromise || refreshRevision !== revision) {
|
||||
refreshRevision = revision
|
||||
refreshPromise = (async () => {
|
||||
if (session.refreshToken !== observedRefreshToken && session.token) return session.token
|
||||
try {
|
||||
const tokens = await refreshRequest(observedRefreshToken)
|
||||
requireSameSession(revision)
|
||||
if (session.refreshToken !== observedRefreshToken) {
|
||||
if (session.token) return session.token
|
||||
throw sessionExpiredError()
|
||||
@@ -82,10 +90,14 @@ async function refreshAccessToken() {
|
||||
redirectingToLogin = false
|
||||
return session.token
|
||||
} catch (error) {
|
||||
requireSameSession(revision)
|
||||
if (isUnauthorized(error)) return expireSession(error, observedRefreshToken)
|
||||
throw error
|
||||
}
|
||||
})().finally(() => { refreshPromise = null })
|
||||
})()
|
||||
const pending = refreshPromise
|
||||
const release = () => { if (refreshPromise === pending) { refreshPromise = null; refreshRevision = null } }
|
||||
pending.then(release, release) // Original pending promise still propagates failures to callers.
|
||||
}
|
||||
return refreshPromise
|
||||
}
|
||||
@@ -101,12 +113,17 @@ export function ensureAccessToken() {
|
||||
|
||||
async function runAuthenticated(execute) {
|
||||
requireOnline()
|
||||
const revision = getSessionRevision()
|
||||
let accessToken = await validAccessToken()
|
||||
requireSameSession(revision)
|
||||
let response = await execute(accessToken)
|
||||
requireSameSession(revision)
|
||||
if (!isUnauthorized(response)) return response
|
||||
accessToken = session.token && session.token !== accessToken ? session.token : await refreshAccessToken()
|
||||
requireSameSession(revision)
|
||||
const activeRefreshToken = session.refreshToken
|
||||
response = await execute(accessToken)
|
||||
requireSameSession(revision)
|
||||
if (isUnauthorized(response)) expireSession(response, activeRefreshToken)
|
||||
return response
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user