Quickstart: Sign in users and call the Microsoft Graph API from a mobile application

In this quickstart, you download and run a code sample that demonstrates how an Android application can sign in users and get an access token to call the Microsoft Graph API.

See How the sample works for an illustration.

Applications must be represented by an app object in Azure Active Directory so that the Microsoft identity platform can provide tokens to your application.

Prerequisites

Step 1: Get the sample app

Download the code.

Step 2: Run the sample app

Select your emulator, or physical device, from Android Studio's available devices dropdown and run the app.

The sample app starts on the Single Account Mode screen. A default scope, user.read, is provided by default, which is used when reading your own profile data during the Microsoft Graph API call. The URL for the Microsoft Graph API call is provided by default. You can change both of these if you wish.

MSAL sample app showing single and multiple account usage

Use the app menu to change between single and multiple account modes.

In single account mode, sign in using a work or home account:

  1. Select Get graph data interactively to prompt the user for their credentials. You'll see the output from the call to the Microsoft Graph API in the bottom of the screen.
  2. Once signed in, select Get graph data silently to make a call to the Microsoft Graph API without prompting the user for credentials again. You'll see the output from the call to the Microsoft Graph API in the bottom of the screen.

In multiple account mode, you can repeat the same steps. Additionally, you can remove the signed-in account, which also removes the cached tokens for that account.

How the sample works

Screenshot of the sample app

The code is organized into fragments that show how to write a single and multiple accounts MSAL app. The code files are organized as follows:

File Demonstrates
MainActivity Manages the UI
MSGraphRequestWrapper Calls the Microsoft Graph API using the token provided by MSAL
MultipleAccountModeFragment Initializes a multi-account application, loads a user account, and gets a token to call the Microsoft Graph API
SingleAccountModeFragment Initializes a single-account application, loads a user account, and gets a token to call the Microsoft Graph API
res/auth_config_multiple_account.json The multiple account configuration file
res/auth_config_single_account.json The single account configuration file
Gradle Scripts/build.grade (Module:app) The MSAL library dependencies are added here

We'll now look at these files in more detail and call out the MSAL-specific code in each.

Adding MSAL to the app

MSAL (com.microsoft.identity.client) is the library used to sign in users and request tokens used to access an API protected by Microsoft identity platform. Gradle 3.0+ installs the library when you add the following to Gradle Scripts > build.gradle (Module: app) under Dependencies:

dependencies {
    ...
    implementation 'com.microsoft.identity.client:msal:2.+'
    ...
}

This instructs Gradle to download and build MSAL from maven central.

You must also add references to maven to the allprojects > repositories portion of the build.gradle (Module: app) like so:

allprojects {
    repositories {
        mavenCentral()
        google()
        mavenLocal()
        maven {
            url 'https://pkgs.dev.azure.com/MicrosoftDeviceSDK/DuoSDK-Public/_packaging/Duo-SDK-Feed/maven/v1'
        }
        maven {
            name "vsts-maven-adal-android"
            url "https://identitydivision.pkgs.visualstudio.com/_packaging/AndroidADAL/maven/v1"
            credentials {
                username System.getenv("ENV_VSTS_MVN_ANDROIDADAL_USERNAME") != null ? System.getenv("ENV_VSTS_MVN_ANDROIDADAL_USERNAME") : project.findProperty("vstsUsername")
                password System.getenv("ENV_VSTS_MVN_ANDROIDADAL_ACCESSTOKEN") != null ? System.getenv("ENV_VSTS_MVN_ANDROIDADAL_ACCESSTOKEN") : project.findProperty("vstsMavenAccessToken")
            }
        }
        jcenter()
    }
}

MSAL imports

The imports that are relevant to the MSAL library are com.microsoft.identity.client.*. For example, you'll see import com.microsoft.identity.client.PublicClientApplication; which is the namespace for the PublicClientApplication class, which represents your public client application.

SingleAccountModeFragment.java

This file demonstrates how to create a single account MSAL app and call a Microsoft Graph API.

