Anonymous Authentication using the Firebase SDK

Revision as of 19:18, 14 August 2017 by Neil (Talk | contribs) (Created page with "All of the Firebase authentication examples covered in the book so far require that the user provide an identity in the form of an email address, phone number or third party a...")

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Revision as of 19:18, 14 August 2017 by Neil (Talk | contribs) (Created page with "All of the Firebase authentication examples covered in the book so far require that the user provide an identity in the form of an email address, phone number or third party a...")

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

All of the Firebase authentication examples covered in the book so far require that the user provide an identity in the form of an email address, phone number or third party account such as Facebook before gaining access to restricted content or features. Situations might arise, however, where having the user authenticate with an identity is not the first priority. A retail app, for example, might allow a user to browse products and place potential items in a shopping cart prior to purchase. In this scenario, the app will need some temporary way to identify the user in order to keep track of the items in the shopping cart. Only at the point of checkout would the user be required to create a permanent account using an established identity or email address.

To address this requirement, Firebase provides the ability to perform anonymous authentications, a topic which will be covered in the rest of this chapter.

Anonymous Firebase Authentication

As the name suggests, anonymous authentication provides a way for the user to authenticate using a temporary anonymous identity. This allows users to gain access to an app without the need to go through the process of authenticating with an identity. Anonymous authentication can be performed with a single button click, or even in the background when the user launches the app.

Once signed in anonymously, the user is assigned a temporary account which can be used by the app when performing tasks such as storing data for the user during the current session. Once the user signs out of the anonymous account, the anonymous account continues to exist within the Firebase account database, but is unreachable by that, or any other user. If the same user signs in anonymously again, an entirely new anonymous account will be created and assigned to the user for the current app session.

If the user wishes to create a non-temporary account and continue using the same Firebase stored data, the anonymous account must be associated with a permanent email or third-party authentication account. This will typically involve prompting the user to authenticate using an identity using one or more of the options outlined in preceding chapters and then linking that account to the user’s anonymous account. Going forward, the user will be able to sign in using the permanent account while continuing to have access to any data associated with the anonymous account.

As will be revealed in the remainder of this chapter, anonymous authentication is a straightforward process that makes use of many of the Firebase authentication concepts outlined in earlier chapters.

In fact, implementation is almost identical to email based authentication except the user is not required to enter an email and password and the signInAnonymously() method is called in place of signInWithEmailAndPassword().

The rest of this chapter is dedicated to the task of creating an example project that implements Firebase anonymous authentication. Once these basics have been covered, the next chapter (entitled Linking and Unlinking Firebase Authentication Providers) will cover the topic of linking Firebase accounts.

Creating the AnonAuth Project

Begin by launching Android Studio and selecting the Start a new Android Studio project quick start option from the welcome screen. Within the new project dialog, enter AnonAuth into the Application name field and your domain as the Company Domain setting before clicking on the Next button.

On the form factors screen, enable the Phone and Tablet option and set the minimum SDK to API 16: Android 4.1 (Jellybean). Continue to proceed through the screens, requesting the creation of an Empty Activity named AnonAuthActivity with a corresponding layout named activity_anon_auth.


Connecting the Project to Firebase

As with previous examples, the project will need to be connected to Firebase. Within Android Studio, use the Tools -> Firebase menu to display the Firebase assistant panel, locate and click on the Authentication category, select the Email and password authentication link and then click on the Connect to Firebase button to display the Firebase connection dialog.

Choose the option to store the app in an existing Firebase project and select the Firebase Examples project created in the beginning of the book. With the project’s Firebase connection established, refer to the Firebase assistant panel once again, this time clicking on the Add Firebase Authentication to your app button. A dialog will appear outlining the changes that will be made to the project build configuration to enable Firebase authentication. Click on the Accept Changes button to commit the changes to the project configuration.

Enabling Anonymous Authentication

