mobizt / Firebase-ESP-Client

[DEPRECATED]🔥Firebase Arduino Client Library for ESP8266, ESP32 and RP2040 Pico. The complete, fast, secured and reliable Firebase Arduino client library that supports RTDB, Cloud Firestore, Firebase and Google Cloud Storage, Cloud Messaging and Cloud Functions for Firebase.
MIT License
471 stars 100 forks source link

Programm gets stuck in Firebase.begin(&config, &auth) after User Enters wrong Email or Password #622

Closed MatthiasIllmer closed 8 months ago

MatthiasIllmer commented 8 months ago

I have a UI where the User has to enter his Email and his Password from his Firebase account. The Problem is, when the User enters a wrong Email or a wrong Password, the code gets stuck in this function: "Firebase.begin(&config, &auth);" and i get the following messages in the Terminal until i restart the ESP32:

_Token info: type = id token (GITKit token), status = on request Token info: type = id token (GITKit token), status = error Token error: code: 400, message: INVALID_LOGIN_CREDENTIALS Token info: type = id token (GITKit token), status = error Token error: code: 400, message: bad request Token info: type = id token (GITKit token), status = on request Token info: type = id token (GITKit token), status = error Token error: code: 400, message: TOO_MANY_ATTEMPTS_TRY_LATER : Access to this account has been temporarily disabled due to many failed login attempts. You can immediately restore it by resetting your password or you can try again later. Token info: type = id token (GITKit token), status = error Token error: code: 400, message: bad request Token info: type = id token (GITKit token), status = on request Token info: type = id token (GITKit token), status = error Token error: code: 400, message: TOO_MANY_ATTEMPTS_TRYLATER : Access to this account has been temporarily disabled due to many failed login attempts. You can immediately restore it by resetting your password or you can try again later.

this is my code from the Firebase part: ` configTime(0, 0, ntpServer);

// Assign the api key (required) config.api_key = API_KEY;

// Assign the user sign in credentials auth.user.email = USER_EMAIL; auth.user.password = USER_PASSWORD;

// Assign the RTDB URL (required) config.database_url = DATABASE_URL;

Firebase.reconnectWiFi(true); fbdo.setResponseSize(4096);

// Assign the callback function for the long running token generation task config.token_status_callback = tokenStatusCallback; // see addons/TokenHelper.h

// Assign the maximum retry of token generation config.max_token_generation_retry = 5;

// Initialize the library with the Firebase authen and config

Firebase.begin(&config, &auth);

// Getting the user UID might take a few seconds Serial.println("Getting User UID"); while ((auth.token.uid) == "") { Serial.print('.'); delay(1000); } // Print user UID uid = auth.token.uid.c_str(); Serial.print("User UID: "); Serial.println(uid);

// Update database path databasePath = "/UsersData/" + uid + "/readings"; state_init_firebase_was_true = true; state_init_firebase = false;`

i have already tried try/catch but it didnt catch any error.

mobizt commented 8 months ago

If you look at the comments at the bottom of the example sketch, you will see the guidelines which you can do and should not.

The blocking code of authentication waiting is not what you should not do as it stops at that block.

As I mentioned about Firebase.ready, you can run it in your setup loop until it returns true but in your loop it should contain delay(0) or yield to allow other system tasks including WiFi to work.

Using delay other than delay(0) will block the library to work as it runs by your code without a background task.

MatthiasIllmer commented 8 months ago

I think you misunderstood my issue. The code doesnt gets stuck here:
while ((auth.token.uid) == "") { Serial.print('.'); delay(1000); } The code doesn't even comes that far if the Password or email is wrong.

the code gets stuck here if the User enters a wrong Password or Email: Firebase.begin(&config, &auth);

Is there a way i can check if the User Email and Password is correct, and if its not i just return from the function and the User must enter new Login data?

Library Version: 4.4.9

mobizt commented 8 months ago

I understand your point, but you are not right even user provides the correct credential in all authentication methods.

Thid is not possible and should not use like this, and the code stops here because uid is only variable and not the return of any function that you are trying to watch it which I already said that library has no task to run in the background that is why the loop will never exit.

while ((auth.token.uid) == "") { Serial.print('.'); delay(1000); }

MatthiasIllmer commented 8 months ago

But if i Enter the right user credentials i get the UID and everything and the code also continiues to run....

Token info: type = id token (GITKit token), status = on request Token info: type = id token (GITKit token), status = ready Getting User UID User UID: xtVKl2y9t6Zbr....

mobizt commented 8 months ago

Ok, it may work in case ID token only, other authentications will not work that is why I'm not recommend.

In case of ID token, the process under the authentication method is using email and password as request payload for sign in.

The secure token (Firebase Auth ID token) will be returned if success. This ID token will used for user authentication.

If google returns the error from sign in process, it will not return the ID token for authentication.

Actually, the library uses Identity toolkit API v3 which is deprecated for verifying password with email and password provided, Which this method also provides the ID token for authentication, but it is indirect method to get ID token only (user is not actually logging into the Firebase system but can access the Firebase service using ID token).

In the next release of AsyncFirebaseClient library, this method will be replaced internally with signing method using the current identity API or Firebase Auth REST API.

For your question about account (email/password) verifying, the library is actually do this behind as I mentioned above but this process is not available for user via library function, but you can do it manually with http post to this end point.

https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=<your web API key>

With the payload

{"email":"user email", "password":"user password, "returnSecureToken":true}

Please note that, the above Google API is deprecated.

Edit: Fix the invalid identity toolkit API endpoint.

MatthiasIllmer commented 8 months ago

Thank you for your help it works now. code: `bool verifyUserCredentials(String email, String password) { // Make a direct request to Firebase Authentication API to verify credentials String payload = "{\"email\":\"" + email + "\", \"password\":\"" + password + "\", \"returnSecureToken\":true}"; String url = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=" + String(API_KEY);

HTTPClient http; http.begin(url); http.addHeader("Content-Type", "application/json");

int httpResponseCode = http.POST(payload);

if (httpResponseCode == 200) { // Successfully verified credentials return true; } else { // Failed to verify credentials Serial.print("Error verifying credentials. HTTP response code: "); Serial.println(httpResponseCode); return false; }

http.end(); }`

JonyPower commented 5 months ago

Just change the format of this line to compile without error in Arduino IDE String payload = "{\"email\":\"" + email + "\",\"password\":\"" + password + "\",\"returnSecureToken\":true}";