Входящий объект JSON не содержит поле client_email - PullRequest
20 голосов
/ 27 июня 2019

Я пытаюсь создать облачную функцию Firebase.Так что я бы запустил локальную облачную функцию Firebase.Но это не работает, как настроить аутентификацию.

Я установил Firebase Tools: https://firebase.google.com/docs/functions/local-emulator Я выполнил команду firebase login, так что теперь я вошел в систему.Затем я создал ключ json с помощью этого урока: https://cloud.google.com/docs/authentication/getting-started Теперь, если я наберу echo $GOOGLE_APPLICATION_CREDENTIALS, результат будет /home/$USER/.google/****.json, который содержит

"project_id","private_key_id","private_key","client_email", "client_id",  "auth_uri", "token_uri", "auth_provider_x509_cert_url", "client_x509_cert_url"

Также я попытался установитьполный google cloud sdk и я запустил: gcloud auth application-default login но безуспешно.

Версии пакета Npm:

"firebase-functions":"3.0.2"
"firebase-admin": "8.2.0"

Я думаю, что предоставил достаточно информации, но не стесняйтесь спрашивать меня, еслиВы хотите.

const functions = require("firebase-functions");
const admin = require("firebase-admin");
const express = require("express");
const app = express();
app.get("/", async (req, res) => {
admin.firestore().collection('something').get().then((collection) =>
    return res.send({"count": collection.docs.length, "status": 200});
});
exports.exports = functions.https.onRequest(app);

код не важен, самое главное, что даже я выполнил все эти шаги, когда я локально эмулирую свою пожарную базу с помощью firebase serve и запускаю функцию, яесть эта ошибка: Ошибка: входящий объект JSON не содержит поле client_email

Я могу убедиться, что файл json содержит поле client_email.

Можете ли вы помочь мне пройти аутентификацию в Google?

Спасибо за вашу помощь.

Ответы [ 6 ]

18 голосов
/ 28 июня 2019

У меня была похожая проблема. Вероятно, это ошибка в версии 7.0.2 из firebase-tools. Я откатился до версии 7.0.0 и теперь она работает.

Итак, временное решение:

npm i firebase-tools@7.0.0 -g  
10 голосов
/ 04 июля 2019

Короче говоря:

admin.initializeApp({ credential: admin.credential.applicationDefault() });

См. Документы для admin.credential.applicationDefault ()

Обновление: обратите внимание, что это рекомендуется только для тестирования / эксперимента:

Эта стратегия полезна при тестировании и экспериментах, но может сделать Трудно сказать, какие учетные данные использует ваше приложение. Мы рекомендуем явно указывать, какие учетные данные приложения следует использовать, ... Источник

Немного больше информации

У меня было то же самое при попытке локально вызвать функцию firebase, которая пытается обновить некоторые документы в базе данных firestore в пакетном режиме. (Не тестировал без партии).

Чтобы начать локально вызывать функции firebase, я использую:

firebase function:shell

Как вы, вероятно, знаете, здесь перечислены доступные функции для вашего проекта.

Я вызвал свою функцию и получил следующую ошибку callstack:

Unhandled error Error: The incoming JSON object does not contain a client_email field
>      at JWT.fromJSON (D:\thdk\Projects\timesheets\functions\node_modules\firebase-admin\node_modules\google-auth-library\build\src\auth\jwtclient.js:165:19)
>      at GoogleAuth.fromJSON (D:\thdk\Projects\timesheets\functions\node_modules\firebase-admin\node_modules\google-auth-library\build\src\auth\googleauth.js:294:16)
>      at GoogleAuth.getClient (D:\thdk\Projects\timesheets\functions\node_modules\firebase-admin\node_modules\google-auth-library\build\src\auth\googleauth.js:476:52)
>      at GrpcClient._getCredentials (D:\thdk\Projects\timesheets\functions\node_modules\firebase-admin\node_modules\google-gax\build\src\grpc.js:107:40)
>      at GrpcClient.createStub (D:\thdk\Projects\timesheets\functions\node_modules\firebase-admin\node_modules\google-gax\build\src\grpc.js:223:34)
>      at new FirestoreClient (D:\thdk\Projects\timesheets\functions\node_modules\firebase-admin\node_modules\@google-cloud\firestore\build\src\v1\firestore_client.js:128:39)
>      at ClientPool.Firestore._clientPool.pool_1.ClientPool [as clientFactory] (D:\thdk\Projects\timesheets\functions\node_modules\firebase-admin\node_modules\@google-cloud\firestore\build\src\index.js:315:26)
>      at ClientPool.acquire (D:\thdk\Projects\timesheets\functions\node_modules\firebase-admin\node_modules\@google-cloud\firestore\build\src\pool.js:61:35)
>      at ClientPool.run (D:\thdk\Projects\timesheets\functions\node_modules\firebase-admin\node_modules\@google-cloud\firestore\build\src\pool.js:114:29)
>      at Firestore.readStream (D:\thdk\Projects\timesheets\functions\node_modules\firebase-admin\node_modules\@google-cloud\firestore\build\src\index.js:995:26)

RESPONSE RECEIVED FROM FUNCTION: 500, {
  "error": {
    "status": "INTERNAL",
    "message": "INTERNAL"
  }
}

Я выполнял свою функцию локально, используя командную строку: firebase functions:shell

Я использовал этот код:

// Reference report in Firestore
const db = admin.firestore();

admin.initializeApp();

export const performMyCallableFirebaseFunction = (db, { from, to }) => {
    return db.collection("collectionName").where("prop", "==", from).limit(500).get().then(snapshot => {
        if (snapshot.empty) return new Promise(resolve => resolve(`No docs found with prop: ${from}`));

        const batch = db.batch();
        snapshot.forEach(doc => batch.update(doc.ref, { prop: to }));

        return batch.commit();
    });
};
exports.myCallableFirebaseFunction = functions.https.onCall(data => performMyCallableFirebaseFunction(db, data.from, data.to));

Я изменил строку

admin.initializeApp();

до

admin.initializeApp({ credential: admin.credential.applicationDefault() });

и теперь я смог вызвать свою функцию локально, используя:

firebase functions:shell
firebase > myCallableFirebaseFunction({from: "foo", to: "bar"})

См. Документы для admin.credential.applicationDefault ()

4 голосов
/ 27 июня 2019

Вероятно, вам нужно настроить Firebase Admin SDK для использования эмулятора Firebase. Вы можете сделать это, передав свойство credential при вызове метода admin.initializeApp():

const serviceAccount = require('../serviceAccount.json');

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
});

