@@ -19,6 +19,7 @@ import {AuthClientErrorCode, FirebaseAuthError, ErrorInfo} from '../utils/error'
1919import * as validator from '../utils/validator' ;
2020import * as jwt from 'jsonwebtoken' ;
2121import { HttpClient , HttpRequestConfig , HttpError } from '../utils/api-request' ;
22+ import { DecodedIdToken } from './auth' ;
2223
2324// Audience to use for Firebase Auth Custom tokens
2425const 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 } ) ;
0 commit comments