Tutorial: Add shared-device mode support to your Android application
Article
In this tutorial, Android developers learn how to add shared device mode support in an Android application using the Microsoft Authentication Library (MSAL) for Android.
In this tutorial:
Create or modify an existing Android application project.
Enable and detect shared-device mode
Detect single or multiple account mode
Detect a user switch
Enable global sign-in and sign-out
Create or modify an existing Android application
To complete the rest of the tutorial, you need to create a new or modify an existing Android application. If you haven't already, see the MSAL Android tutorial for guidance on how to integrate MSAL with your Android app, sign in a user, call Microsoft graph, and sign out a user. If you prefer using a completed code sample for learning and testing, clone the sample application from GitHub. The sample has the capability to work in single or multi account mode.
Add the MSAL SDK to your local Maven repository
If you're not using the sample app, add the MSAL library as a dependency in your build.gradle file, like so:
Applications written using the Microsoft Authentication Library (MSAL) SDK can manage a single account or multiple accounts. For details, see single-account mode or multiple-account mode.
The Microsoft identity platform features available to your app vary depending on whether the application is running in single-account mode or multiple-account mode.
Shared device mode apps only work in single-account mode.
Important
Applications that only support multiple-account mode can't run on a shared device. If an employee loads an app that doesn't support single-account mode, it won't run on the shared device.
Apps written before the MSAL SDK was released run in multiple-account mode and must be updated to support single-account mode before they can run on a shared mode device.
Supporting both single-account and multiple-accounts
Your app can be built to support running on both personal devices and shared devices. If your app currently supports multiple accounts and you want to support shared device mode, add support for single account mode.
You may also want your app to change its behavior depending on the type of device it's running on. Use ISingleAccountPublicClientApplication.isSharedDevice() to determine when to run in single-account mode.
There are two different interfaces that represent the type of device your application is on. When you request an application instance from MSAL's application factory, the correct application object is provided automatically.
The following object model illustrates the type of object you may receive and what it means in the context of a shared device:
You need to do a type check and cast to the appropriate interface when you get your PublicClientApplication object. The following code checks for multiple account modes or single account modes, and casts the application object appropriately:
private IPublicClientApplication mApplication;
// Running in personal-device mode?
if (mApplication instanceOf IMultipleAccountPublicClientApplication) {
IMultipleAccountPublicClientApplication multipleAccountApplication = (IMultipleAccountPublicClientApplication) mApplication;
...
// Running in shared-device mode?
} else if (mApplication instanceOf ISingleAccountPublicClientApplication) {
ISingleAccountPublicClientApplication singleAccountApplication = (ISingleAccountPublicClientApplication) mApplication;
...
}
The following differences apply depending on whether your app is running on a shared or personal device:
Shared mode device
Personal device
Accounts
Single account
Multiple accounts
Sign-in
Global
Global
Sign-out
Global
Each application can control if the sign-out is local to the app.
Set "shared_device_mode_supported" to true in your MSAL configuration file.
You may not be planning to support multiple-account mode. That could be if you're not using a shared device, and the user can sign into the app with more than one account at the same time. If so, set "account_mode" to "SINGLE". This guarantees that your app will always get ISingleAccountPublicClientApplication, and significantly simplifies your MSAL integration. The default value of "account_mode" is "MULTIPLE", so it's important to change this value in the config file if you're using "single account" mode.
Here's an example of the auth_config.json file included in the app>main>res>raw directory of the sample app:
{
"client_id": "Client ID after app registration at https://aka.ms/MobileAppReg",
"authorization_user_agent": "DEFAULT",
"redirect_uri": "Redirect URI after app registration at https://aka.ms/MobileAppReg",
"account_mode": "SINGLE",
"broker_redirect_uri_registered": true,
"shared_device_mode_supported": true,
"authorities": [
{
"type": "AAD",
"audience": {
"type": "AzureADandPersonalMicrosoftAccount",
"tenant_id": "common"
}
}
]
}
Detect shared-device mode
Shared-device mode allows you to configure Android devices to be shared by multiple employees, while providing Microsoft Identity backed management of the device. Employees can sign in to their devices and access customer information quickly. When they're finished with their shift or task, they'll be able to sign out of all apps on the shared device with a single click and the device will be immediately ready for the next employee to use.
Use isSharedDevice() to determine if an app is running on a device that is in shared-device mode. Your app could use this flag to determine if it should modify UX accordingly.
Here's a code snippet that shows how you could use isSharedDevice(). It's from the SingleAccountModeFragment class in the sample app:
If you set "account_mode":"SINGLE" in the MSAL config file, you can safely cast the returned application object as an ISingleAccountPublicCLientApplication.
private ISingleAccountPublicClientApplication mSingleAccountApp;
/*Configure your sample app and save state for this activity*/
PublicClientApplication.create(this.getApplicationCOntext(),
R.raw.auth_config,
new PublicClientApplication.ApplicationCreatedListener(){
@Override
public void onCreated(IPublicClientApplication application){
mSingleAccountApp = (ISingleAccountPublicClientApplication)application;
loadAccount();
}
@Override
public void onError(MsalException exception){
/*Fail to initialize PublicClientApplication */
}
});
Detect single vs. multiple account mode
If you're writing an app that will only be used for frontline workers on a shared device, we recommend you write your app to only support single-account mode. This includes most applications that are task focused such as medical records apps, invoice apps, and most line-of-business apps. This will simplify your development as many features of the SDK won't need to be accommodated.
If your app supports multiple accounts and shared device mode, you must perform a type check and cast to the appropriate interface as shown below.
Get the signed in user and determine if a user has changed on the device
The loadAccount method retrieves the account of the signed in user. The onAccountChanged method determines if the signed-in user has changed, and if so, clean up:
private void loadAccount()
{
mSingleAccountApp.getCurrentAccountAsync(new ISingleAccountPublicClientApplication.CurrentAccountCallback())
{
@Override
public void onAccountLoaded(@Nullable IAccount activeAccount)
{
if (activeAccount != null)
{
signedInUser = activeAccount;
mSingleAccountApp.acquireTokenSilentAsync(SCOPES,"http://login.microsoftonline.com/common",getAuthSilentCallback());
}
}
@Override
public void onAccountChanged(@Nullable IAccount priorAccount, @Nullable Iaccount currentAccount)
{
if (currentAccount == null)
{
//Perform a cleanup task as the signed-in account changed.
updateSingedOutUI();
}
}
@Override
public void onError(@NonNull Exception exception)
{
}
}
}
Globally sign in a user
The following signs in a user across the device to other apps that use MSAL with the Authenticator App:
The following removes the signed-in account and clears cached tokens from not only the app but also from the device that is in shared device mode:
private void onSignOutClicked()
{
mSingleAccountApp.signOut(new ISingleAccountPublicClientApplication.SignOutCallback()
{
@Override
public void onSignOut()
{
updateSignedOutUI();
}
@Override
public void onError(@NonNull MsalException exception)
{
/*failed to remove account with an exception*/
}
});
}
Receive broadcast to detect global sign out initiated from other applications
To receive the account change broadcast, you need to register a broadcast receiver. It’s recommended to register your broadcast receiver via the Context-registered receivers.
The following code snippet shows how you could register a broadcast receiver.
private static final String CURRENT_ACCOUNT_CHANGED_BROADCAST_IDENTIFIER = "com.microsoft.identity.client.sharedmode.CURRENT_ACCOUNT_CHANGED";
private BroadcastReceiver mAccountChangedBroadcastReceiver;
private void registerAccountChangeBroadcastReceiver(){
mAccountChangedBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//INVOKE YOUR PRIOR ACCOUNT CLEAN UP LOGIC HERE
}
};
IntentFilter filter = new
IntentFilter(CURRENT_ACCOUNT_CHANGED_BROADCAST_IDENTIFIER);
this.registerReceiver(mAccountChangedBroadcastReceiver, filter);
}
Register the application and set up your tenant for testing
Before you can set up your application and put your device into shared-device mode, you need to register the application within your organizational tenant. You then provide these values in auth_config.json for your application to run correctly.
When you register your app, please use the quickstart guide on the left-hand side and then select Android. This will lead you to a page where you'll be asked to provide the Package Name and Signature Hash for your app. These are very important to ensure your app configuration will work. You'll then receive a configuration object that you can use for your app that you'll cut and paste into your auth_config.json file.
You should select Make this change for me and then provide the values the quickstart asks for. When done, Microsoft Entra ID generates all the configuration files you need.
For testing purposes, set up the following roles in your tenant - at least two employees and a Cloud Device Administrator. To set the Cloud Device Administrator, you need to modify Organizational Roles. From the Microsoft Entra admin center, go to your Organizational Roles by selecting Identity > Roles & admins > Roles & admins > All roles, and then select Cloud Device Administrator. Add the users that can put a device into shared mode.
Running the sample app
The Sample Application is a simple app that will call the Graph API of your organization. On first run, you'll be prompted to consent as the application is new to your employee account.
Next steps
Set up an Android device to run apps in shared device mode and test your app.
Discover how Microsoft Entra External ID can provide secure, seamless sign-in experiences for your consumers and business customers. Explore tenant creation, app registration, flow customization, and account security.