Return 401 status code for expired tokens (#12281)

* Refresh token when it's expired & retry request

* move refresh token interceptor in autoRefresh flag

* add TOKEN_EXPIRED exception

* update interceptor condition & fix autoRefreshJob

* update docs

* revert auth drivers changes

* remove unused imports

* undo sdk auth refresh changes
This commit is contained in:
Azri Kahar
2022-04-04 21:23:28 +08:00
committed by GitHub
parent 4cb8e8f0ca
commit d0b0818cca
5 changed files with 18 additions and 4 deletions

View File

@@ -13,6 +13,7 @@ export * from './method-not-allowed';
export * from './range-not-satisfiable';
export * from './route-not-found';
export * from './service-unavailable';
export * from './token-expired';
export * from './unprocessable-entity';
export * from './unsupported-media-type';
export * from './user-suspended';

View File

@@ -0,0 +1,7 @@
import { BaseException } from '@directus/shared/exceptions';
export class TokenExpiredException extends BaseException {
constructor(message = 'Token expired.') {
super(message, 401, 'TOKEN_EXPIRED');
}
}

View File

@@ -1,6 +1,6 @@
import jwt, { JsonWebTokenError, TokenExpiredError } from 'jsonwebtoken';
import { DirectusTokenPayload } from '../types';
import { InvalidTokenException, ServiceUnavailableException } from '../exceptions';
import { InvalidTokenException, ServiceUnavailableException, TokenExpiredException } from '../exceptions';
export function verifyAccessJWT(token: string, secret: string): DirectusTokenPayload {
let payload;
@@ -11,7 +11,7 @@ export function verifyAccessJWT(token: string, secret: string): DirectusTokenPay
}) as Record<string, any>;
} catch (err) {
if (err instanceof TokenExpiredError) {
throw new InvalidTokenException('Token expired.');
throw new TokenExpiredException();
} else if (err instanceof JsonWebTokenError) {
throw new InvalidTokenException('Token invalid.');
} else {

View File

@@ -1,6 +1,6 @@
import { verifyAccessJWT } from '../../src/utils/jwt';
import jwt from 'jsonwebtoken';
import { InvalidTokenException, ServiceUnavailableException } from '../../src/exceptions';
import { InvalidTokenException, ServiceUnavailableException, TokenExpiredException } from '../../src/exceptions';
import { DirectusTokenPayload } from '../../src/types';
const payload: DirectusTokenPayload = { role: null, app_access: false, admin_access: false };
@@ -13,10 +13,14 @@ test('Returns the payload of a correctly signed token', () => {
expect(result).toEqual(payload);
});
test('Throws TokenExpiredException when token used has expired', () => {
const token = jwt.sign({ ...payload, exp: new Date().getTime() / 1000 - 500 }, secret, options);
expect(() => verifyAccessJWT(token, secret)).toThrow(TokenExpiredException);
});
const InvalidTokenCases = {
'wrong issuer': jwt.sign(payload, secret, { issuer: 'wrong' }),
'wrong secret': jwt.sign(payload, 'wrong-secret', options),
expired: jwt.sign({ ...payload, exp: new Date().getTime() / 1000 - 500 }, secret, options),
'string payload': jwt.sign('illegal payload', secret),
'missing properties in token payload': jwt.sign({ role: null }, secret, options),
};