2

From the documentation of the Firebase REST API, to log in the user with email and password, just need to follow this step:

@override
  Future<UserModel> signInWithEmailAndPassword(
    String email,
    String password,
  ) async {
    final authModel = AuthModel(email: email, password: password);
    final response = await post(
      https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=YOUR_API_KEY,
      body: jsonEncode(authModel.toJson()),
    ).timeout(const Duration(seconds: AppConstants.TIMEOUT));
    if (response.statusCode == HttpStatus.ok) {
      final body = jsonDecode(response.body);
      return UserModel(
        displayName: body["displayName"],
        email: body["email"],
        uid: body["localId"],
        refreshToken: body["refreshToken"],
        idToken: body["idToken"],
      );
    } else {
      throw Exception(jsonDecode(response.body)["error"]["message"]);
    }
  }

The AuthModel:

class AuthModel {
  String email, password;
  bool returnSecureToken = true;

  AuthModel({this.email, this.password});

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> json = new Map<String, dynamic>();
    json["email"] = this.email;
    json["password"] = this.password;
    json["returnSecureToken"] = this.returnSecureToken;
    return json;
  }
}

So, the login is working fine. And then, to relogin (reauthenticate) user everytime he open the app again, you just need to use the refreshToken saved from the last login, following this step:

@override
  Future<UserModel> renewToken(String refreshToken) async {
    ExchangeTokenModel exchangeToken = ExchangeTokenModel(
      refreshToken: refreshToken,
    );
    final response = await post(
      https://securetoken.googleapis.com/v1/token?key=YOUR _API_KEY,
      body: jsonEncode(exchangeToken.toJson()),
    ).timeout(const Duration(seconds: AppConstants.TIMEOUT));
    final body = jsonDecode(response.body);
    return UserModel(
      uid: body["user_id"],
      idToken: body["id_token"],
      refreshToken: body["refresh_token"],
    );
  }

The ExchangeTokenModel:

class ExchangeTokenModel {
  final String grantType = "refresh_token";
  String refreshToken;

  ExchangeTokenModel({this.refreshToken});

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> json = new Map<String, dynamic>();
    json["grant_type"] = grantType;
    json["refresh_token"] = refreshToken;
    return json;
  }

  @override
  String toString() {
    return "ExchangeTokenModel"
        "["
        "grant_type: $grantType, "
        "refresh_token: $refreshToken"
        "]";
  }
}

So, at this point, everything is working fine. The problem is to delete user's account using the REST API. From the documentation, this step don't say this current error while trying to delete an user account:

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

The only two Common error codes are: INVALID_ID_TOKEN and USER_NOT_FOUND.

Searching on another post from stackoverflow, I found that, for security, the user should relogin again.

So, how can I solve it (not telling user to sign out and sign in again)? Because everytime when user open the app, I already reauthenticate user's idToken credential from the ExchangeToken step. Everytime user's have a VALID idToken to read/write on db, but he CAN'T delete his account due to this error. The documentation don't specify this error and don't have an enpoint to reauthenticate the user? Is that correct or it's a bug on firebase auth?

Ps.1: this error only appears if you already logged in for more than 30min/1h (don't matter if you open the app again to renew the idToken, the error persists)

Ps.2: if you sign out and sign in again, the request is successful completed

Marcello Câmara
  • 187
  • 1
  • 13

0 Answers0