|
16 | 16 |
|
17 | 17 | import {AuthClientErrorCode, FirebaseAuthError, ErrorInfo} from '../utils/error';
|
18 | 18 |
|
| 19 | +import * as util from '../utils/index'; |
19 | 20 | import * as validator from '../utils/validator';
|
20 | 21 | import * as jwt from 'jsonwebtoken';
|
21 | 22 | import { HttpClient, HttpRequestConfig, HttpError } from '../utils/api-request';
|
22 | 23 | import { DecodedIdToken } from './auth';
|
23 |
| -import { Agent } from 'http'; |
| 24 | +import { FirebaseApp } from '../firebase-app'; |
24 | 25 |
|
25 | 26 | // Audience to use for Firebase Auth Custom tokens
|
26 | 27 | const FIREBASE_AUDIENCE = 'https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit';
|
@@ -75,9 +76,8 @@ export class FirebaseTokenVerifier {
|
75 | 76 | private readonly shortNameArticle: string;
|
76 | 77 |
|
77 | 78 | constructor(private clientCertUrl: string, private algorithm: string,
|
78 |
| - private issuer: string, private projectId: string | null, |
79 |
| - private tokenInfo: FirebaseTokenInfo, |
80 |
| - private readonly httpAgent?: Agent) { |
| 79 | + private issuer: string, private tokenInfo: FirebaseTokenInfo, |
| 80 | + private readonly app: FirebaseApp) { |
81 | 81 | if (!validator.isURL(clientCertUrl)) {
|
82 | 82 | throw new FirebaseAuthError(
|
83 | 83 | AuthClientErrorCode.INVALID_ARGUMENT,
|
@@ -144,7 +144,14 @@ export class FirebaseTokenVerifier {
|
144 | 144 | );
|
145 | 145 | }
|
146 | 146 |
|
147 |
| - if (!validator.isNonEmptyString(this.projectId)) { |
| 147 | + return util.findProjectId(this.app) |
| 148 | + .then((projectId) => { |
| 149 | + return this.verifyJWTWithProjectId(jwtToken, projectId); |
| 150 | + }); |
| 151 | + } |
| 152 | + |
| 153 | + private verifyJWTWithProjectId(jwtToken: string, projectId: string | null): Promise<DecodedIdToken> { |
| 154 | + if (!validator.isNonEmptyString(projectId)) { |
148 | 155 | throw new FirebaseAuthError(
|
149 | 156 | AuthClientErrorCode.INVALID_CREDENTIAL,
|
150 | 157 | `Must initialize app with a cert credential or set your Firebase project ID as the ` +
|
@@ -186,13 +193,13 @@ export class FirebaseTokenVerifier {
|
186 | 193 | } else if (header.alg !== this.algorithm) {
|
187 | 194 | errorMessage = `${this.tokenInfo.jwtName} has incorrect algorithm. Expected "` + this.algorithm + `" but got ` +
|
188 | 195 | `"` + header.alg + `".` + verifyJwtTokenDocsMessage;
|
189 |
| - } else if (payload.aud !== this.projectId) { |
| 196 | + } else if (payload.aud !== projectId) { |
190 | 197 | errorMessage = `${this.tokenInfo.jwtName} has incorrect "aud" (audience) claim. Expected "` +
|
191 |
| - this.projectId + `" but got "` + payload.aud + `".` + projectIdMatchMessage + |
| 198 | + projectId + `" but got "` + payload.aud + `".` + projectIdMatchMessage + |
192 | 199 | verifyJwtTokenDocsMessage;
|
193 |
| - } else if (payload.iss !== this.issuer + this.projectId) { |
| 200 | + } else if (payload.iss !== this.issuer + projectId) { |
194 | 201 | errorMessage = `${this.tokenInfo.jwtName} has incorrect "iss" (issuer) claim. Expected ` +
|
195 |
| - `"${this.issuer}"` + this.projectId + `" but got "` + |
| 202 | + `"${this.issuer}"` + projectId + `" but got "` + |
196 | 203 | payload.iss + `".` + projectIdMatchMessage + verifyJwtTokenDocsMessage;
|
197 | 204 | } else if (typeof payload.sub !== 'string') {
|
198 | 205 | errorMessage = `${this.tokenInfo.jwtName} has no "sub" (subject) claim.` + verifyJwtTokenDocsMessage;
|
@@ -284,7 +291,7 @@ export class FirebaseTokenVerifier {
|
284 | 291 | const request: HttpRequestConfig = {
|
285 | 292 | method: 'GET',
|
286 | 293 | url: this.clientCertUrl,
|
287 |
| - httpAgent: this.httpAgent, |
| 294 | + httpAgent: this.app.options.httpAgent, |
288 | 295 | };
|
289 | 296 | return client.send(request).then((resp) => {
|
290 | 297 | if (!resp.isJson() || resp.data.error) {
|
@@ -327,35 +334,31 @@ export class FirebaseTokenVerifier {
|
327 | 334 | /**
|
328 | 335 | * Creates a new FirebaseTokenVerifier to verify Firebase ID tokens.
|
329 | 336 | *
|
330 |
| - * @param {string} projectId Project ID string. |
331 |
| - * @param {Agent} httpAgent Optional HTTP agent. |
| 337 | + * @param {FirebaseApp} app Firebase app instance. |
332 | 338 | * @return {FirebaseTokenVerifier}
|
333 | 339 | */
|
334 |
| -export function createIdTokenVerifier(projectId: string | null, httpAgent?: Agent): FirebaseTokenVerifier { |
| 340 | +export function createIdTokenVerifier(app: FirebaseApp): FirebaseTokenVerifier { |
335 | 341 | return new FirebaseTokenVerifier(
|
336 |
| - CLIENT_CERT_URL, |
337 |
| - ALGORITHM_RS256, |
338 |
| - 'https://securetoken.google.com/', |
339 |
| - projectId, |
340 |
| - ID_TOKEN_INFO, |
341 |
| - httpAgent, |
| 342 | + CLIENT_CERT_URL, |
| 343 | + ALGORITHM_RS256, |
| 344 | + 'https://securetoken.google.com/', |
| 345 | + ID_TOKEN_INFO, |
| 346 | + app, |
342 | 347 | );
|
343 | 348 | }
|
344 | 349 |
|
345 | 350 | /**
|
346 | 351 | * Creates a new FirebaseTokenVerifier to verify Firebase session cookies.
|
347 | 352 | *
|
348 |
| - * @param {string} projectId Project ID string. |
349 |
| - * @param {Agent} httpAgent Optional HTTP agent. |
| 353 | + * @param {FirebaseApp} app Firebase app instance. |
350 | 354 | * @return {FirebaseTokenVerifier}
|
351 | 355 | */
|
352 |
| -export function createSessionCookieVerifier(projectId: string | null, httpAgent?: Agent): FirebaseTokenVerifier { |
| 356 | +export function createSessionCookieVerifier(app: FirebaseApp): FirebaseTokenVerifier { |
353 | 357 | return new FirebaseTokenVerifier(
|
354 | 358 | SESSION_COOKIE_CERT_URL,
|
355 | 359 | ALGORITHM_RS256,
|
356 | 360 | 'https://session.firebase.google.com/',
|
357 |
| - projectId, |
358 | 361 | SESSION_COOKIE_INFO,
|
359 |
| - httpAgent, |
| 362 | + app, |
360 | 363 | );
|
361 | 364 | }
|
0 commit comments