How to provide user login with a username and NOT an email?

Firebase Authentication

Firebase Authentication Problem Overview


I'd like to use Firebase for my web app that is for people with dementia in a care home. They do not have email or social network accounts so will need a simple username / password sign up / sign in.

What is the easiest way to do this? From what I can see in the docs I'd have to use a custom auth flow but I do not have an existing auth server.

If I do need ot do this what is the easiest way to provide the token? In Azure there is Functions and AWS has Lambda but I see nothing here is Firebase

Firebase Authentication Solutions


Solution 1 - Firebase Authentication

You are correct that username/password sign-in is not supported natively in Firebase Auth at this moment.

You can implement a custom provider as shown in this example. This allows you to meet any custom requirements, but is admittedly a bit more involved than using the built-in providers. There is an example of this here that you can use as a starting point.

A workaround you could take without needing to use custom auth with another backend is to accept usernames in your UI, but on the underlying logic, append "@yourowndomain.com" before calling the functions to sign up or sign in with email.

So you would be using email/password authentication, mapping <username> to <username>@yourowndomain.com

Solution 2 - Firebase Authentication

You can use sign in with custom token

Firebase gives you complete control over authentication by allowing you to authenticate users or devices using secure JSON Web Tokens (JWTs). You generate these tokens on your server, pass them back to a client device, and then use them to authenticate via the signInWithCustomToken() method.

  1. You need to save username and password in your database or rtdb or firestore
  2. When user touch the login button, client will send username and password to your backend. If the username and password correct, generate custom token and send it back to the client
  3. Client then can login with custom token from the server using signInWithCustomToken() method

More detail can be read in this documentation

Solution 3 - Firebase Authentication

Appending a dummy domain at end is a kind of a patch up and should be avoided. To enable username login just follow these simple steps.

Sign Up

During sign up take the userid , email and password . Register the user with normal email and password. On Success of it save the email against the user_id in a separate node(branch).

mButtonSignUp.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if(isValid()){
                mProgressBar.setVisibility(View.VISIBLE);
                final String userId = mEditTextUserId.getText().toString();
                final String emailId = mEditTextEmail.getText().toString() ;
                String password = mEditTextPassword.getText().toString() ;
                firebaseRef.createUser(emailId, password, new Firebase.ResultHandler() {
                    @Override
                    public void onSuccess() {
                       firebaseRef.child("user_ids").child(userId).setValue(emailId);
                       Toast.makeText(getBaseContext(),"You are successfully registered ",Toast.LENGTH_SHORT).show();
                       mProgressBar.setVisibility(View.GONE);
                    }

                    @Override
                    public void onError(FirebaseError firebaseError) {
                        mProgressBar.setVisibility(View.GONE);
                        Toast.makeText(getBaseContext(),firebaseError.toString(),Toast.LENGTH_SHORT).show();
                    }
                });

            }
        }
    });

Database

Database structure will look like this

enter image description here

Login

Check if the user has entered an email or userId. If it is a email id then directly perform login with it otherwise fetch the email id associated with the username and perform login.

    Button buttonLogIn = (Button)findViewById(R.id.button_login);
    buttonLogIn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {             
        
            mProgressBar.setVisibility(View.VISIBLE);
            String username = mEditTextEmail.getText().toString() ;
            final String password = mEditTextPassWord.getText().toString() ;
            
          //  Check if it is an email or not
             if(android.util.Patterns.EMAIL_ADDRESS.matcher(username).matches())                 {
                performLogin(username,password);
            }else{
              //get the emailId associated with the username      
        firebaseRef.child("user_ids").child(username)
              .addListenerForSingleValueEvent(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        if(dataSnapshot!=null){
                            String userEmail =	dataSnapshot.getValue(String.class);
                            performLogin(userEmail,password);
                        }
                    }

                    @Override
                    public void onCancelled(FirebaseError firebaseError) {
                        //Handle Error
                    }
                });
            }

        }
    });

private void performLogin(String emailId, String password) {
    firebaseRef.authWithPassword(emailId,password, new Firebase.AuthResultHandler() {
        @Override
        public void onAuthenticated(AuthData authData) {
            uid = authData.getUid() ;
            Toast.makeText(getBaseContext(), authData.toString(), Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onAuthenticationError(FirebaseError firebaseError) {
            Toast.makeText(getBaseContext(), firebaseError.toString(), Toast.LENGTH_SHORT).show();
        }
    });
}

Solution 4 - Firebase Authentication

You may use Alfonso's solution as well. And where you need a real e-mail, you can set an textfield for an e-mail when the user registers and you can keep it in your database and you can use it.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSteve LeeView Question on Stackoverflow
Solution 1 - Firebase AuthenticationAlfonso Gomez Jordana ManasView Answer on Stackoverflow
Solution 2 - Firebase AuthenticationfarukView Answer on Stackoverflow
Solution 3 - Firebase AuthenticationSaurabh PadwekarView Answer on Stackoverflow
Solution 4 - Firebase AuthenticationAlperView Answer on Stackoverflow