fix(auth): revoke captured client sessions safely on logout
This commit is contained in:
@@ -35,7 +35,7 @@ function harness(t, expired = false) {
|
||||
class ApiError extends Error { constructor(status) { super('failed'); this.status = status } }
|
||||
const module = compile('./auth.ts', {
|
||||
vue, pinia, '@/api/session': session,
|
||||
'@/modules/auth/api/auth': { logoutMerchant: async refresh => behavior.logout?.(refresh) },
|
||||
'@/modules/auth/api/auth': { logoutMerchant: async (access, refresh) => behavior.logout?.(refresh, access) },
|
||||
'@/modules/auth/utils/jwt': compile('../utils/jwt.ts'),
|
||||
'@/api/http': { ApiError, refreshAuthenticatedSession: async () => {
|
||||
session.persistTokenPair({ accessToken: token(1, 1, 1, 'refreshed'), refreshToken: 'refresh-new' })
|
||||
@@ -152,3 +152,17 @@ test('store logout clears immediately and late revocation failure preserves a la
|
||||
assert.equal(h.auth.isAuthenticated, true)
|
||||
assert.equal(h.session.getRefreshToken(), 'refresh-b')
|
||||
})
|
||||
|
||||
test('duplicate logout joins captured pair revocation and does not send again',async t=>{
|
||||
const h=harness(t);const remote=deferred();let count=0,sent
|
||||
h.behavior.logout=(refresh,access)=>{count++;sent={refresh,access};return remote.promise}
|
||||
const a=h.auth.logout(),b=h.auth.logout();assert.equal(h.auth.isAuthenticated,false);assert.equal(sent.access,token());assert.equal(sent.refresh,'refresh-a');assert.equal(count,1);remote.resolve();await Promise.all([a,b])
|
||||
})
|
||||
|
||||
test('B logout during A pending revokes B; A finally cannot release B deduplication',async t=>{
|
||||
const h=harness(t);const a=deferred(),b=deferred(),calls=[]
|
||||
h.behavior.logout=(refresh,access)=>{calls.push({refresh,access});return calls.length===1?a.promise:b.promise}
|
||||
const leavingA=h.auth.logout();h.rotate(token(2,2,2));await flush();assert.equal(h.auth.isAuthenticated,true)
|
||||
const leavingB=h.auth.logout();assert.equal(h.auth.isAuthenticated,false);assert.equal(h.session.getAccessToken(),'');assert.equal(calls.length,2);assert.equal(calls[1].access,token(2,2,2))
|
||||
a.resolve();await leavingA;const duplicateB=h.auth.logout();assert.equal(calls.length,2);let duplicateFinished=false;void duplicateB.then(()=>{duplicateFinished=true});await flush();assert.equal(duplicateFinished,false);b.resolve();await Promise.all([leavingB,duplicateB])
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user