Android - Facebook Login

View on Github

Android - Facebook Login

Gravatar for luciano.balmaceda@auth0.com
By Luciano Balmaceda

This tutorial demonstrates how to add user login to an Android application using native Facebook Login. We recommend that you log in to follow this quickstart with examples configured for your account.

I want to explore a sample app

2 minutes

Get a sample configured with your account settings or check it out on Github.

View on Github
System requirements: Android Studio 3.6.1 | Android SDK 25 | Emulator - Nexus 5X - Android 6.0

This tutorial describes how to implement login with the Facebook SDK. ​

Before You Start

  • Install and configure the Facebook Login SDK. You’ll also go through the process of creating a Facebook app in https://developers.facebook.com. When you finish this step, you should have a mobile app running with Facebook Login integrated.
  • Configure your Auth0 application in the dashboard to use Facebook Native Sign In. See Add Facebook Login to Native Apps. When you finish this step, your application will be able to implement Facebook Native Login.

Set up the “Continue with Facebook” button

This guide will help you add authentication with Auth0 to the application you built in the first step.

Request Facebook permissions

Your application is already able to sign in with Facebook. However, to ensure you have a rich user profile, you need to update the permissions with which the Facebook Login Button was set up.

Set the requested permissions to public_profile and email. This way, the user email will also be included as part of the response, provided the access request is accepted by the user.

loginButton.setPermissions(Arrays.asList("public_profile", "email"));

Now, to kick off the authentication process with Auth0, create a new method in which you will prepare the payload to be sent.

You will make use of a small interface to handle our internal callbacks.

In the sample, the method was named performLogin and the interface SimpleCallback. Go ahead and add both.

private void performLogin(@NonNull final AccessToken accessToken) {
  // TODO
}

private interface SimpleCallback<T> {
    void onResult(@NonNull T result);

    void onError(@NonNull Throwable cause);
}

Now, call the method from the Facebook login callback's onSuccess method.

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_login);

    Auth0 account = new Auth0(getString(R.string.com_auth0_client_id), getString(R.string.com_auth0_domain));
    auth0Client = new AuthenticationAPIClient(account);

    fbCallbackManager = CallbackManager.Factory.create();

    LoginButton loginButton = findViewById(R.id.login_button);
    loginButton.setPermissions(FACEBOOK_PERMISSIONS);
    loginButton.registerCallback(fbCallbackManager, new FacebookCallback<LoginResult>() {
        @Override
        public void onSuccess(LoginResult result) {
            //1. Logged in to Facebook
            AccessToken accessToken = result.getAccessToken();
            performLogin(accessToken);
        }

        @Override
        public void onCancel() {
            //User closed the dialog. Safe to ignore
        }

        @Override
        public void onError(FacebookException error) {
            //Handle Facebook authentication error
        }
    });
}

Integrate Facebook

When you sign in with Facebook at Auth0, the backend will perform some checks in the background to ensure the user is who they say they are. To achieve this, it needs to be provided with a Session Access Token.

Furthermore, if a user needs to be created on Auth0 to represent this Facebook user, the backend will require some of their information, such as their name, last name, and email. The email, if provided, will be flagged as non-verified on the Auth0 user profile.

To obtain the Session Access Token and the user profile, two additional requests need to be made against the Facebook API.

Fetch Facebook session Access Token

Make a new GET request against the Facebook API's /oauth/access_token endpoint. Use the following query parameters:

  • grant_type: fb_attenuate_token.
  • fb_exchange_token: the access token received upon login.
  • client_id: your App ID. This value comes from the Facebook Developer's dashboard and should already be in use in your application if you have integrated Facebook Login successfully.

Put the logic from this step in its own method. You will be calling it later from the previously-added method.

The sample uses the Facebook SDK's GraphRequest class to perform this request.

private void fetchSessionToken(String token, final SimpleCallback<String> callback) {
    Bundle params = new Bundle();
    params.putString("grant_type", "fb_attenuate_token");
    params.putString("fb_exchange_token", token);
    params.putString("client_id", getString(R.string.facebook_app_id));

    GraphRequest request = new GraphRequest();
    request.setParameters(params);
    request.setGraphPath("oauth/access_token");
    request.setCallback(new GraphRequest.Callback() {
        @Override
        public void onCompleted(GraphResponse response) {
            FacebookRequestError error = response.getError();
            if (error != null) {
                //Failed to fetch session token
                callback.onError(error.getException());
                return;
            }
            try {
                String fbSessionToken = response.getJSONObject().getString("access_token");
                callback.onResult(fbSessionToken);
            } catch (JSONException e) {
                //Failed to parse session token
                callback.onError(e);
            }
        }
    });
    request.executeAsync();
}

Fetch Facebook user profile

Now make another GET request, just like in the step above. The endpoint path will be the User ID value from the Facebook login result (for example, /904636746222815). Use the following parameters:

  • access_token: the access token received upon login.
  • fields: the fields from the user profile that you'd like to get back in the response. These are directly tied to the Facebook Login Button permissions that were configured at the beginning. When a permission is optional, the user must first consent to give access to it. For the purpose of signing up a user at Auth0, their full name and email will suffice.
