Taskr - A Microsoft Intune Android MAM SDK Example
MAM SDK Version | MSAL Version |
---|---|
9.5.0 | 4.1.0 |
This project is a demonstration of the Microsoft Intune SDK for Android and contains examples from the SDK Guide, which is available to provide additional developer guidance.
It also demonstrates how to integrate a line-of-business app with the Trusted Roots Certificates Management API. Detailed information can be found in section Using Trusted Root Certificates from Intune to Establish Trust Anchors of the SDK Guide.
- A tenant is necessary for the configuration of an Intune subscription. A free trial is sufficient for this demo and can be registered for at Microsoft's demo site.
- Once a tenant is acquired the Intune subscription will need to be properly configured to target the user and the application. This can be accomplished by following the steps to Set up Intune.
This sample features an MSAL integration to highlight MAM functionality, see About the code for more information regarding MSAL. The purpose of registering with MSAL is to acquire a unique client ID, redirect URI, and signature hash for your application.
- Perform the app registration and configuration steps by following the Register Your Own Application steps for an MSAL application.
- Update the MSAL values in this sample with those called out by Using MSAL.
- Replace the included
auth-config
JSON file with the configuration for your app.
- You will need to grant your app permissions to the Intune Mobile Application Management (MAM) service.
This project demonstrates proper integration with the MAM SDK and the APP service for a single-identity application.
If your application is a multi-identity application, please refer to the multi-identity application integration guide for the necessary modifications.
The following policies require app participation in order to be properly enforced.
A full breakdown of policies requiring app participation can be found in the "Enable features that require app participation" section of the SDK guide.
- Prevent Android backups – The app enables managed backups in
AndroidManifest.xml
. More information is available here. - Prevent "Save As":
- To User's Device - To determine if saving to the device is allowed, the app manually checks the user's policy in
fragments/TasksFragment.java
. If allowed, the save button will save a CSV containing all open tasks to the user's device. Otherwise, a notification will be displayed to the user.
- To User's Device - To determine if saving to the device is allowed, the app manually checks the user's policy in
- App configuration policies – The app displays the current configuration as an example on the About page in
fragments/AboutFragment.java
.
The following policies are automatically managed by the SDK without explicit app involvement and require no additional development.
- Require PIN for access – The MAM SDK will prompt the user for a PIN before any UI code is executed, if required by policy.
- Allow fingerprint instead of PIN - See above.
- Require corporate credentials for access – See above.
- Allow app to transfer data to other apps – This policy is demonstrated when the user clicks on the save button, which attempts to export a CSV containing tasks to Excel.
- Disable printing – This policy is demonstrated when the user clicks on the print button, which attempts to open the CSV in Android’s default printing view.
- Allow app to receive data from other apps – This policy is demonstrated when the app receives intents containing the text of a description to create a task.
- Restrict web content to display in the Managed Browser – This policy is demonstrated when a user clicks on a link from the About screen.
- Encrypt app data - This policy is demonstrated when the app attempts to save a CSV file. If enabled, the file will be encrypted on disk.
The AndroidManifest contains the BrowserTabActivity that is required for proper MSAL integration.
<!-- Must be specified to allow users to login via MSAL -->
<activity android:name="com.microsoft.identity.client.BrowserTabActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!--
Add in your scheme/host from registered redirect URI
note that the leading "/" is required for android:path
-->
<data
android:host="com.intune.samples.taskr"
android:path="/SignatureHash"
android:scheme="msauth" />
</intent-filter>
</activity>
The SignatureHash
will need to be replaced with the MSAL
registration values for your application.
There is no specific MAM code alteration required for the BrowserTabActivity
.
Apps targeting Android 12 must explicitly declare the android:exported
attribute for app components. Activity supporting VIEW
and LAUNCHER
must be exported.
For more information check Android developer notes on Behavior changes.
The MSALUtil class serves as a utility for accessing the required MSAL integration code.
The AuthenticationCallback class is registered in TaskrApplication and handles acquiring the MAM token.
You must register this callback in order to receive a token for MAM. Without this, full MAM integration is not achievable.
// Registers a MAMServiceAuthenticationCallback, which will try to acquire access tokens for MAM.
// This is necessary for proper MAM integration.
MAMEnrollmentManager mgr = MAMComponents.get(MAMEnrollmentManager.class);
mgr.registerAuthenticationCallback(new AuthenticationCallback(getApplicationContext()));
This callback should be registered as early as possible in the onCreate
method of your application.
@Nullable
@Override
public String acquireToken(@NonNull final String upn, @NonNull final String aadId, @NonNull final String resourceId) {
try {
// Create the MSAL scopes by using the default scope of the passed in resource id.
final String[] scopes = {resourceId + "/.default"};
final IAuthenticationResult result = MSALUtil.acquireTokenSilentSync(mContext, aadId, scopes);
if (result != null)
return result.getAccessToken();
} catch (MsalException | InterruptedException e) {
LOGGER.log(Level.SEVERE, "Failed to get token for MAM Service", e);
return null;
}
LOGGER.warning("Failed to get token for MAM Service - no result from MSAL");
return null;
}
As is noted by the comments, the resource ID that is passed to the acquireToken
method should be
used to construct the proper scopes for the MAM token.
The AndroidManifest file models how to utilize the MAM SDK's backup manager to block and encrypt backups, if specified by policy.
<!-- The backupAgent here is provided by the MAM SDK. It will block/encrypt backups if necessary. -->
<application
android:allowBackup="true"
android:fullBackupOnly="true"
android:fullBackupContent="true"
android:backupAgent="com.microsoft.intune.mam.client.app.backup.MAMDefaultBackupAgent"
...
The AccountFragment
class models how to retrieve the app config from the MAM SDK.
String currentUser = AppSettings.getAccount(this.getContext()).getAADID();
MAMAppConfigManager configManager = MAMComponents.get(MAMAppConfigManager.class);
MAMAppConfig appConfig = configManager.getAppConfig(currentUser);
The SaveFragment
class models how to check data transfer policy for saving data to local storage.
String currentUser = AppSettings.getAccount(view.getContext()).getAADID();
if (MAMPolicyManager.getPolicy(getActivity())
.getIsSaveToLocationAllowed(SaveLocation.LOCAL, currentUser)) {
...
Trusted Root Certificates Management allows your app to use trusted root certificates from Intune in combination with certificates from the device. This allows your app to establish trust with resources that are protected by a certificate issued by your organization.
This sample showcases three different ways to use trusted roots certificates from Intune to establish trust anchors:
The submitOkHttpClientRequest
method in the TrustedRootsNetworkHandler
class models how to configure an OkHttpClient
to use the Trusted Root Certificates Management API.
OkHttpClient okHttpClient = OkHttpClient.Builder()
.sslSocketFactory(
MAMTrustedRootCertsManager.createSSLSocketFactory(null, null),
MAMTrustedRootCertsManager.createX509TrustManagers(null).first() as X509TrustManager
)
.build();
...
The submitApacheHttpClient5Request
method in the TrustedRootsNetworkHandler
class models how to configure an Apache HttpClient
to use the Trusted Root Certificates Management API.
HttpClientConnectionManager connectionManager =
PoolingHttpClientConnectionManagerBuilder.create()
.setSSLSocketFactory(
SSLConnectionSocketFactory(MAMTrustedRootCertsManager.createSSLContext(null, null))
)
.build();
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(connectionManager)
.build();
...
The WebViewClientFragment
and WebViewClientViewModel
classes model how to configure a WebView
to use the Trusted Roots enabled WebViewClient
from the SDK.
MAMCertTrustWebViewClient mamCertTrustWebViewClient = new MAMCertTrustWebViewClient();
// Set the MAM WebViewClient from the SDK as the current handler on the instance of WebView
webView.setWebViewClient(mamCertTrustWebViewClient);
...