Атрибут Firebase Auth ID имеет неправильную претензию "aud"

Я пытаюсь проверить бэкэнд idToken. Пользователь успешно вошел в систему на стороне клиента firebase, но когда я пытаюсь проверить idToken на моем бэкэнд, я получаю сообщение об этом не очень полезное сообщение

У токена идентификатора Firebase Auth ID неверная заявка "aud"

Сообщение об ошибке, похоже, стало немного более информативным и сводится к отсутствию имени проекта в ключе авторизации:

Ошибка: токен Firebase ID имеет неправильную претензию "ауди" (аудитория). Ожидаемый "stripmall-0000", но получил "617699194096-0aafcvsml0gke61d6077kkark051f3e1.apps.googleusercontent.com". Убедитесь, что маркер ID поступает из одного проекта Firebase, так как учетной записи службы, используемой для аутентификации этого SDK. Видеть https://firebase.google.com/docs/auth/server/verify-id-tokens для подробнее о том, как получить токен ID.

Кто-нибудь с малейшей идеей может ошибаться? Я правильно получаю tokenId от клиента, поэтому это не должно быть проблемой. Искренние пристрастия, если это было задано раньше или тривиально каким-либо другим способом.

  firebase.initializeApp({
        serviceAccount: {
            "type": "service_account",
            "project_id": <project id here>,
            "private_key_id": <key id goes here>,
            "private_key": <key goes here>
            "client_email": <email goes here>,
            "client_id": <my client id>,
            "auth_uri": "https://accounts.google.com/o/oauth2/auth",
            "token_uri": "https://accounts.google.com/o/oauth2/token",
            "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
            "client_x509_cert_url": <url goes here>
        },
        databaseURL: <my db url here>
    });

    router.post("/verify", function (req, res) {
        firebase.auth().verifyIdToken(req.body.idToken).then(function (decodedToken) {
            var uid = decodedToken.sub;
            res.send(uid);
        }).catch(function (error, param2) {
            console.log(error);  // 'Firebase Auth ID token has incorrect "aud" claim'
        });

    });

Ответ 1

Возможно, проблема заключается в том, что вы пытаетесь использовать токен JWT, возвращаемый одной из функций auth(), таких как firebaseRef.auth().signInWithPopup(). Они возвращают токен JWT, однако утверждения auth, вероятно, будут неправильными и не будут проходить проверку на verifyIdToken. Это было подтверждено технической поддержкой firebase.

Вы должны использовать функцию firebaseRef.auth().currentUser.getToken(). Этот токен пройдет проверку.

Ответ 2

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

FileInputStream serviceAccount = new FileInputStream("path/to/serviceAccountKey.json");

FirebaseOptions options = new FirebaseOptions.Builder()
            .setCredentials(GoogleCredentials.fromStream(serviceAccount))
            .setDatabaseUrl("https://<DATABASE_NAME>.firebaseio.com/")
            .build();

FirebaseApp.initializeApp(options);
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();

// Get the FB uid from the token
FirebaseToken decodedToken = firebaseAuth.verifyIdTokenAsync(token).get();
String uid = decodedToken.getUid();

источник: https://firebase.google.com/docs/admin/setup

Ответ 3

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

Ответ 4

TL;DR: как уже упоминалось в другом ответе, вы неправильно инициализируете приложение.

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

Прежде всего, если API не изменился с тех пор, как был задан этот вопрос, serviceAccount не существует как свойство как часть интерфейса AppOptions, поэтому, вероятно, вы получили ошибку. Таким образом, я буду считать, что у вас там имеется в виду, что в credential ключа.

Во-вторых, вы видите, что эта ошибка выдается по адресу https://github.com/firebase/firebase-admin-node/blob/master/src/auth/token-verifier.ts (строка 187 на момент написания этой статьи), где утверждение aud в токене сравнивается с this.projectId.

Теперь, как упоминают другие ответы, это может быть потому, что токен, который вы пытаетесь проверить, был создан не на стороне клиента, а каким-то другим пользовательским методом, и в этом случае утверждение aud может отсутствовать, что-то совершенно случайное, или что-то, что определенно не будет соответствовать вашему projectId так что вы должны проверить это в первую очередь.

Однако, если вы уверены, что токен был создан на стороне клиента, он сводится к тому, что projectId не установлен или, по крайней мере, не настроен так, как вы ожидаете. Если вы посмотрите на метод getProjectId() в https://github.com/firebase/firebase-admin-node/blob/master/src/utils/index.ts (строка 66 на момент написания этой статьи), вы увидите что projectId определяется в одном из 3 -х способов: от app.options объекта непосредственно из projectId собственности в app.options.credential, или из process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT. Это означает, что если projectId не установлен, и если ваш проект размещен на GCloud (который я предполагаю, что stripmall-0000 есть), то Google будет автоматически использовать текущую среду ProjectID для всего, что касается firebase-AUTH, не ProjectID из исходный проект.

Итак, три варианта:

  1. Инициализируйте ваше приложение с AppOptions projectId установленным непосредственно в AppOptions:

    firebase.initializeApp({
        databaseURL: <my db url here>,
        // Set your projectId directly here in options:
        projectId: <your-projectId-here>
    });
    
  2. Или, возможно, лучше сделать это, правильно установив объект учетных данных:

    firebase.initializeApp({
        credentials: admin.credential.cert(<<path-to-your-certificate> || <admin.ServiceAccount object>>),
        databaseURL: <my db url here>
    });
    
  3. Или просто разместите приложение в том же проекте, что и ваше приложение Firebase (теперь, когда они являются частью одной экосистемы), чтобы переменные среды были одинаковыми. (На самом деле не 100% об этом, но я предполагаю, что именно так работают firebase-функции или облачные функции)