Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 37 additions & 17 deletions frontend-new/src/auth/services/Authentication.service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -480,35 +480,55 @@ describe("AuthenticationService", () => {
expect(console.warn).not.toHaveBeenCalled();
});

test.each([
[
"expired token",
{ iat: currentTime - CLOCK_TOLERANCE - 100, exp: currentTime - CLOCK_TOLERANCE - 1 },
"TOKEN_EXPIRED",
],
[
"future token",
{ iat: currentTime + CLOCK_TOLERANCE + 1, exp: currentTime + CLOCK_TOLERANCE + 100 },
"TOKEN_NOT_YET_VALID",
],
])("should return false for %s", (_, payload, expectedFailureCause) => {
// GIVEN a token with invalid timing
const givenToken = "invalid-token";
test("should return false for expired token", () => {
// GIVEN an expired token
const givenToken = "expired-token";
(jwtDecode as jest.Mock)
.mockReturnValueOnce({
typ: "JWT",
alg: "RS256",
kid: "key-id",
} as TokenHeader)
.mockReturnValueOnce(payload as Token);
.mockReturnValueOnce({
iat: currentTime - CLOCK_TOLERANCE - 100,
exp: currentTime - CLOCK_TOLERANCE - 1,
} as Token);

// WHEN isTokenValid is called
const result = service.isTokenValid(givenToken);

// THEN it should return false
// THEN it should return false with TOKEN_EXPIRED
expect(result.isValid).toBe(false);
expect(result.decodedToken).toBeNull();
expect(result.failureCause).toBe(expectedFailureCause);
expect(result.failureCause).toBe(TokenValidationFailureCause.TOKEN_EXPIRED);

// AND expect no errors or warning to have occurred
expect(console.error).not.toHaveBeenCalled();
expect(console.warn).not.toHaveBeenCalled();
});

test("should return true when iat is in the future due to client clock skew", () => {
// GIVEN a token where the server clock is ahead of the client (iat appears to be in the future)
// but the token has not yet expired
const givenToken = "clock-skewed-token";
(jwtDecode as jest.Mock)
.mockReturnValueOnce({
typ: "JWT",
alg: "RS256",
kid: "key-id",
} as TokenHeader)
.mockReturnValueOnce({
iat: currentTime + CLOCK_TOLERANCE + 1,
exp: currentTime + CLOCK_TOLERANCE + 100,
} as Token);

// WHEN isTokenValid is called
const result = service.isTokenValid(givenToken);

// THEN it should return true — iat is not checked client-side
expect(result.isValid).toBe(true);
expect(result.decodedToken).toBeDefined();
expect(result.failureCause).toBeUndefined();

// AND expect no errors or warning to have occurred
expect(console.error).not.toHaveBeenCalled();
Expand Down
15 changes: 0 additions & 15 deletions frontend-new/src/auth/services/Authentication.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export const CLOCK_TOLERANCE = 10; // 10 second buffer for expiration and issuan

export enum TokenValidationFailureCause {
TOKEN_EXPIRED = "TOKEN_EXPIRED",
TOKEN_NOT_YET_VALID = "TOKEN_NOT_YET_VALID",
TOKEN_NOT_A_JWT = "TOKEN_NOT_A_JWT",
TOKEN_NOT_SIGNED = "TOKEN_NOT_SIGNED",
TOKEN_DOES_NOT_HAVE_A_KEY_ID = "TOKEN_DOES_NOT_HAVE_A_KEY_ID",
Expand Down Expand Up @@ -218,20 +217,6 @@ abstract class AuthenticationService {
);
}

// Check issued time with buffer
// similarly, we add a buffer to the issuance time to account for the potential time difference between the server and client clocks
if (currentTime < decodedToken.iat - CLOCK_TOLERANCE) {
console.debug("Token issued in the future: ", { iat: decodedToken.iat, currentTime });
return { isValid: false, decodedToken: null, failureCause: TokenValidationFailureCause.TOKEN_NOT_YET_VALID };
} else if (currentTime < decodedToken.iat) {
console.warn(
"Warning: token issued at time was after the current time, but within the acceptable tolerance period ",
{
iat: decodedToken.iat,
currentTime,
}
);
}
return { isValid: true, decodedToken: decodedToken };
} catch (error) {
return { isValid: false, decodedToken: null, failureCause: TokenValidationFailureCause.ERROR_DECODING_TOKEN };
Expand Down