Skip to content

Commit

Permalink
🐛 Debias clock leeway on auth tokens (#150)
Browse files Browse the repository at this point in the history
Previously, we added 2 hours of leeway to the expiration. This is resulting in a significant percentage of our requests failing due to `jwt.exceptions.ImmatureSignatureError: The token is not yet valid (iat)`. This change adjusts the values to be an hour in the past or future, hopefully reducing the incidence of this error.
  • Loading branch information
dmihalcik-virtru authored Feb 16, 2023
1 parent 7aefd8f commit 4edfee3
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 37 deletions.
20 changes: 15 additions & 5 deletions lib/src/auth/auth.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { JWTPayload, SignJWT } from 'jose';
import { type JWTHeaderParameters, type JWTPayload, type KeyLike, SignJWT } from 'jose';

export type Method =
| 'GET'
Expand Down Expand Up @@ -48,17 +48,27 @@ export function withHeaders(httpReq: HttpRequest, newHeaders: Record<string, str
return { ...httpReq, headers };
}

function getTimestampInSeconds() {
return Math.floor(Date.now() / 1000);
}

/**
* Generate a JWT (or JWS-ed object)
* @param toSign the data to sign. Interpreted as JWTPayload but AFAIK this isn't required
* @param privateKey an RSA key
* @returns the signed object, with a JWS header. This may be a JWT.
*/
export async function reqSignature(toSign: unknown, privateKey: CryptoKey) {
export async function reqSignature(
toSign: unknown,
privateKey: KeyLike,
jwtProtectedHeader: JWTHeaderParameters = { alg: 'RS256' }
) {
const now = getTimestampInSeconds();
const anHour = 3600;
return new SignJWT(toSign as JWTPayload)
.setProtectedHeader({ alg: 'RS256' })
.setIssuedAt()
.setExpirationTime('2h')
.setProtectedHeader(jwtProtectedHeader)
.setIssuedAt(now - anHour)
.setExpirationTime(now + anHour)
.sign(privateKey);
}

Expand Down
22 changes: 0 additions & 22 deletions lib/src/nanotdf-crypto/authToken.ts

This file was deleted.

1 change: 0 additions & 1 deletion lib/src/nanotdf-crypto/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export { Ciphers } from './ciphers.js';
export { default as authToken } from './authToken.js';
export { default as cryptoPublicToPem } from './cryptoPublicToPem.js';
export { default as decrypt } from './decrypt.js';
export { default as digest } from './digest.js';
Expand Down
7 changes: 4 additions & 3 deletions lib/src/nanotdf/Client.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type { TypedArray } from '../tdf/index.js';
import * as base64 from '../encodings/base64.js';
import {
authToken,
cryptoPublicToPem,
decrypt,
enums as cryptoEnums,
Expand All @@ -13,7 +12,7 @@ import {
import getHkdfSalt from './helpers/getHkdfSalt.js';
import DefaultParams from './models/DefaultParams.js';
import { fetchWrappedKey } from '../kas.js';
import { AuthProvider } from '../auth/providers.js';
import { AuthProvider, reqSignature } from '../auth/providers.js';

const { KeyUsageType, AlgorithmName, NamedCurve } = cryptoEnums;

Expand Down Expand Up @@ -214,7 +213,9 @@ export default class Client {

const jwtPayload = { requestBody: requestBodyStr };
const requestBody = {
signedRequestToken: await authToken(this.requestSignerKeyPair.privateKey, jwtPayload),
signedRequestToken: await reqSignature(jwtPayload, this.requestSignerKeyPair.privateKey, {
alg: AlgorithmName.ES256,
}),
};

// Wrapped
Expand Down
8 changes: 2 additions & 6 deletions lib/tdf3/src/tdf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { EventEmitter } from 'events';
import axios from 'axios';
import crc32 from 'buffer-crc32';
import { v4 } from 'uuid';
import { exportSPKI, importPKCS8, importX509, SignJWT } from 'jose';
import { exportSPKI, importPKCS8, importX509 } from 'jose';
import { AnyTdfStream, makeStream } from './client/tdf-stream.js';
import { EntityObject } from '../../src/tdf/EntityObject.js';

Expand Down Expand Up @@ -809,11 +809,7 @@ class TDF extends EventEmitter {

const jwtPayload = { requestBody: requestBodyStr };
const pkKeyLike = await importPKCS8(this.privateKey, 'RS256');
const signedRequestToken = await new SignJWT(isAppIdProvider ? {} : jwtPayload)
.setProtectedHeader({ alg: 'RS256' })
.setIssuedAt()
.setExpirationTime('2h')
.sign(pkKeyLike);
const signedRequestToken = await reqSignature(isAppIdProvider ? {} : jwtPayload, pkKeyLike);

let requestBody;
if (isAppIdProvider) {
Expand Down

0 comments on commit 4edfee3

Please sign in to comment.