Ошибка аутентификации Firebase Admin SDK TOO_MANY_ATTEMPTS_TRY_LATER

Я использую firebase admin sdk в своих облачных функциях, и я случайно получаю ошибку в некоторых исполнениях при попытке получить пользователя по uid.

let userRecord = await admin.auth().getUser(userId);

Подробная информация об ошибке:

{"error":{"code":400,"message":"TOO_MANY_ATTEMPTS_TRY_LATER",
 "errors":[{ "message":"TOO_MANY_ATTEMPTS_TRY_LATER",
             "domain":"global","reason":"invalid"}]
 }
}

Моя облачная функция выполняется в базе данных в реальном времени write и может запускаться для нескольких пользователей. Всего у меня есть 4 вызова функции аутентификации в одном выполнении, первый - это предыдущий, второй вызов - снова получить пользователя с помощью uid или email, третий вызов - generateEmailVerificationLink, а последний вызов - generatePasswordResetLink.

Я проверил ограничения скорости в документации для аутентификации, но нет никаких упоминаний об ограничении скорости для этой операции. Также ошибка TOO_MANY_ATTEMPTS_TRY_LATER упоминалась только в REST API для регистрации с паролем электронной почты.

Если эта ошибка связана с ограничением скорости, что мне следует изменить, чтобы предотвратить эту ошибку, учитывая, что эти 4 вызова необходимы для операции, необходимой для записи в базу данных ?.

РЕДАКТИРОВАТЬ:

Я определил фактический вызов, который вызывает ошибку слишком большого количества попыток. Вызовы auth().generateEmailVerificationLink() и auth().generatePasswordResetLink() вызывают эту ошибку при слишком большом количестве вызовов.

Я вызвал этих двоих в цикл со 100 итерациями и ждал обещаний. Первые исполнения завершаются без ошибок, т.е. 200 запросов. Но запуск второго выполнения, как только закончится первое, вызовет ошибку слишком большого количества попыток. Так что я думаю, что у этих двух звонков есть предел. Теперь я пытаюсь сократить количество обращений и повторно использовать информацию о ссылках. Другие вызовы, такие как getUserByEmail, работают нормально.

let promises = [];
let auth = admin.auth();
let hrstart = process.hrtime()
for (let i = 0; i < 100; i++) {
    promises.push(auth.getUserByEmail("user email"));
    promises.push(auth.generateEmailVerificationLink("user email", {url: `https://app.firebaseapp.com/path`}));
    promises.push(auth.generatePasswordResetLink("user email", {url: `https://app.firebaseapp.com/path`}));

}

Promise.all(promises)
    .then(value => {
        let hrend = process.hrtime(hrstart);
        console.log(hrend);
        // console.log(value)
    });

person Umar Hussain    schedule 15.02.2019    source источник
comment
Вы упомянули, что есть четыре звонка. Покажите, пожалуйста, весь пакет кода.   -  person Doug Stevenson    schedule 15.02.2019
comment
Привет, Умар, не могли бы вы предоставить информацию о том, какой вызов API вызывает ошибку? Это на 4-м звонке generatePasswordResetLink?   -  person bojeil    schedule 15.02.2019
comment
В настоящее время я больше изучаю эту проблему, есть вызовы операций аутентификации в двух разных исполнениях функций firebase, поэтому я получу дополнительную информацию. Что касается ошибки, это первый вызов getUser. Я думаю, что одно выполнение переходит к третьему или четвертому вызову, а второе выполнение затем не выполняется при вызове getUser, возможно, потому, что выполнение выполняется параллельно.   -  person Umar Hussain    schedule 15.02.2019
comment
Я вернусь с дополнительной информацией и кодом, если это необходимо.   -  person Umar Hussain    schedule 15.02.2019
comment
Также вам нужно оптимизировать ваши звонки. Почему вам нужно искать пользователя по uid, а затем по электронной почте? Что касается проверки электронной почты и сброса пароля, почему вам нужно звонить одному и тому же пользователю? Я считаю, что ссылка для сброса пароля также должна подтверждать пользователя.   -  person bojeil    schedule 15.02.2019
comment
Да, я оптимизирую свои звонки после этой ошибки, повторно используя информацию, где это возможно. Я получаю пользователя либо по идентификатору, либо по электронной почте, в зависимости от того, что доступно. Ссылка для сброса пароля в моем случае не является обязательной, поэтому я не могу использовать ее всегда.   -  person Umar Hussain    schedule 15.02.2019
comment
@DougStevenson, пожалуйста, посмотрите отредактированный вопрос. Спасибо.   -  person Umar Hussain    schedule 18.02.2019
comment
@bojeil, пожалуйста, посмотрите отредактированный вопрос.   -  person Umar Hussain    schedule 18.02.2019


Ответы (2)


Ошибка была конкретно в операции auth.createEmailLink. Эта функция имеет следующие ограничения: 20QPS / IP-адрес, где QPS - (запросов в секунду). Этот предел можно увеличить, отправив вариант использования в Firebase.

Я получил эту информацию от службы поддержки firebase после отправки своей проблемы.

Ссылка на мою проблему с github: https://github.com/firebase/firebase-admin-node/issues/458

person Umar Hussain    schedule 20.02.2019

У меня было меньше 20QPS, но получалось это исключение. Фактически, он всегда будет выдавать исключение TOO_MANY_ATTEMPTS_TRY_LATER при второй попытке.

Оказалось, что вместо создания статического экземпляра использовался FirebaseAuth.DefaultInstance:

В определении класса: private readonly FirebaseApp _firebase;

В конструкторе класса: _firebase = FirebaseAdmin.FirebaseApp.Create();

В функции:

var auth = FirebaseAuth.GetAuth(_firebase);
var actionCodeSettings = new ActionCodeSettings()
{
    ...
};
var link = await auth.GenerateEmailVerificationLinkAsync(email, actionCodeSettings);
return link;
person Troy Busot    schedule 09.09.2020
comment
Не уверен, пойму ли я, не могли бы вы рассказать, в чем заключается настоящая проблема и решение? У меня такая же проблема, и я не могу понять это - person DaveTheAl; 31.05.2021