Single account apps are only used by a single user. For example, you might just have one account that you sign into your mapping app with.

Single account MSAL initialization

In auth_config_single_account.json, in onCreateView(), a single account PublicClientApplication is created using the config information stored in the auth_config_single_account.json file. This is how you initialize the MSAL library for use in a single-account MSAL app:

...
// Creates a PublicClientApplication object with res/raw/auth_config_single_account.json
PublicClientApplication.createSingleAccountPublicClientApplication(getContext(),
        R.raw.auth_config_single_account,
        new IPublicClientApplication.ISingleAccountApplicationCreatedListener() {
            @Override
            public void onCreated(ISingleAccountPublicClientApplication application) {
                /**
                 * This test app assumes that the app is only going to support one account.
                 * This requires "account_mode" : "SINGLE" in the config json file.
                 **/
                mSingleAccountApp = application;
                loadAccount();
            }

            @Override
            public void onError(MsalException exception) {
                displayError(exception);
            }
        });

Sign in a user

In SingleAccountModeFragment.java, the code to sign in a user is in initializeUI(), in the signInButton click handler.

Call signIn() before trying to acquire tokens. signIn() behaves as though acquireToken() is called, resulting in an interactive prompt for the user to sign in.

Signing in a user is an asynchronous operation. A callback is passed that calls the Microsoft Graph API and update the UI once the user signs in:

mSingleAccountApp.signIn(getActivity(), null, getScopes(), getAuthInteractiveCallback());

Sign out a user

In SingleAccountModeFragment.java, the code to sign out a user is in initializeUI(), in the signOutButton click handler. Signing a user out is an asynchronous operation. Signing the user out also clears the token cache for that account. A callback is created to update the UI once the user account is signed out:

mSingleAccountApp.signOut(new ISingleAccountPublicClientApplication.SignOutCallback() {
    @Override
    public void onSignOut() {
        updateUI(null);
        performOperationOnSignOut();
    }

    @Override
    public void onError(@NonNull MsalException exception) {
        displayError(exception);
    }
});

Get a token interactively or silently

To present the fewest number of prompts to the user, you'll typically get a token silently. Then, if there's an error, attempt to get to token interactively. The first time the app calls signIn(), it effectively acts as a call to acquireToken(), which will prompt the user for credentials.

Some situations when the user may be prompted to select their account, enter their credentials, or consent to the permissions your app has requested are:

  • The first time the user signs in to the application
  • If a user resets their password, they'll need to enter their credentials
  • If consent is revoked
  • If your app explicitly requires consent
  • When your application is requesting access to a resource for the first time
  • When MFA or other Conditional Access policies are required

The code to get a token interactively, that is with UI that will involve the user, is in SingleAccountModeFragment.java, in initializeUI(), in the callGraphApiInteractiveButton click handler:

/**
 * If acquireTokenSilent() returns an error that requires an interaction (MsalUiRequiredException),
 * invoke acquireToken() to have the user resolve the interrupt interactively.
 *
 * Some example scenarios are
 *  - password change
 *  - the resource you're acquiring a token for has a stricter set of requirement than your Single Sign-On refresh token.
 *  - you're introducing a new scope which the user has never consented for.
 **/
mSingleAccountApp.acquireToken(getActivity(), getScopes(), getAuthInteractiveCallback());

If the user has already signed in, acquireTokenSilentAsync() allows apps to request tokens silently as shown in initializeUI(), in the callGraphApiSilentButton click handler:

/**
 * Once you've signed the user in,
 * you can perform acquireTokenSilent to obtain resources without interrupting the user.
 **/
  mSingleAccountApp.acquireTokenSilentAsync(getScopes(), AUTHORITY, getAuthSilentCallback());

Load an account

The code to load an account is in SingleAccountModeFragment.java in loadAccount(). Loading the user's account is an asynchronous operation, so callbacks to handle when the account loads, changes, or an error occurs is passed to MSAL. The following code also handles onAccountChanged(), which occurs when an account is removed, the user changes to another account, and so on.

