Skip to content

Commit d23b1c5

Browse files
fix: Update jsonwebtoken to v9.0.0 (#2025)
* fix: Update jsonwebtoken to v9.0.0 * Fix emulator based integration tests
1 parent 1acdb67 commit d23b1c5

File tree

10 files changed

+46
-79
lines changed

10 files changed

+46
-79
lines changed

package-lock.json

+12-50
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@
200200
"@firebase/database-compat": "^0.2.6",
201201
"@firebase/database-types": "^0.9.13",
202202
"@types/node": ">=12.12.47",
203-
"jsonwebtoken": "^8.5.1",
203+
"jsonwebtoken": "^9.0.0",
204204
"jwks-rsa": "^2.1.4",
205205
"node-forge": "^1.3.1",
206206
"uuid": "^9.0.0"

src/utils/jwt.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ export class PublicKeySignatureVerifier implements SignatureVerifier {
244244
export class EmulatorSignatureVerifier implements SignatureVerifier {
245245
public verify(token: string): Promise<void> {
246246
// Signature checks skipped for emulator; no need to fetch public keys.
247-
return verifyJwtSignature(token, '');
247+
return verifyJwtSignature(token, undefined as any, { algorithms:['none'] });
248248
}
249249
}
250250

test/integration/auth.spec.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -1065,12 +1065,14 @@ describe('admin.auth', () => {
10651065
audience: projectId,
10661066
issuer: 'https://securetoken.google.com/' + projectId,
10671067
subject: uid,
1068-
});
1068+
}, undefined, 'secret');
10691069
return getAuth().verifyIdToken(unsignedToken);
10701070
});
10711071

10721072
it('verifyIdToken() fails when called with a token with wrong project', () => {
1073-
const unsignedToken = mocks.generateIdToken({ algorithm: 'none', audience: 'nosuch' });
1073+
const unsignedToken = mocks.generateIdToken(
1074+
{ algorithm: 'none', audience: 'nosuch' },
1075+
undefined, 'secret');
10741076
return getAuth().verifyIdToken(unsignedToken)
10751077
.should.eventually.be.rejected.and.have.property('code', 'auth/argument-error');
10761078
});
@@ -1081,7 +1083,7 @@ describe('admin.auth', () => {
10811083
audience: projectId,
10821084
issuer: 'https://securetoken.google.com/' + projectId,
10831085
subject: 'nosuch',
1084-
});
1086+
}, undefined, 'secret');
10851087
return getAuth().verifyIdToken(unsignedToken)
10861088
.should.eventually.be.rejected.and.have.property('code', 'auth/user-not-found');
10871089
});