Вы можете загрузить JSON-файл своей учетной записи службы в консоли Firebase:

  • Нажмите на значок «Настройки»;
  • Перейти к «Пользователи и разрешения»;
  • Нажмите на ссылку, где написано, что «N сервисных учетных записей также имеют доступ к этому проекту»;
  • Нажмите кнопку «Создать новый закрытый ключ».
2 голосов
/ 16 июля 2019

Вот как я решил проблему после нескольких часов борьбы:

Краткий ответ:

Создание ключа Firebase-adminsdk

Как это сделать:

  • Перейти к Google-cloud-platform > Service accounts https://console.cloud.google.com/iam-admin/serviceaccounts/

  • Выбрать проект

  • Выберите firebase-admin-sdk, похожий на firebase-adminsdk-u4k3i@example..
  • Включите режим редактирования
  • Create key и выберите JSON
  • Вы можете загрузить .json.Который содержит ProjectID, PrivateKey and ClientEmail
  • , используйте информацию, подобную этой, при инициализации приложения:
// Providing a service account object inline
admin.initializeApp({
    credential: admin.credential.cert({
        projectId: "<PROJECT_ID>",
        clientEmail: "foo@<PROJECT_ID>.iam.gserviceaccount.com",
        privateKey: "-----BEGIN PRIVATE KEY-----<KEY>-----END PRIVATE KEY-----\n"
    })
});
2 голосов
/ 28 июня 2019

Создав проект Firebase, вы можете инициализировать SDK с помощью стратегии авторизации, которая объединяет файл учетной записи службы и учетные данные приложения Google по умолчанию.

Чтобы аутентифицировать учетную запись службы и авторизовать ее для доступа к службам Firebase, вы должны сгенерировать файл закрытого ключа в формате JSON.

Чтобы создать файл личного ключа для вашей учетной записи службы:

  1. В консоли Firebase откройте Настройки> Учетные записи служб.

  2. Нажмите «Создать новый закрытый ключ», затем подтвердите, нажав «Создать ключ».

  3. Безопасное хранение файла JSON, содержащего ключ.

Задайте для переменной среды GOOGLE_APPLICATION_CREDENTIALS путь к файлу JSON, в котором содержится ключ учетной записи службы. Эта переменная применяется только к текущему сеансу оболочки, поэтому, если вы открываете новый сеанс, установите переменную снова.

$env:GOOGLE_APPLICATION_CREDENTIALS="C:\Users\username\Downloads\service-account-file.json"

https://firebase.google.com/docs/admin/setup?authuser=3

0 голосов
/ 02 июля 2019

Я получаю эту ошибку при запуске firebase emulators:start.

В соответствии с исследованием этой ошибки: https://github.com/firebase/firebase-tools/issues/1451, похоже, что это проблема с обращением к приложению напрямую, а не через модуль администратора.

т.е. это вызывает ошибку:

const app = admin.initializeApp();
const firestore = app.firestore();

но это не так:

admin.initializeApp();
const firestore = admin.firestore();

Однако для первоначального вопроса вы используете admin.firestore (), чтобы не было проблемы. Кажется, что admin.initializeApp() никогда не вызывается. Возможно, это может быть причиной вашей проблемы?

...