private void fetchUserProfile(String token, String userId, final SimpleCallback<String> callback) {
    Bundle params = new Bundle();
    params.putString("access_token", token);
    params.putString("fields", "first_name,last_name,email");

    GraphRequest request = new GraphRequest();
    request.setParameters(params);
    request.setGraphPath(userId);
    request.setCallback(new GraphRequest.Callback() {
        @Override
        public void onCompleted(GraphResponse response) {
            FacebookRequestError error = response.getError();
            if (error != null) {
                //Failed to fetch user profile
                callback.onError(error.getException());
                return;
            }
            //Handle back the profile as received
            callback.onResult(response.getRawResponse());
        }
    });
    request.executeAsync();
}

Integrate Auth0

Now that the required artifacts have been obtained, you are ready to trade them for Auth0 user credentials, such as the ID and Access Tokens. But first, you must set up the Auth0 SDK to make that last request.

Get your application keys

Go to the Applications section of the Auth0 Dashboard and select the existing application in which you enabled Sign in with Facebook. If you need help with this step, please check the requirements section at the top of this article.

Copy the Domain and Client ID values from the application settings page. These are required by the SDK.

Create two new resources in your Android application's strings.xml file to store them. The name of the keys must match the ones used below:

<resources>
    <string name="com_auth0_domain">{TENANT}</string>
    <string name="com_auth0_client_id">{CLIENT_ID}</string>
</resources>

Install the Auth0 SDK

In your Android application, add this line to the app/build.gradle file:

dependencies {
    implementation 'com.auth0.android:auth0:1.+'
}

Now is time to run the Gradle Sync task to refresh the project and its dependencies.

Web Authentication

If your application does not plan to make use of the Web Authentication module provided by the SDK, you will need to remove the unused activity from the AndroidManifest.xml file to prevent Manifest Placeholder issues. This can be achieved by adding an activity declaration and annotating it with tools:node="remove".

<application>
  <!-- Add the activity declaration line below -->
   <activity
    android:name="com.auth0.android.provider.AuthenticationActivity"
    tools:node="remove" />
  
</application>

However, if you do plan to support Web Authentication, head over here to learn how to declare the Manifest Placeholders.

Exchange the received data for Auth0 tokens

The SDK must be instantiated before use. Define a field at the class level and initialize it on the onCreate method. Note how the credentials defined in the step above are passed to the Auth0 constructor and then a new instance of the AuthenticationAPIClient is created with it.

private AuthenticationAPIClient auth0Client;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_login);

    Auth0 account = new Auth0(getString(R.string.com_auth0_client_id), getString(R.string.com_auth0_domain));
    auth0Client = new AuthenticationAPIClient(account);

    //...
}

Create the method that will hold the logic to exchange the two obtained artifacts for Auth0 user credentials. In the sample, this method is named exchangeTokens.

The API client declares the method loginWithNativeSocialToken that receives a token and a subject type. The former corresponds to the session token, and the latter indicates what type of connection the backend will attempt to authenticate with. For native Facebook Login, you will use the following value:

"http://auth0.com/oauth/token-type/facebook-info-session-access-token"

Other values that need to be configured are the user profile (using the user_profile key) and the scope you request the Auth0 tokens contain.

private void exchangeTokens(@NonNull String sessionToken, @NonNull String userProfile, @NonNull final SimpleCallback<Credentials> callback) {
    Map<String, Object> params = new HashMap<>();
    params.put("user_profile", userProfile);

    auth0Client.loginWithNativeSocialToken(sessionToken, "http://auth0.com/oauth/token-type/facebook-info-session-access-token")
            .setScope("openid email profile offline_access")
            .addAuthenticationParameters(params)
            .start(new BaseCallback<Credentials, AuthenticationException>() {
                @Override
                public void onSuccess(Credentials credentials) {
                    callback.onResult(credentials);
                }

                @Override
                public void onFailure(AuthenticationException error) {
                    callback.onError(error);
                }
            });
}

It's a good practice to keep all the values that you know won't change as constants at the top of the class. The sample makes use of constants for the subject token type, the Facebook permissions, and the Auth0 scopes. You can read more about Auth0 scopes in the dedicated article.

Now that every step is defined in its own method, it's time to put everything together inside the performLogin method.

private void performLogin(@NonNull final AccessToken accessToken) {
    final String token = accessToken.getToken();
    fetchSessionToken(token, new SimpleCallback<String>() {
        @Override
        public void onResult(@NonNull final String sessionToken) {
            //2. Obtained the Facebook session token
            fetchUserProfile(token, accessToken.getUserId(), new SimpleCallback<String>() {

                @Override
                public void onResult(@NonNull String jsonProfile) {
                    //3. Obtained the Facebook user profile
                    exchangeTokens(sessionToken, jsonProfile, new SimpleCallback<Credentials>() {

                        @Override
                        public void onResult(@NonNull Credentials credentials) {
                            /*
                            *  4. Logged in!
                            *     Use access token to call API
                            *     or consume ID token locally
                            */
                        }

                        @Override
                        public void onError(@NonNull Throwable cause) {
                            //Handle token exchange error
                        }
                    });
                }

                @Override
                public void onError(@NonNull Throwable cause) {
                    //Handle profile request error
                }
            });
        }

        @Override
        public void onError(@NonNull Throwable cause) {
            //Handle session token request error
        }
    });
}

If everything went well, you should now be able to authenticate natively with the Facebook Login SDK. This means that if the Facebook app is installed on the device, the authentication will be handled via the application and not a browser app.

Use Auth0 for FREE