Before anonymous authentication can be used it must first be enabled for the project within the Firebase console. Open the Firebase console in a browser window, select the Firebase Examples project and display the Authentication screen. Select the Sign-in Method tab and edit the setting for Anonymous authentication. In the settings panel, change the Enable switch to the on position:


[[File:]]

Figure 17-1


Designing the User Interface Layout

The user interface layout is going to consist of two EditText fields, two TextViews and three Buttons. Begin by loading the activity_anon_auth.xml file into the layout editor tool and turning off Autoconnect mode.

Add Email and Password EditText objects to the layout together with the TextView and Button widgets to the layout so that it resembles the layout shown in Figure 17-2. Shift-click on the TextView buttons so that both are selected and increase the textSize attribute in the properties window to 18sp:


[[File:]]

Figure 17-2


Assign IDs of emailText and passwordText to the two EditText objects and userText and statusText to the TextView widgets. Select the uppermost of the three buttons and change the ID to softButton.

Change the text on the three buttons to Anonymous Sign-in, Sign In and Sign Out. Configure onClick properties so that the buttons are configured to call methods named softButtonClick, signIn and signOut respectively.

With the view components added to the layout it is now time to add some constraints. Click in the upper right-hand corner of the layout canvas and drag the resulting rectangle until it encompasses all of the widgets. On releasing the mouse button, all four widgets should now be selected. Right-click on the ImageView object and, from the resulting menu, select the Center Horizontally menu option. Repeat this step once again, this time selecting the Center Vertically menu option.


[[File:]]

Figure 17-3


The uppermost of the three buttons is going to be implemented as a dual mode button. In the default mode, clicking the button will sign the user into the app anonymously. After the user has been assigned an anonymous account, the button will change to display text which reads Create an Account which, when clicked, will create an email/password based account for the user and link it to the anonymous account. The two remaining buttons will perform standard email and password authentication sign-in and sign-out operations.

Accessing the FirebaseAuth Instance

As with all forms of Firebase SDK authentication, the two key components are the FirebaseAuth instance and the authentication state listener. The next step in implementing Firebase anonymous authentication is to obtain a reference to the FirebaseAuth instance. Within Android Studio, edit the AnonAuthActivity.java file to obtain a reference to the FirebaseAuth instance and to perform some basic initialization tasks:

package com.ebookfrenzy.anonauth;

import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.AuthCredential;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.EmailAuthProvider;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseAuthInvalidCredentialsException;
import com.google.firebase.auth.FirebaseAuthInvalidUserException;
import com.google.firebase.auth.FirebaseUser;

public class AnonAuthActivity extends AppCompatActivity {

    private static final int ANON_MODE = 100;
    private static final int CREATE_MODE = 101;
    private int buttonMode = ANON_MODE;

    private static final String TAG = "AnonAuth";
    private TextView userText;
    private TextView statusText;
    private EditText emailText;
    private EditText passwordText;
    private Button softButton;

    private FirebaseAuth fbAuth;
    private FirebaseAuth.AuthStateListener authListener;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_anon_auth);

        userText = (TextView) findViewById(R.id.userText);
        statusText = (TextView) findViewById(R.id.statusText);
        emailText = (EditText) findViewById(R.id.emailText);
        passwordText = (EditText) findViewById(R.id.passwordText);
        softButton = (Button) findViewById(R.id.softButton);

        fbAuth = FirebaseAuth.getInstance();
    }
.
.
}

Adding the Authentication State Listener

With the AnonAuthActivity.java file still open in the Android Studio code editor, further modify the onCreate() method to declare the authentication state listener method:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_anon_auth_sdk);

    userText = (TextView) findViewById(R.id.userText);
    statusText = (TextView) findViewById(R.id.statusText);
    emailText = (EditText) findViewById(R.id.emailText);
    passwordText = (EditText) findViewById(R.id.passwordText);
    softButton = (Button) findViewById(R.id.softButton);

    fbAuth = FirebaseAuth.getInstance();

    authListener = new FirebaseAuth.AuthStateListener() {
        @Override
        public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {

            FirebaseUser user = firebaseAuth.getCurrentUser();

            if (user != null) {
                userText.setText(user.getEmail());
                statusText.setText("Signed In");

            } else {
                userText.setText("");
                statusText.setText("Signed Out");
                softButton.setText("Anonymous Sign-in");
                buttonMode = ANON_MODE;
            }
        }
    };
}

