Skip to content

There is an error in the type defined in the ServiceAccount #2769

Closed
@k-redstone

Description

@k-redstone

Describe your environment

  • Operating System version: window 11
  • Firebase SDK version: firebase-admin 13.0.0
  • Firebase Product: credential, auth
  • Node.js version: 20.12.0
  • NPM version: 10,5.0

[REQUIRED] Step 3: Describe the problem

I followed the example provided for the admin.credential.cert() function, but encountered an issue.

I'm trying to initialize the app with admin.initializeApp() using Firebase Admin SDK version 13. However, there seems to be a discrepancy between the type defined in ServiceAccount and the key values actually used for authentication.

Steps to reproduce:

The following code causes the following error.

The incoming JSON object does not contain a private_key field
The incoming JSON object does not contain a client_email field

as-is

import admin, { ServiceAccount } from "firebase-admin";

const serviceAccount: ServiceAccount = {
  projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
  privateKey: process.env.FIREBASE_PRIVATE_KEY?.replace(/\\n/g, "\n"),
  clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
};

if (!admin.apps.length) {
  admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: `https://${process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID}.firebaseio.com`,
  });
}

export default admin;

So, after modifying the code as follows, it worked correctly.

import admin from 'firebase-admin'

const serviceAccount = {
  projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
  client_email: process.env.FIREBASE_CLIENT_EMAIL,
  private_key: process.env.FIREBASE_PRIVATE_KEY?.replace(/\\n/g, '\n'),
}

if (!admin.apps.length) {
  admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: `https://${process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID}.firebaseio.com`,
  })
} else {
  admin.app()
}

export default admin

Relevant Code:

In my opinion, the transition to version 13.0 involved switching to use google-auth-library, which seems to be causing this issue.

maybe auth.fromJSON() cause error

src/app/credential-internal.ts 456 line

function populateGoogleAuth(keyFile: string | object, httpAgent?: Agent)
  : { auth: GoogleAuth, client: AnyAuthClient | undefined } {
  let client: AnyAuthClient | undefined;
  const auth = new GoogleAuth({
    scopes: SCOPES,
    clientOptions: {
      transporterOptions: {
        agent: httpAgent,
      },
    },
    keyFile: (typeof keyFile === 'string') ? keyFile : undefined,
  });

  if (typeof keyFile === 'object') {
    if (!util.isNonNullObject(keyFile)) {
      throw new FirebaseAppError(
        AppErrorCodes.INVALID_CREDENTIAL,
        'Service account must be an object.',
      );
    }
    client = auth.fromJSON(keyFile);
  }
  return { auth, client };
}

google-auth-library /src/aut/jtwclient.js 206 line

  fromJSON(json) {
        if (!json) {
            throw new Error('Must pass in a JSON object containing the service account auth settings.');
        }
        if (!json.client_email) {
            throw new Error('The incoming JSON object does not contain a client_email field');
        }
        if (!json.private_key) {
            throw new Error('The incoming JSON object does not contain a private_key field');
        }
        // Extract the relevant information from the json key file.
        this.email = json.client_email;
        this.key = json.private_key;
        this.keyId = json.private_key_id;
        this.projectId = json.project_id;
        this.quotaProjectId = json.quota_project_id;
        this.universeDomain = json.universe_domain || this.universeDomain;
    }

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions