Get started with Microsoft Graph in an Android app

Building apps for enterprise customers? Your app may not work if your enterprise customer turns on enterprise mobility security features like conditional device access. In this case, you may not know and your customers may experience errors.

To support all enterprise customers across all enterprise scenarios, you must use the Azure AD endpoint and manage your apps using the Azure Management Portal. For more information, see Deciding between the Azure AD and Azure AD v2.0 endpoints.

This article describes the tasks required to get an access token from the Azure AD v2.0 endpoint and call Microsoft Graph. It walks you through building the Connect Sample for Android and explains the main concepts that you implement to use Microsoft Graph in your app for Android. The article also describes how to access Microsoft Graph by using either the Microsoft Graph SDK for Android or raw REST calls.

To use Microsoft Graph in your app for Android, you need to show the Microsoft sign in page to your users, as shown in the following screenshot.

Sign in page for Microsoft accounts on Android

Don't feel like building an app? Get up and running fast by downloading the Connect Sample for Android that this article is based on.

Prerequisites

To get started, you'll need:

Configure a new project

If you have downloaded the Connect Sample for Android, skip this step.

Start a new project in Android Studio. You can leave the default values for most of the wizard, just make sure to choose the following options:

  • Target Android Devices - Phone and Tablet
    • Minimum SDK - API 16: Android 4.1 (Jelly Bean)
  • Add an Activity to Mobile - Basic Activity

This provides you with an Android project with an activity and a button that you can use to authenticate the user.

Register the application

You need to register your app on the Microsoft App Registration Portal whether you've downloaded the connect sample or created a new project.

Register an app on the Microsoft App Registration Portal. This generates the app ID that you'll use to configure the app.

  1. Sign into the Microsoft App Registration Portal using either your personal or work or school account.

  2. Choose Add an app.

Tip: If you have downloaded the Connect Sample for Android and are just creating a registration for it, uncheck Guided Setup before chosing the Create button.

  1. Enter a name for the app, and choose Create.

    For the Guided Setup flow:

    a. Choose Mobile and Desktop App to define the kind of app you are creating.

    b. Choose Android to define the mobile technology you are using.

    c. Review the introductory topic and when finished, click the Setup button at the end of the page.

    d. Follow the instructions on the Setup step to add the MSAL library to your app build.gradle.

    e. Follow the directions on the Use step to add MSAL logic to your new project

    f. On the Configure page, the portal has created a unique application ID for you. Use it to configure your app.

    For the unguided flow:

    The registration page displays, listing the properties of your app.

    a. Copy the application ID. This is the unique identifier for your app.

    b. Choose Add Platform and Native Application.

    Note: The Application Registration Portal provides a Redirect URI with a value of msalENTER_YOUR_CLIENT_ID://auth. Do not use the built-in redirect URIs. The Connect Sample for Android implements the MSAL authentication library that requires this redirect URI. If you're using a supported third-party library or the ADAL library, you must use the built-in redirect URIs.

    a. Add delegated permissions. You'll need profile, Mail.ReadWrite, Mail.Send, Files.ReadWrite, and User.ReadBasic.All.

    b. Choose Save.

Authenticate the user and get an access token

Note: If you followed the instructions in the Guided Setup flow from the application registration portal to create a new application, you can skip these steps. Go to Call Microsoft Graph using the Microsoft Graph SDK to learn more about the Graph API.

Let's walk through the Connect Sample for Android to learn about the MSAL and Microsoft Graph code we've added.

Add the dependency to app/build.gradle

Open the build.gradle file in the app module and find the following dependency:

    compile ('com.microsoft.identity.client:msal:0.1.+') {
        exclude group: 'com.android.support', module: 'appcompat-v7'
    }
    compile 'com.android.volley:volley:1.0.0'

Start the authentication flow

  1. Open the AuthenticationManager file and find the PublicClientApplication object declaration and then the instation in the getInstance method.
    private static PublicClientApplication mPublicClientApplication;
    ....

    public static synchronized AuthenticationManager getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new AuthenticationManager();
            if (mPublicClientApplication == null) {
                mPublicClientApplication = new PublicClientApplication(Connect.getInstance());
            }
        }
        return INSTANCE;
    }

  1. In the ConnectActivity class, locate the event handler for the click event of the mConnectButton. Find the onClick method and review relevant code.

    The connect method enables personally identifyable information (PII) logging, gets an instance of the sample helper class AuthenticationManager, and gets the MSAL platform object users collection. If there are no users, the new user is taken to the Azure AD authentication and authorization flow. Otherwise, an authentication token is obtained silently.

    @Override
    public void onClick(View view) {
        ....
        connect();
    }

        private void connect() {

        if (mEnablePiiLogging) {
            Logger.getInstance().setEnablePII(true);
        } else {
            Logger.getInstance().setEnablePII(false);
        }

        AuthenticationManager mgr = AuthenticationManager.getInstance();

        List<User> users = null;

        try {
            users = mgr.getPublicClient().getUsers();

            if (users != null && users.size() == 1) {
                mUser = users.get(0);
                mgr.callAcquireTokenSilent(mUser, true, this);
            } else {
                mgr.callAcquireToken(
                        this,
                        this);
            }
        } catch (MsalClientException e) {
            Log.d(TAG, "MSAL Exception Generated while getting users: " + e.toString());

        } catch (IndexOutOfBoundsException e) {
            Log.d(TAG, "User at this position does not exist: " + e.toString());
        }
    }

  1. Find the event handler that processes the Azure AD redirect response generated by Azure AD when the user closes the authintication dialog. This handler is in the ConnectActivity class.
       /**
     * Handles redirect response from https://login.microsoftonline.com/common and
     * notifies the MSAL library that the user has completed the authentication
     * dialog
     * @param requestCode
     * @param resultCode
     * @param data
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (AuthenticationManager
                .getInstance()
                .getPublicClient() != null) {
            AuthenticationManager
                    .getInstance()
                    .getPublicClient()
                    .handleInteractiveRequestRedirect(requestCode, resultCode, data);
        }
    }

  1. Find the authentication callback method that caches the authentication token that is used in Graph API calls.
    /* Callback used for interactive request.  If succeeds we use the access
         * token to call the Microsoft Graph. Does not check cache
         */
    private AuthenticationCallback getAuthInteractiveCallback() {
        return new AuthenticationCallback() {
            @Override
            public void onSuccess(AuthenticationResult authenticationResult) {
            /* Successfully got a token, call graph now */
                Log.d(TAG, "Successfully authenticated");
                Log.d(TAG, "ID Token: " + authenticationResult.getIdToken());

            /* Store the auth result */
                mAuthResult = authenticationResult;
                if (mActivityCallback != null)
                    mActivityCallback.onSuccess(mAuthResult);
            }

            @Override
            public void onError(MsalException exception) {
            /* Failed to acquireToken */
                Log.d(TAG, "Authentication failed: " + exception.toString());
                if (mActivityCallback != null)
                    mActivityCallback.onError(exception);
            }

            @Override
            public void onCancel() {
            /* User canceled the authentication */
                Log.d(TAG, "User cancelled login.");
            }
        };
    }

The connect sample app has a Connect button on the main activity. If you press the button, on first use, the app presents an authentication page using the device's browser. The next step is to handle the code that the authorization server sends to the redirect URI and exchange it for an access token.

Exchange the authorization code for an access token

You need to make your app ready to handle the authorization server response, which contains a code that you can exchange for an access token.

  1. You need to tell the Android system that Connect app can handle requests to the redirect URL configured in the application registration. To do this, open the strings.xml string resource file and add the following children to the projects <application/> element.
   <!DOCTYPE resources [
       <!ENTITY clientId "ENTER_YOUR_CLIENT_ID">
       ]>

    ...
    <string name="client_Id">&clientId;</string>
    <string name="msalPrefix">msal&clientId;</string>

The string resources are used in the AndroidManifest.xml file. The MSAL library reads the client ID at runtime and returns REST responses to the redirect URL defined for the BrowserTabActivity.

        <uses-sdk tools:overrideLibrary="com.microsoft.identity.msal" />
        <application ...>
            ...
           <activity
               android:name="com.microsoft.identity.client.BrowserTabActivity">
               <intent-filter>
                   <action android:name="android.intent.action.VIEW" />
                   <category android:name="android.intent.category.DEFAULT" />
                   <category android:name="android.intent.category.BROWSABLE" />
                   <data android:scheme="@string/msalPrefix"
                       android:host="auth" />
               </intent-filter>
           </activity>
           <meta-data
               android:name="https://login.microsoftonline.com/common"
               android:value="authority string"/>
           <meta-data
               android:name="com.microsoft.identity.client.ClientId"
               android:value="@string/client_Id"/>
        </application>
  1. The MSAL library needs access to the application Id assigned by the registration portal. The MSAL library refers to the application Id as the "Client Id". It gets the application Id (Client Id) from the application context that you pass in the library constructor.

Note: You can also provide the client Id at run-time by passing a string parameter to the constructor.

  1. The activity is invoked when the authorization server sends a response. Request an access token with the response from the authorization server. Go to your AuthenticationManager and find the following code in the class.
    /**
     * Authenticates the user and lets the user authorize the app for the requested permissions.
     * An authentication token is returned via the getAuthInteractiveCalback method
     * @param activity
     * @param authenticationCallback
     */
    public void connect(Activity activity, final MSALAuthenticationCallback authenticationCallback){
        mActivityCallback = authenticationCallback;
        mPublicClientApplication.acquireToken(
                activity, Constants.SCOPES, getAuthInteractiveCallback());
    }


     /* Callback used for interactive request.  If succeeds we use the access
         * token to call the Microsoft Graph. Does not check cache
         */
    private AuthenticationCallback getAuthInteractiveCallback() {
        return new AuthenticationCallback() {
            @Override
            public void onSuccess(AuthenticationResult authenticationResult) {
            /* Successfully got a token, call graph now */
                Log.d(TAG, "Successfully authenticated");
                Log.d(TAG, "ID Token: " + authenticationResult.getIdToken());

            /* Store the auth result */
                mAuthResult = authenticationResult;
                if (mAct