Skip to content

Commit f930998

Browse files
authored
fix: v4 Signing Errors with exactly 7 day expiry (#2170)
* fix: if expiry date object has >= 500 ms then a rounding error occurs and is thrown. added tests to replicate. * fix: typo * fix: smplifiy the unittest
1 parent 130818d commit f930998

File tree

3 files changed

+53
-4
lines changed

3 files changed

+53
-4
lines changed

src/signer.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -416,7 +416,7 @@ export class URLSigner {
416416
throw new Error(ExceptionMessages.EXPIRATION_DATE_PAST);
417417
}
418418

419-
return Math.round(expiresInMSeconds / 1000); // The API expects seconds.
419+
return Math.floor(expiresInMSeconds / 1000); // The API expects seconds.
420420
}
421421

422422
parseAccessibleAt(accessibleAt?: string | number | Date): number {

system-test/storage.ts

+25
Original file line numberDiff line numberDiff line change
@@ -3290,6 +3290,31 @@ describe('storage', () => {
32903290
assert.strictEqual(body, localFile.toString());
32913291
});
32923292

3293+
it('should not throw with expiration of exactly 7 days', async () => {
3294+
const ACCESSIBLE_AT = new Date().setMilliseconds(999).valueOf();
3295+
const SEVEN_DAYS_IN_SECONDS = 7 * 24 * 60 * 60;
3296+
const SEVEN_DAYS_IN_MS = SEVEN_DAYS_IN_SECONDS * 1000;
3297+
await assert.doesNotReject(
3298+
async () => {
3299+
await file.getSignedUrl({
3300+
version: 'v4',
3301+
action: 'read',
3302+
accessibleAt: ACCESSIBLE_AT,
3303+
expires: ACCESSIBLE_AT + SEVEN_DAYS_IN_MS,
3304+
virtualHostedStyle: true,
3305+
});
3306+
},
3307+
err => {
3308+
assert(err instanceof Error);
3309+
assert.strictEqual(
3310+
err.message,
3311+
`Max allowed expiration is seven days (${SEVEN_DAYS_IN_SECONDS} seconds).`
3312+
);
3313+
return true;
3314+
}
3315+
);
3316+
});
3317+
32933318
it('should create a signed read url with accessibleAt in the past', async () => {
32943319
const [signedReadUrl] = await file.getSignedUrl({
32953320
version: 'v4',

test/signer.ts

+27-3
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ describe('signer', () => {
5656
let bucket: BucketI;
5757
let file: FileI;
5858

59-
const NOW = new Date('2019-03-18T00:00:00Z');
59+
const NOW = new Date('2019-03-18T00:00:00.999Z');
6060
let fakeTimers: sinon.SinonFakeTimers;
6161

6262
beforeEach(() => (fakeTimers = sinon.useFakeTimers(NOW)));
@@ -554,7 +554,7 @@ describe('signer', () => {
554554
signer = new URLSigner(authClient, bucket, file);
555555
CONFIG = {
556556
method: 'GET',
557-
expiration: Math.floor((NOW.valueOf() + 2000) / 1000),
557+
expiration: (NOW.valueOf() + 2000) / 1000,
558558
bucket: bucket.name,
559559
};
560560
});
@@ -573,6 +573,30 @@ describe('signer', () => {
573573
);
574574
});
575575

576+
it('should not throw with expiration of exactly 7 days', async () => {
577+
const ACCESSIBLE_AT = NOW.valueOf();
578+
const SEVEN_DAYS_IN_SECONDS = 7 * 24 * 60 * 60;
579+
const SEVEN_DAYS_IN_MS = SEVEN_DAYS_IN_SECONDS * 1000;
580+
await assert.doesNotReject(
581+
async () => {
582+
await signer.getSignedUrl({
583+
method: 'GET',
584+
expires: ACCESSIBLE_AT + SEVEN_DAYS_IN_MS,
585+
accessibleAt: ACCESSIBLE_AT,
586+
version: 'v4',
587+
});
588+
},
589+
err => {
590+
assert(err instanceof Error);
591+
assert.strictEqual(
592+
err.message,
593+
`Max allowed expiration is seven days (${SEVEN_DAYS_IN_SECONDS} seconds).`
594+
);
595+
return true;
596+
}
597+
);
598+
});
599+
576600
describe('headers', () => {
577601
it('should add path-styled host header', async () => {
578602
const getCanonicalHeaders = sandbox
@@ -988,7 +1012,7 @@ describe('signer', () => {
9881012

9891013
it('returns expiration date in seconds', () => {
9901014
const expires = signer.parseExpires(NOW);
991-
assert.strictEqual(expires, Math.round(NOW.valueOf() / 1000));
1015+
assert.strictEqual(expires, Math.floor(NOW.valueOf() / 1000));
9921016
});
9931017
});
9941018
});

0 commit comments

Comments
 (0)