Skip to content

Support for Google Password Policy constraints, on FirebaseUI #2128

Open
@smlima

Description

@smlima

Step 3: Describe the problem:

I'm working on an app that uses the Google Identity platform (GIdP), and we're setting the password policy to be way more restricted than the normal 6 chars that firebaseUI has on Android (and also iOS, but will create a separate issue for it).
So it would be interesting to be able to show on the signup screen, instead of a generic error say exactly which policies are failing, because that information does come down from GIdP. Because if the user knows that the password must include an Uppercase, then he will add it, instead of going round and round, or contact support asking why he can't create an account.

I believe It would be a simple change to have a somewhat FirebaseAuthPasswordPolicyException coming down from firebase.auth, with all the required info and then check at RegisterEmailFragment for that exception and then show the failing policy elements on the UI.

We could eventually hack it on FirebaseUI of something like
`public class FirebaseAuthPasswordPolicyException extends Exception {

public static boolean instance(Exception e) {
    return e.getMessage().contains("PASSWORD_DOES_NOT_MEET_REQUIREMENTS");
}

public FirebaseAuthPasswordPolicyException(Exception e) {
    super(e);
}

public String prettyMessage() {
    String mesg = getMessage();
    int index1 = mesg.lastIndexOf("[");
    int index2 = mesg.indexOf("]");

    String errorM = mesg.substring(index1+1, index2);

    return errorM.replace(", ", "\n");
}

}
`
But I believe this should come from above, not created on the FirebaseUI.

and then on the RegisterEmailFragment class ,line 122


            protected void onFailure(@NonNull Exception e) {
                if (e instanceof FirebaseAuthWeakPasswordException) {
                    mPasswordInput.setError(getResources().getQuantityString(
                            R.plurals.fui_error_weak_password,
                            R.integer.fui_min_password_length));
                } else if (e instanceof FirebaseAuthInvalidCredentialsException) {
                    mEmailInput.setError(getString(R.string.fui_invalid_email_address));
                } else if (e instanceof FirebaseAuthAnonymousUpgradeException) {
                    IdpResponse response = ((FirebaseAuthAnonymousUpgradeException) e).getResponse();
                    mListener.onMergeFailure(response);
                } else if (e instanceof FirebaseAuthPasswordPolicyException) {
                    mPasswordInput.setError(((FirebaseAuthPasswordPolicyException) e).prettyMessage());
                } else {
                    // General error message, this branch should not be invoked but
                    // covers future API changes
                    mEmailInput.setError(getString(R.string.fui_email_account_creation_error));
                }
            }

And on the EmailProviderResponseHandler

authOperationManager.createOrLinkUserWithEmailAndPassword(getAuth(),
                getArguments(),
                email,
                password)
                .continueWithTask(new ProfileMerger(response))
                .addOnFailureListener(new TaskFailureLogger(TAG, "Error creating user"))
                .addOnSuccessListener(result -> handleSuccess(response, result))
                .addOnFailureListener(e -> {
                    if (e instanceof FirebaseAuthUserCollisionException) {
                        if (authOperationManager.canUpgradeAnonymous(getAuth(),
                                getArguments())) {
                            AuthCredential credential = EmailAuthProvider.getCredential(email,
                                    password);
                            handleMergeFailure(credential);
                        } else {
                            Log.w(TAG, "Got a collision error during a non-upgrade flow", e);

                            // Collision with existing user email without anonymous upgrade
                            // it should be very hard for the user to even get to this error
                            // due to CheckEmailFragment.
                            ProviderUtils.fetchTopProvider(getAuth(), getArguments(), email)
                                    .addOnSuccessListener(new StartWelcomeBackFlow(email))
                                    .addOnFailureListener(e1 -> setResult(Resource.forFailure(
                                            e1)));
                        }
                    } else if (FirebaseAuthPasswordPolicyException.instance(e)) {
                        setResult(Resource.forFailure(new FirebaseAuthPasswordPolicyException(e)));
                    } else {
                        setResult(Resource.forFailure(e));
                    }
                });

And this should be enough for exposing the password policy failures.

What do you think?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions