There is an error in the type defined in the ServiceAccount
Closed this issue · 8 comments
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;
}
I found a few problems with this issue:
- I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.
- This issue does not seem to follow the issue template. Make sure you provide all the required information.
Hi @k-redstone ,
Thank you for reporting this issue. You are right! I think this is a bug. Let me start working on a fix and in the meantime, your workaround seems reasonable. You can also try setting the GOOGLE_APPLICATION_CREDENTIALS
env variable to point to the service account json file as an alternative.
I can confirm the same thing happened to me yesterday! While I didn’t investigate as thoroughly, I did roll back to a previous version of the admin SDK, but I still received the same error message, and I’m initializing it the same way as the OP. Thanks for taking care of it! 🙏
I came here to file this exact issue as I was banging my head all afternoon trying to understand how this first step was not working! Thanks @k-redstone for filing the issue.
Yup it happened to me too, after changing to client_email and private_key its solved
Same here!
Error output:
ERROR [ExceptionsHandler] Credential implementation provided to initializeApp() via the "credential" property failed to fetch a valid Google OAuth2 access token with the following error: "The incoming JSON object does not contain a client_email field".
I encountered the same issue when upgrading to v13.0.0.
FirebaseAppError: Credential implementation provided to initializeApp() via the "credential" property failed to fetch a valid Google OAuth2 access token with the following error: "The incoming JSON object does not contain a client_email field".
The problem doesn't occur in the latest v12.* version (v12.7.0).
Thanks for your patience folks! This issue is now fixed in v13.0.1
. Please open a new issue if you run into any problems.