Skip to content

Commit 2605cf1

Browse files
committed
Enable 'strictFunctionTypes' ts compiler option.
1 parent e6f520a commit 2605cf1

File tree

4 files changed

+28
-14
lines changed

4 files changed

+28
-14
lines changed

src/auth/token-verifier.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {AuthClientErrorCode, FirebaseAuthError, ErrorInfo} from '../utils/error'
1919
import * as validator from '../utils/validator';
2020
import * as jwt from 'jsonwebtoken';
2121
import { HttpClient, HttpRequestConfig, HttpError } from '../utils/api-request';
22+
import { DecodedIdToken } from './auth';
2223

2324
// Audience to use for Firebase Auth Custom tokens
2425
const FIREBASE_AUDIENCE = 'https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit';
@@ -130,10 +131,10 @@ export class FirebaseTokenVerifier {
130131
* Verifies the format and signature of a Firebase Auth JWT token.
131132
*
132133
* @param {string} jwtToken The Firebase Auth JWT token to verify.
133-
* @return {Promise<object>} A promise fulfilled with the decoded claims of the Firebase Auth ID
134+
* @return {Promise<DecodedIdToken>} A promise fulfilled with the decoded claims of the Firebase Auth ID
134135
* token.
135136
*/
136-
public verifyJWT(jwtToken: string): Promise<object> {
137+
public verifyJWT(jwtToken: string): Promise<DecodedIdToken> {
137138
if (!validator.isString(jwtToken)) {
138139
throw new FirebaseAuthError(
139140
AuthClientErrorCode.INVALID_ARGUMENT,
@@ -224,16 +225,16 @@ export class FirebaseTokenVerifier {
224225
* Verifies the JWT signature using the provided public key.
225226
* @param {string} jwtToken The JWT token to verify.
226227
* @param {string} publicKey The public key certificate.
227-
* @return {Promise<object>} A promise that resolves with the decoded JWT claims on successful
228+
* @return {Promise<DecodedIdToken>} A promise that resolves with the decoded JWT claims on successful
228229
* verification.
229230
*/
230-
private verifyJwtSignatureWithKey(jwtToken: string, publicKey: string): Promise<object> {
231+
private verifyJwtSignatureWithKey(jwtToken: string, publicKey: string): Promise<DecodedIdToken> {
231232
const verifyJwtTokenDocsMessage = ` See ${this.tokenInfo.url} ` +
232233
`for details on how to retrieve ${this.shortNameArticle} ${this.tokenInfo.shortName}.`;
233234
return new Promise((resolve, reject) => {
234235
jwt.verify(jwtToken, publicKey, {
235236
algorithms: [this.algorithm],
236-
}, (error: jwt.VerifyErrors, decodedToken: any) => {
237+
}, (error: jwt.VerifyErrors, decodedToken: string | object) => {
237238
if (error) {
238239
if (error.name === 'TokenExpiredError') {
239240
const errorMessage = `${this.tokenInfo.jwtName} has expired. Get a fresh ${this.tokenInfo.shortName}` +
@@ -246,8 +247,19 @@ export class FirebaseTokenVerifier {
246247
}
247248
return reject(new FirebaseAuthError(AuthClientErrorCode.INVALID_ARGUMENT, error.message));
248249
} else {
249-
decodedToken.uid = decodedToken.sub;
250-
resolve(decodedToken);
250+
// TODO(rsgowman): I think the typing on jwt.verify is wrong. It claims that this can be either a string or an
251+
// object, but the code always seems to call it as an object. Investigate and upstream typing changes if this
252+
// is actually correct.
253+
if (typeof decodedToken === 'string') {
254+
return reject(new FirebaseAuthError(
255+
AuthClientErrorCode.INTERNAL_ERROR,
256+
"Unexpected decodedToken. Expected an object but got a string: '" + decodedToken + "'",
257+
));
258+
} else {
259+
const decodedIdToken = (decodedToken as DecodedIdToken);
260+
decodedIdToken.uid = decodedIdToken.sub;
261+
resolve(decodedIdToken);
262+
}
251263
}
252264
});
253265
});

src/messaging/messaging-types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ export interface NotificationMessagePayload {
203203
export interface MessagingPayload {
204204
data?: DataMessagePayload;
205205
notification?: NotificationMessagePayload;
206+
[index: string]: DataMessagePayload | NotificationMessagePayload;
206207
}
207208

208209
/* Options that can passed along with messages */

test/unit/messaging/messaging.spec.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import * as mocks from '../../resources/mocks';
2828

2929
import {FirebaseApp} from '../../../src/firebase-app';
3030
import {
31-
Message, MessagingOptions, MessagingPayload, MessagingDevicesResponse,
31+
Message, MessagingOptions, MessagingPayload, MessagingDevicesResponse, MessagingDeviceGroupResponse,
3232
MessagingTopicManagementResponse, BatchResponse, SendResponse, MulticastMessage,
3333
} from '../../../src/messaging/messaging-types';
3434
import {
@@ -1309,10 +1309,11 @@ describe('Messaging', () => {
13091309
mocks.messaging.registrationToken + '2',
13101310
],
13111311
mocks.messaging.payload,
1312-
).then((response: MessagingDevicesResponse) => {
1312+
).then((response: MessagingDevicesResponse | MessagingDeviceGroupResponse) => {
13131313
expect(response).to.have.keys([
13141314
'failureCount', 'successCount', 'canonicalRegistrationTokenCount', 'multicastId', 'results',
13151315
]);
1316+
response = response as MessagingDevicesResponse;
13161317
expect(response.failureCount).to.equal(2);
13171318
expect(response.successCount).to.equal(1);
13181319
expect(response.canonicalRegistrationTokenCount).to.equal(1);
@@ -2084,19 +2085,19 @@ describe('Messaging', () => {
20842085
invalidPayloads.forEach((invalidPayload) => {
20852086
it(`should throw given invalid type for payload argument: ${ JSON.stringify(invalidPayload) }`, () => {
20862087
expect(() => {
2087-
messaging.sendToDevice(mocks.messaging.registrationToken, invalidPayload as MessagingPayload);
2088+
messaging.sendToDevice(mocks.messaging.registrationToken, invalidPayload as unknown as MessagingPayload);
20882089
}).to.throw('Messaging payload must be an object');
20892090

20902091
expect(() => {
2091-
messaging.sendToDeviceGroup(mocks.messaging.notificationKey, invalidPayload as MessagingPayload);
2092+
messaging.sendToDeviceGroup(mocks.messaging.notificationKey, invalidPayload as unknown as MessagingPayload);
20922093
}).to.throw('Messaging payload must be an object');
20932094

20942095
expect(() => {
2095-
messaging.sendToTopic(mocks.messaging.topic, invalidPayload as MessagingPayload);
2096+
messaging.sendToTopic(mocks.messaging.topic, invalidPayload as unknown as MessagingPayload);
20962097
}).to.throw('Messaging payload must be an object');
20972098

20982099
expect(() => {
2099-
messaging.sendToCondition(mocks.messaging.condition, invalidPayload as MessagingPayload);
2100+
messaging.sendToCondition(mocks.messaging.condition, invalidPayload as unknown as MessagingPayload);
21002101
}).to.throw('Messaging payload must be an object');
21012102
});
21022103
});

tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"alwaysStrict": true,
1010
"strictBindCallApply": true,
1111
//"strictNullChecks": true,
12-
//"strictFunctionTypes": true,
12+
"strictFunctionTypes": true,
1313
//"strictPropertyInitialization": true,
1414
"lib": ["es2015"],
1515
"outDir": "lib",

0 commit comments

Comments
 (0)