The authentication state listener tests for a valid user account and updates the user interface accordingly. If no valid user is found, the code assumes that the user has signed out and reverts the softButton instance to anonymous sign-in mode.

Within the AnonAuthActivity.java file, override the onStart() and onStop() methods to add and remove the listener:

@Override
public void onStart() {
    super.onStart();
    fbAuth.addAuthStateListener(authListener);
}

@Override
public void onStop() {
    super.onStop();
    if (authListener != null) {
        fbAuth.removeAuthStateListener(authListener);
    }
} 

Performing the Anonymous Authentication

The softButton is configured to call a method named softButtonClicked() when tapped by the user. It is the responsibility of this method to identify whether the button is currently in anonymous sign-in or account creation mode and then call the appropriate method to complete the authentication task. Implement this method now within the AnonAuthActivity.java file so that it reads as follows:

public void softButtonClick(View view) {
    if (buttonMode == ANON_MODE) {
        anonSignIn();
    } else {
        createAccount();
    }
}

When the button is in anonymous sign-in mode, the anonSignIn() method is called, the code for which must now be added to the AnonAuthActivity class:

public void anonSignIn() {
    fbAuth.signInAnonymously()
            .addOnCompleteListener(this, 
			new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    
                    if (!task.isSuccessful()) {
                        Toast.makeText(AnonAuthActivity.this, 
				"Authentication failed. " 
					+ task.getException(),
                                Toast.LENGTH_SHORT).show();
                    } else {
                        softButton.setText("Create an Account");
                        buttonMode = CREATE_MODE;
                    }
                }
            });
}

The anonSignIn() method calls the signInAnonymously() method of the FirebaseAuth instance and uses a completion listener to receive the result of the authentication. If the authentication fails, a message is displayed to the user. In the event of a successful anonymous authentication, the softButton instance is switch to account creation mode. The successful authentication will have also triggered a call to the authentication state listener causing the user interface to be updated accordingly.

The code for the createAccount() method will be implemented in the next chapter as part of the account linking process. For now, add a template for this method to the class file to avoid errors during the project compilation.

public void createAccount() {
        
}

Signing Out

The final task before testing the project is to add the signOut() method as follows:

public void signOut(View view) {
    fbAuth.signOut();
}

Testing the Project

Build and run the app and tap the anonymous sign-in button. After a short delay the status TextView widget should update to indicate that the user is signed in and the soft button should switch to account creation mode.

Within a browser window, navigate to the Authentication page of the Firebase console and select the option to list user accounts. In addition to any previously added accounts, a new anonymous account should now also be listed as illustrated in Figure 17-4:


[[File:]]

Figure 17-4


This account will be assigned to the user until the user signs out. To demonstrate the transient nature of the user’s association with this anonymous account, click the Sign Out button then perform a second anonymous sign-in. Return to the Firebase console, refresh the user account list and note that the user now has an entirely new anonymous account.

To preserve the user’s association with an anonymous account, together with any data stored within Firebase, the user must first authenticate using either an email address or a third-party authentication provider. Once that account has been established it must be linked to the anonymous account, a topic that will be covered in the next chapter.

Summary

In addition to providing authentication using an email address and password or an account from a third-party platform such as Twitter and Facebook, Firebase also allows users to be authenticated anonymously.

Anonymous authentication allows the user to be temporarily registered as an app user without the need to enter account credentials. The user’s association to an anonymous account is temporary and is lost when the user either signs out or the app exits. The only way to preserve the association between the anonymous account and the user is to register a permanent account and then link that account to the anonymous account.