@@ -19,6 +19,7 @@ import {AuthClientErrorCode, FirebaseAuthError, ErrorInfo} from '../utils/error'
19
19
import * as validator from '../utils/validator' ;
20
20
import * as jwt from 'jsonwebtoken' ;
21
21
import { HttpClient , HttpRequestConfig , HttpError } from '../utils/api-request' ;
22
+ import { DecodedIdToken } from './auth' ;
22
23
23
24
// Audience to use for Firebase Auth Custom tokens
24
25
const FIREBASE_AUDIENCE = 'https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit' ;
@@ -130,10 +131,10 @@ export class FirebaseTokenVerifier {
130
131
* Verifies the format and signature of a Firebase Auth JWT token.
131
132
*
132
133
* @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
134
135
* token.
135
136
*/
136
- public verifyJWT ( jwtToken : string ) : Promise < object > {
137
+ public verifyJWT ( jwtToken : string ) : Promise < DecodedIdToken > {
137
138
if ( ! validator . isString ( jwtToken ) ) {
138
139
throw new FirebaseAuthError (
139
140
AuthClientErrorCode . INVALID_ARGUMENT ,
@@ -224,16 +225,16 @@ export class FirebaseTokenVerifier {
224
225
* Verifies the JWT signature using the provided public key.
225
226
* @param {string } jwtToken The JWT token to verify.
226
227
* @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
228
229
* verification.
229
230
*/
230
- private verifyJwtSignatureWithKey ( jwtToken : string , publicKey : string ) : Promise < object > {
231
+ private verifyJwtSignatureWithKey ( jwtToken : string , publicKey : string ) : Promise < DecodedIdToken > {
231
232
const verifyJwtTokenDocsMessage = ` See ${ this . tokenInfo . url } ` +
232
233
`for details on how to retrieve ${ this . shortNameArticle } ${ this . tokenInfo . shortName } .` ;
233
234
return new Promise ( ( resolve , reject ) => {
234
235
jwt . verify ( jwtToken , publicKey , {
235
236
algorithms : [ this . algorithm ] ,
236
- } , ( error : jwt . VerifyErrors , decodedToken : any ) => {
237
+ } , ( error : jwt . VerifyErrors , decodedToken : string | object ) => {
237
238
if ( error ) {
238
239
if ( error . name === 'TokenExpiredError' ) {
239
240
const errorMessage = `${ this . tokenInfo . jwtName } has expired. Get a fresh ${ this . tokenInfo . shortName } ` +
@@ -246,8 +247,19 @@ export class FirebaseTokenVerifier {
246
247
}
247
248
return reject ( new FirebaseAuthError ( AuthClientErrorCode . INVALID_ARGUMENT , error . message ) ) ;
248
249
} 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
+ }
251
263
}
252
264
} ) ;
253
265
} ) ;
0 commit comments