microsoftconnect / Taskr-Sample-Intune-Android-App

Taskr is a simple, open source, Android app designed to let you test out the capabilities of the Microsoft Intune APP SDK.
MIT License
21 stars 18 forks source link

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.

Important Notes Before Starting

Configuring an Intune Subscription

Configuring App for MSAL Authentication

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.

Grant App Permission to MAM Service

Highlighted SDK Features

:warning: For policy to be applied to the application, the user will need to sign in and authenticate with MSAL.

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.

Managed via App Participation

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.

Managed by the SDK

The following policies are automatically managed by the SDK without explicit app involvement and require no additional development.

About the code

MSAL Integration and the MAM Token

AndroidManifest

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.

MSALUtil class

The MSALUtil class serves as a utility for accessing the required MSAL integration code.

AuthenticationCallback class

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.

Callback Registration

// 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.

Callback Implementation

@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.

Policy Enforcement

AndroidManifest xml

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"
    ...

AboutFragment class

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);

SaveFragment class

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 Roots Certificate Management

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:

Using OkHttpClient

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();
        ...

Using Apache HttpClient

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();
        ...

Using WebView

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);
    ...