mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-07-24 10:11:44 +00:00
When /auth/refresh rotates the refresh token, the previous token is kept valid for a short grace period so a client that never received the rotation response (e.g. a dropped or suspended mobile request) can retry with the old token and get back the already-rotated current token instead of a 401. That window was hardcoded to 60 seconds, which is too short for real mobile conditions: iOS backgrounding, VPN/proxy timeouts, or network handoff can delay the retry past a minute, permanently locking the session out (#5281). Make it configurable via REFRESH_TOKEN_GRACE_PERIOD (seconds), following the existing REFRESH_TOKEN_EXPIRY / ACCESS_TOKEN_EXPIRY pattern, and raise the default to 10 minutes. Adds unit tests for the new config. Fixes #5281
52 lines
2 KiB
JavaScript
52 lines
2 KiB
JavaScript
const chai = require('chai')
|
|
const sinon = require('sinon')
|
|
const { expect } = chai
|
|
|
|
// Require Database before TokenManager to resolve the Database -> Auth -> TokenManager
|
|
// require cycle (otherwise requiring TokenManager first yields an incomplete export).
|
|
require('../../../server/Database')
|
|
const Logger = require('../../../server/Logger')
|
|
const TokenManager = require('../../../server/auth/TokenManager')
|
|
|
|
describe('TokenManager', () => {
|
|
describe('refresh token grace period configuration', () => {
|
|
let loggerInfoStub
|
|
const originalEnv = process.env.REFRESH_TOKEN_GRACE_PERIOD
|
|
|
|
beforeEach(() => {
|
|
loggerInfoStub = sinon.stub(Logger, 'info')
|
|
delete process.env.REFRESH_TOKEN_GRACE_PERIOD
|
|
})
|
|
|
|
afterEach(() => {
|
|
loggerInfoStub.restore()
|
|
if (originalEnv === undefined) delete process.env.REFRESH_TOKEN_GRACE_PERIOD
|
|
else process.env.REFRESH_TOKEN_GRACE_PERIOD = originalEnv
|
|
})
|
|
|
|
it('defaults to 10 minutes (600 seconds) when the env var is not set', () => {
|
|
const tokenManager = new TokenManager()
|
|
expect(tokenManager.RefreshTokenGracePeriod).to.equal(600)
|
|
})
|
|
|
|
it('reads a positive value from REFRESH_TOKEN_GRACE_PERIOD (in seconds)', () => {
|
|
process.env.REFRESH_TOKEN_GRACE_PERIOD = '300'
|
|
const tokenManager = new TokenManager()
|
|
expect(tokenManager.RefreshTokenGracePeriod).to.equal(300)
|
|
expect(loggerInfoStub.calledWithMatch(/grace period set from ENV/i)).to.equal(true)
|
|
})
|
|
|
|
it('falls back to the default for a non-positive or invalid value', () => {
|
|
process.env.REFRESH_TOKEN_GRACE_PERIOD = '0'
|
|
expect(new TokenManager().RefreshTokenGracePeriod).to.equal(600)
|
|
|
|
process.env.REFRESH_TOKEN_GRACE_PERIOD = 'not-a-number'
|
|
expect(new TokenManager().RefreshTokenGracePeriod).to.equal(600)
|
|
})
|
|
|
|
it('does not log the ENV override message when the env var is unset', () => {
|
|
new TokenManager()
|
|
expect(loggerInfoStub.calledWithMatch(/grace period set from ENV/i)).to.equal(false)
|
|
})
|
|
})
|
|
})
|