private void loadAccount() {
    ...

    mSingleAccountApp.getCurrentAccountAsync(new ISingleAccountPublicClientApplication.CurrentAccountCallback() {
        @Override
        public void onAccountLoaded(@Nullable IAccount activeAccount) {
            // You can use the account data to update your UI or your app database.
            updateUI(activeAccount);
        }

        @Override
        public void onAccountChanged(@Nullable IAccount priorAccount, @Nullable IAccount currentAccount) {
            if (currentAccount == null) {
                // Perform a cleanup task as the signed-in account changed.
                performOperationOnSignOut();
            }
        }

        @Override
        public void onError(@NonNull MsalException exception) {
            displayError(exception);
        }
    });

Call Microsoft Graph

When a user is signed in, the call to Microsoft Graph is made via an HTTP request by callGraphAPI() which is defined in SingleAccountModeFragment.java. This function is a wrapper that simplifies the sample by doing some tasks such as getting the access token from the authenticationResult and packaging the call to the MSGraphRequestWrapper, and displaying the results of the call.

private void callGraphAPI(final IAuthenticationResult authenticationResult) {
    MSGraphRequestWrapper.callGraphAPIUsingVolley(
            getContext(),
            graphResourceTextView.getText().toString(),
            authenticationResult.getAccessToken(),
            new Response.Listener<JSONObject>() {
                @Override
                public void onResponse(JSONObject response) {
                    /* Successfully called graph, process data and send to UI */
                    ...
                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    ...
                }
            });
}

auth_config_single_account.json

This is the configuration file for a MSAL app that uses a single account.

See Understand the Android MSAL configuration file for an explanation of these fields.

Note the presence of "account_mode" : "SINGLE", which configures this app to use a single account.

"client_id" is preconfigured to use an app object registration that Microsoft maintains. "redirect_uri"is preconfigured to use the signing key provided with the code sample.

{
  "client_id" : "0984a7b6-bc13-4141-8b0d-8f767e136bb7",
  "authorization_user_agent" : "DEFAULT",
  "redirect_uri" : "msauth://com.azuresamples.msalandroidapp/1wIqXSqBj7w%2Bh11ZifsnqwgyKrY%3D",
  "account_mode" : "SINGLE",
  "broker_redirect_uri_registered": true,
  "authorities" : [
    {
      "type": "AAD",
      "audience": {
        "type": "AzureADandPersonalMicrosoftAccount",
        "tenant_id": "common"
      }
    }
  ]
}

MultipleAccountModeFragment.java

This file demonstrates how to create a multiple account MSAL app and call a Microsoft Graph API.

An example of a multiple account app is a mail app that allows you to work with multiple user accounts such as a work account and a personal account.

Multiple account MSAL initialization

In the MultipleAccountModeFragment.java file, in onCreateView(), a multiple account app object (IMultipleAccountPublicClientApplication) is created using the config information stored in the auth_config_multiple_account.json file:

// Creates a PublicClientApplication object with res/raw/auth_config_multiple_account.json
PublicClientApplication.createMultipleAccountPublicClientApplication(getContext(),
        R.raw.auth_config_multiple_account,
        new IPublicClientApplication.IMultipleAccountApplicationCreatedListener() {
            @Override
            public void onCreated(IMultipleAccountPublicClientApplication application) {
                mMultipleAccountApp = application;
                loadAccounts();
            }

            @Override
            public void onError(MsalException exception) {
                ...
            }
        });

The created MultipleAccountPublicClientApplication object is stored in a class member variable so that it can be used to interact with the MSAL library to acquire tokens and load and remove the user account.

Load an account

Multiple account apps usually call getAccounts() to select the account to use for MSAL operations. The code to load an account is in the MultipleAccountModeFragment.java file, in loadAccounts(). Loading the user's account is an asynchronous operation. So a callback handles the situations when the account is loaded, changes, or an error occurs.

/**
 * Load currently signed-in accounts, if there's any.
 **/
private void loadAccounts() {
    if (mMultipleAccountApp == null) {
        return;
    }

    mMultipleAccountApp.getAccounts(new IPublicClientApplication.LoadAccountsCallback() {
        @Override
        public void onTaskCompleted(final List<IAccount> result) {
            // You can use the account data to update your UI or your app database.
            accountList = result;
            updateUI(accountList);
        }

        @Override
        public void onError(MsalException exception) {
            displayError(exception);
        }
    });
}

Get a token interactively or silently

Some situations when the user may be prompted to select their account, enter their credentials, or consent to the permissions your app has requested are:

  • The first time users sign in to the application
  • If a user resets their password, they'll need to enter their credentials
  • If consent is revoked
  • If your app explicitly requires consent
  • When your application is requesting access to a resource for the first time
  • When MFA or other Conditional Access policies are required

Multiple account apps should typically acquire tokens interactively, that is with UI that involves the user, with a call to acquireToken(). The code to get a token interactively is in the MultipleAccountModeFragment.java file in initializeUI(), in the callGraphApiInteractiveButton click handler:

/**
 * Acquire token interactively. It will also create an account object for the silent call as a result (to be obtained by getAccount()).
 *
 * If acquireTokenSilent() returns an error that requires an interaction,
 * invoke acquireToken() to have the user resolve the interrupt interactively.
 *
 * Some example scenarios are
 *  - password change
 *  - the resource you're acquiring a token for has a stricter set of requirement than your SSO refresh token.
 *  - you're introducing a new scope which the user has never consented for.
 **/
mMultipleAccountApp.acquireToken(getActivity(), getScopes(), getAuthInteractiveCallback());

Apps shouldn't require the user to sign in every time they request a token. If the user has already signed in, acquireTokenSilentAsync() allows apps to request tokens without prompting the user, as shown in the MultipleAccountModeFragment.java file, ininitializeUI() in the callGraphApiSilentButton click handler:

/**
 * Performs acquireToken without interrupting the user.
 *
 * This requires an account object of the account you're obtaining a token for.
 * (can be obtained via getAccount()).
 */
mMultipleAccountApp.acquireTokenSilentAsync(getScopes(),
    accountList.get(accountListSpinner.getSelectedItemPosition()),
    AUTHORITY,
    getAuthSilentCallback());

Remove an account

The code to remove an account, and any cached tokens for the account, is in the MultipleAccountModeFragment.java file in initializeUI() in the handler for the remove account button. Before you can remove an account, you need an account object, which you obtain from MSAL methods like getAccounts() and acquireToken(). Because removing an account is an asynchronous operation, the onRemoved callback is supplied to update the UI.

/**
 * Removes the selected account and cached tokens from this app (or device, if the device is in shared mode).
 **/
mMultipleAccountApp.removeAccount(accountList.get(accountListSpinner.getSelectedItemPosition()),
        new IMultipleAccountPublicClientApplication.RemoveAccountCallback() {
            @Override
            public void onRemoved() {
                ...
                /* Reload account asynchronously to get the up-to-date list. */
                loadAccounts();
            }

            @Override
            public void onError(@NonNull MsalException exception) {
                displayError(exception);
            }
        });

auth_config_multiple_account.json

This is the configuration file for a MSAL app that uses multiple accounts.

See Understand the Android MSAL configuration file for an explanation of the various fields.

Unlike the auth_config_single_account.json configuration file, this config file has "account_mode" : "MULTIPLE" instead of "account_mode" : "SINGLE" because this is a multiple account app.

"client_id" is preconfigured to use an app object registration that Microsoft maintains. "redirect_uri"is preconfigured to use the signing key provided with the code sample.

{
  "client_id" : "0984a7b6-bc13-4141-8b0d-8f767e136bb7",
  "authorization_user_agent" : "DEFAULT",
  "redirect_uri" : "msauth://com.azuresamples.msalandroidapp/1wIqXSqBj7w%2Bh11ZifsnqwgyKrY%3D",
  "account_mode" : "MULTIPLE",
  "broker_redirect_uri_registered": true,
  "authorities" : [
    {
      "type": "AAD",
      "audience": {
        "type": "AzureADandPersonalMicrosoftAccount",
        "tenant_id": "common"
      }
    }
  ]
}

Help and support

If you need help, want to report an issue, or want to learn about your support options, see Help and support for developers.

Next steps

Move on to the Android tutorial in which you build an Android app that gets an access token from the Microsoft identity platform and uses it to call the Microsoft Graph API.

In this quickstart, you download and run a code sample that demonstrates how a native iOS or macOS application can sign in users and get an access token to call the Microsoft Graph API.

The quickstart applies to both iOS and macOS apps. Some steps are needed only for iOS apps and will be indicated as such.

Prerequisites

How the sample works

Shows how the sample app generated by this quickstart works

Register and download your quickstart app

You have two options to start your quickstart application:

Option 1: Register and auto configure your app and then download the code sample

Step 1: Register your application

To register your app,

  1. Go to the Azure portal - App registrations quickstart experience.
  2. Enter a name for your application and select Register.
  3. Follow the instructions to download and automatically configure your new application with just one click.

Option 2: Register and manually configure your application and code sample

Step 1: Register your application

To register your application and add the app's registration information to your solution manually, follow these steps:

  1. Sign in to the Azure portal.
  2. If you have access to multiple tenants, use the Directories + subscriptions filter in the top menu to switch to the tenant in which you want to register the application.
  3. Search for and select Azure Active Directory.
  4. Under Manage, select App registrations > New registration.
  5. Enter a Name for your application. Users of your app might see this name, and you can change it later.
  6. Select Register.
  7. Under Manage, select Authentication > Add Platform > iOS.
  8. Enter the Bundle Identifier for your application. The bundle identifier is a unique string that uniquely identifies your application, for example com.<yourname>.identitysample.MSALMacOS. Make a note of the value you use. Note that the iOS configuration is also applicable to macOS applications.
  9. Select Configure and save the MSAL Configuration details for later in this quickstart.
  10. Select Done.

Step 2: Download the sample project

Step 3: Install dependencies

  1. Extract the zip file.
  2. In a terminal window, navigate to the folder with the downloaded code sample and run pod install to install the latest MSAL library.

Step 4: Configure your project

If you selected Option 1 above, you can skip these steps.

  1. Open the project in XCode.

  2. Edit ViewController.swift and replace the line starting with 'let kClientID' with the following code snippet. Remember to update the value for kClientID with the clientID that you saved when you registered your app in the portal earlier in this quickstart:

    let kClientID = "Enter_the_Application_Id_Here"
    
  3. If you're building an app for Azure AD national clouds, replace the line starting with 'let kGraphEndpoint' and 'let kAuthority' with correct endpoints. For global access, use default values:

    let kGraphEndpoint = "https://graph.microsoft.com/"
    let kAuthority = "https://login.microsoftonline.com/common"
    
  4. Other endpoints are documented here. For example, to run the quickstart with Azure AD Germany, use following:

    let kGraphEndpoint = "https://graph.microsoft.de/"
    let kAuthority = "https://login.microsoftonline.de/common"
    
  5. Open the project settings. In the Identity section, enter the Bundle Identifier that you entered into the portal.

  6. Right-click Info.plist and select Open As > Source Code.

  7. Under the dict root node, replace Enter_the_bundle_Id_Here with the Bundle Id that you used in the portal. Notice the msauth. prefix in the string.

    <key>CFBundleURLTypes</key>
    <array>
       <dict>
          <key>CFBundleURLSchemes</key>
          <array>
             <string>msauth.Enter_the_Bundle_Id_Here</string>
          </array>
       </dict>
    </array>
    
  8. Build and run the app!

More Information

Read these sections to learn more about this quickstart.

Get MSAL

MSAL (MSAL.framework) is the library used to sign in users and request tokens used to access an API protected by Microsoft identity platform. You can add MSAL to your application using the following process:

$ vi Podfile

Add the following to this podfile (with your project's target):

use_frameworks!

target 'MSALiOS' do
   pod 'MSAL'
end

Run CocoaPods installation command:

pod install

Initialize MSAL

You can add the reference for MSAL by adding the following code:

import MSAL

Then, initialize MSAL using the following code:

let authority = try MSALAADAuthority(url: URL(string: kAuthority)!)

let msalConfiguration = MSALPublicClientApplicationConfig(clientId: kClientID, redirectUri: nil, authority: authority)
self.applicationContext = try MSALPublicClientApplication(configuration: msalConfiguration)
Where: Description
clientId The Application ID from the application registered in portal.azure.com
authority The Microsoft identity platform. In most of cases this will be https://login.microsoftonline.com/common
redirectUri The redirect URI of the application. You can pass 'nil' to use the default value, or your custom redirect URI.

For iOS only, additional app requirements

Your app must also have the following in your AppDelegate. This lets MSAL SDK handle token response from the Auth broker app when you do authentication.

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {

    return MSALPublicClientApplication.handleMSALResponse(url, sourceApplication: options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String)
}

Note

On iOS 13+, if you adopt UISceneDelegate instead of UIApplicationDelegate, place this code into the scene:openURLContexts: callback instead (See Apple's documentation). If you support both UISceneDelegate and UIApplicationDelegate for compatibility with older iOS, MSAL callback needs to be placed into both places.

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {

   guard let urlContext = URLContexts.first else {
      return
   }

   let url = urlContext.url
   let sourceApp = urlContext.options.sourceApplication

   MSALPublicClientApplication.handleMSALResponse(url, sourceApplication: sourceApp)
}

Finally, your app must have an LSApplicationQueriesSchemes entry in your Info.plist alongside the CFBundleURLTypes. The sample comes with this included.

<key>LSApplicationQueriesSchemes</key>
<array>
   <string>msauthv2</string>
   <string>msauthv3</string>
</array>

Sign in users & request tokens

MSAL has two methods used to acquire tokens: acquireToken and acquireTokenSilent.

acquireToken: Get a token interactively

Some situations require users to interact with Microsoft identity platform. In these cases, the end user may be required to select their account, enter their credentials, or consent to your app's permissions. For example,

  • The first time users sign in to the application
  • If a user resets their password, they'll need to enter their credentials
  • When your application is requesting access to a resource for the first time
  • When MFA or other Conditional Access policies are required
let parameters = MSALInteractiveTokenParameters(scopes: kScopes, webviewParameters: self.webViewParamaters!)
self.applicationContext!.acquireToken(with: parameters) { (result, error) in /* Add your handling logic */}
Where: Description
scopes Contains the scopes being requested (that is, [ "user.read" ] for Microsoft Graph or [ "<Application ID URL>/scope" ] for custom web APIs (api://<Application ID>/access_as_user)

acquireTokenSilent: Get an access token silently

Apps shouldn't require their users to sign in every time they request a token. If the user has already signed in, this method allows apps to request tokens silently.

self.applicationContext!.getCurrentAccount(with: nil) { (currentAccount, previousAccount, error) in

   guard let account = currentAccount else {
      return
   }

   let silentParams = MSALSilentTokenParameters(scopes: self.kScopes, account: account)
   self.applicationContext!.acquireTokenSilent(with: silentParams) { (result, error) in /* Add your handling logic */}
}
Where: Description
scopes Contains the scopes being requested (that is, [ "user.read" ] for Microsoft Graph or [ "<Application ID URL>/scope" ] for custom web APIs (api://<Application ID>/access_as_user)
account The account a token is being requested for. This quickstart is about a single account application. If you want to build a multi-account app you'll need to define logic to identify which account to use for token requests using accountsFromDeviceForParameters:completionBlock: and passing correct accountIdentifier

Help and support

If you need help, want to report an issue, or want to learn about your support options, see Help and support for developers.

Next steps

Move on to the step-by-step tutorial in which you build an iOS or macOS app that gets an access token from the Microsoft identity platform and uses it to call the Microsoft Graph API.