test/resources/mocks.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -206,9 +206,10 @@ export const jwksKeyPair = {
206206
*
207207
* @param {object} overrides Overrides for the generated token's attributes.
208208
* @param {object} claims Extra claims to add to the token.
209+
* @param {string} secret Custom key to sign the token with.
209210
* @return {string} A mocked Firebase ID token with any provided overrides included.
210211
*/
211-
export function generateIdToken(overrides?: object, claims?: object): string {
212+
export function generateIdToken(overrides?: object, claims?: object, secret?: string): string {
212213
const options = _.assign({
213214
audience: projectId,
214215
expiresIn: ONE_HOUR_IN_SECONDS,
@@ -225,17 +226,18 @@ export function generateIdToken(overrides?: object, claims?: object): string {
225226
...claims,
226227
};
227228

228-
return jwt.sign(payload, certificateObject.private_key, options);
229+
return jwt.sign(payload, secret ?? certificateObject.private_key, options);
229230
}
230231

231232
/**
232233
* Generates a mocked Auth Blocking token.
233234
*
234235
* @param overrides Overrides for the generated token's attributes.
235236
* @param claims Extra claims to add to the token.
237+
* @param {string} secret Custom key to sign the token with.
236238
* @return A mocked Auth Blocking token with any provided overrides included.
237239
*/
238-
export function generateAuthBlockingToken(overrides?: object, claims?: object): string {
240+
export function generateAuthBlockingToken(overrides?: object, claims?: object, secret?: string): string {
239241
const options = _.assign({
240242
audience: `https://us-central1-${projectId}.cloudfunctions.net/functionName`,
241243
expiresIn: TEN_MINUTES_IN_SECONDS,
@@ -252,7 +254,7 @@ export function generateAuthBlockingToken(overrides?: object, claims?: object):
252254
...claims,
253255
};
254256

255-
return jwt.sign(payload, certificateObject.private_key, options);
257+
return jwt.sign(payload, secret ?? certificateObject.private_key, options);
256258
}
257259

258260
/**

test/unit/app-check/token-verifier.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ describe('AppCheckTokenVerifier', () => {
102102

103103
it('should be rejected given an App Check token with an incorrect algorithm', () => {
104104
const mockAppCheckToken = mocks.generateAppCheckToken({
105-
algorithm: 'HS256',
105+
algorithm: 'PS256',
106106
});
107107
return tokenVerifier.verifyToken(mockAppCheckToken)
108108
.should.eventually.be.rejectedWith('The provided App Check token has incorrect algorithm');

test/unit/auth/auth.spec.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -3895,7 +3895,7 @@ AUTH_CONFIGS.forEach((testConfig) => {
38953895
expect(decoded).to.have.property('payload').that.has.property('uid', 'uid1');
38963896

38973897
// Make sure this doesn't throw
3898-
jwt.verify(token, '', { algorithms: ['none'] });
3898+
jwt.verify(token, undefined as any, { algorithms: ['none'] });
38993899
});
39003900

39013901
it('verifyIdToken() should reject revoked ID tokens', () => {
@@ -3909,10 +3909,11 @@ AUTH_CONFIGS.forEach((testConfig) => {
39093909
const unsignedToken = mocks.generateIdToken({
39103910
algorithm: 'none',
39113911
subject: uid,
3912+
header: {},
39123913
}, {
39133914
iat: oneSecBeforeValidSince,
39143915
auth_time: oneSecBeforeValidSince,
3915-
});
3916+
}, 'secret');
39163917

39173918
// verifyIdToken should force checking revocation in emulator mode,
39183919
// even if checkRevoked=false.
@@ -3942,7 +3943,7 @@ AUTH_CONFIGS.forEach((testConfig) => {
39423943
}, {
39433944
iat: oneSecBeforeValidSince,
39443945
auth_time: oneSecBeforeValidSince,
3945-
});
3946+
}, 'secret');
39463947

39473948
// verifySessionCookie should force checking revocation in emulator
39483949
// mode, even if checkRevoked=false.
@@ -3960,7 +3961,7 @@ AUTH_CONFIGS.forEach((testConfig) => {
39603961
it('verifyIdToken() rejects an unsigned token if auth emulator is unreachable', async () => {
39613962
const unsignedToken = mocks.generateIdToken({
39623963
algorithm: 'none'
3963-
});
3964+
}, undefined, 'secret');
39643965

39653966
const errorMessage = 'Error while making request: connect ECONNREFUSED 127.0.0.1. Error code: ECONNREFUSED';
39663967
const getUserStub = sinon.stub(testConfig.Auth.prototype, 'getUser').rejects(new Error(errorMessage));

test/unit/auth/token-generator.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ describe('FirebaseTokenGenerator', () => {
130130

131131
// Check that verify doesn't throw
132132
// Note: the types for jsonwebtoken are wrong so we have to disguise the 'null'
133-
jwt.verify(token, '', { algorithms: ['none'] });
133+
jwt.verify(token, undefined as any, { algorithms: ['none'] });
134134

135135
// Decode and check all three segments
136136
const { header, payload, signature } = jwt.decode(token, { complete: true }) as { [key: string]: any };

test/unit/auth/token-verifier.spec.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ describe('FirebaseTokenVerifier', () => {
281281

282282
it('should be rejected given a Firebase JWT token with an incorrect algorithm', () => {
283283
const mockIdToken = mocks.generateIdToken({
284-
algorithm: 'HS256',
284+
algorithm: 'PS256',
285285
});
286286
return tokenVerifier.verifyJWT(mockIdToken)
287287
.should.eventually.be.rejectedWith('Firebase ID token has incorrect algorithm');
@@ -494,7 +494,7 @@ describe('FirebaseTokenVerifier', () => {
494494
const mockIdToken = mocks.generateIdToken({
495495
algorithm: 'none',
496496
header: {}
497-
});
497+
}, undefined, 'secret');
498498

499499
const isEmulator = true;
500500
const decoded = await emulatorVerifier.verifyJWT(mockIdToken, isEmulator);
@@ -515,14 +515,14 @@ describe('FirebaseTokenVerifier', () => {
515515

516516
const idTokenNoAlg = mocks.generateIdToken({
517517
algorithm: 'none',
518-
});
518+
}, undefined, 'secret');
519519
await tokenVerifier.verifyJWT(idTokenNoAlg)
520520
.should.eventually.be.rejectedWith('Firebase ID token has incorrect algorithm.');
521521

522522
const idTokenNoHeader = mocks.generateIdToken({
523523
algorithm: 'none',
524524
header: {}
525-
});
525+
}, undefined, 'secret');
526526
await tokenVerifier.verifyJWT(idTokenNoHeader)
527527
.should.eventually.be.rejectedWith('Firebase ID token has no "kid" claim.');
528528
});
@@ -589,7 +589,7 @@ describe('FirebaseTokenVerifier', () => {
589589

590590
it('should be rejected given a Auth Blocking JWT token with an incorrect algorithm', () => {
591591
const mockAuthBlockingToken = mocks.generateAuthBlockingToken({
592-
algorithm: 'HS256',
592+
algorithm: 'PS256',
593593
});
594594
return authBlockingTokenVerifier._verifyAuthBlockingToken(mockAuthBlockingToken, false, undefined)
595595
.should.eventually.be.rejectedWith('Firebase Auth Blocking token has incorrect algorithm');
@@ -748,7 +748,7 @@ describe('FirebaseTokenVerifier', () => {
748748
const mockAuthBlockingToken = mocks.generateAuthBlockingToken({
749749
algorithm: 'none',
750750
header: {}
751-
});
751+
}, undefined, 'secret');
752752

753753
const isEmulator = true;
754754
const decoded = await emulatorVerifier._verifyAuthBlockingToken(mockAuthBlockingToken, isEmulator, undefined);
@@ -769,14 +769,14 @@ describe('FirebaseTokenVerifier', () => {
769769

770770
const idTokenNoAlg = mocks.generateAuthBlockingToken({
771771
algorithm: 'none',
772-
});
772+
}, undefined, 'secret');
773773
await authBlockingTokenVerifier._verifyAuthBlockingToken(idTokenNoAlg, false, undefined)
774774
.should.eventually.be.rejectedWith('Firebase Auth Blocking token has incorrect algorithm.');
775775

776776
const idTokenNoHeader = mocks.generateAuthBlockingToken({
777777
algorithm: 'none',
778778
header: {}
779-
});
779+
}, undefined, 'secret');
780780
await authBlockingTokenVerifier._verifyAuthBlockingToken(idTokenNoHeader, false, undefined)
781781
.should.eventually.be.rejectedWith('Firebase Auth Blocking token has no "kid" claim.');
782782
});

test/unit/utils/jwt.spec.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ describe('decodeJwt', () => {
199199
const mockIdToken = mocks.generateIdToken({
200200
algorithm: 'none',
201201
header: {}
202-
});
202+
}, undefined, 'secret');
203203

204204
return decodeJwt(mockIdToken)
205205
.should.eventually.be.fulfilled.and.deep.equal(DECODED_UNSIGNED_TOKEN);
@@ -247,9 +247,9 @@ describe('verifyJwtSignature', () => {
247247
const mockIdToken = mocks.generateIdToken({
248248
algorithm: 'none',
249249
header: {}
250-
});
250+
}, undefined, 'secret');
251251

252-
return verifyJwtSignature(mockIdToken, '')
252+
return verifyJwtSignature(mockIdToken, undefined as any, { algorithms: ['none'] })
253253
.should.eventually.be.fulfilled;
254254
});
255255

@@ -448,7 +448,7 @@ describe('PublicKeySignatureVerifier', () => {
448448
.resolves(VALID_PUBLIC_KEYS_RESPONSE);
449449
stubs.push(keyFetcherStub);
450450
const mockIdToken = mocks.generateIdToken({
451-
algorithm: 'HS256',
451+
algorithm: 'RS384',
452452
});
453453

454454
return verifier.verify(mockIdToken).should.eventually.be
@@ -485,11 +485,11 @@ describe('EmulatorSignatureVerifier', () => {
485485
const emulatorVerifier = new EmulatorSignatureVerifier();
486486

487487
describe('verify', () => {
488-
it('should be fullfilled given a valid unsigned (emulator) token', () => {
488+
it('should be fulfilled given a valid unsigned (emulator) token', () => {
489489
const mockIdToken = mocks.generateIdToken({
490490
algorithm: 'none',
491491
header: {}
492-
});
492+
}, undefined, 'secret');
493493

494494
return emulatorVerifier.verify(mockIdToken).should.eventually.be.fulfilled;
495495
});

0 commit comments

Comments
 (0)