Custom QR code for Android Enterprise enrollment with MEM Intune

This post is a continuation of last months post where I surfaced QR codes for Android dedicated enrollments via a Power App. If you missed last months post, you can view it here.

With Android Enterprise, I’m often asked about modifying QR codes to add properties such as WiFi, leaving all system apps, etc. so I decided to create a Power App that does those things and more. Google publishes Android enrollment QR codes options here: Provision devices  |  Google Play EMM API  |  Google Developers, and I choose a subset of the most common properties we’ve been asked about. There are a lot of optional properties available and feel free to add those if needed, just make sure the JSON formatting is valid, otherwise the enrollment won’t kick off when the QR code is scanned by the device.

Finished app

Let’s get started!

Requirements

  • Azure
  • MEM Intune
  • Microsoft Graph
  • Power Apps
  • Power Automate

App Summary

The Power App does the following:

  1. Pulls all the enrollment profiles from Intune using Graph
  2. Provides options to add the a new QR code
  3. Generates a new QR code with the enrollment token from the profile selected and adds the options if populated

Generating the QR code

Because Power App doesn’t have a native QR code creator I needed to find an API to call. For demonstration purposes I’m using QR code API (goqr.me) to generate the QR codes in Power Automate. Feel free to utilize whatever service you’d like to generate QR codes. Security may be a concern as well so I recommend using calling a trusted service to generate custom QR codes.

Decoding the enrollment QR code

There are plenty of sites online where a QR code image may be uploaded and decrypted. For the purposes of this post, the content below is what I use to create the custom QR code based on which options are selected and populated in the Power App:

{ "android.app.extra.PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME": "com.google.android.apps.work.clouddpc/.receivers.CloudDeviceAdminReceiver", "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION": "https://play.google.com/managed/downloadManagingApp?identifier=setup", "android.app.extra.PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM": "I5YvS0O5hXY46mb01BlRjq4oJJGs2kuUcHvVkAPEXlg", "android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE": {              "com.google.android.apps.work.clouddpc.EXTRA_ENROLLMENT_TOKEN": "SELECTED ENROLLMENT TOKEN"              }, "android.app.extra.PROVISIONING_WIFI_SSID": "", "android.app.extra.PROVISIONING_WIFI_PASSWORD": "", "android.app.extra.PROVISIONING_WIFI_SECURITY_TYPE": "", "android.app.extra.PROVISIONING_WIFI_HIDDEN": true/false, "android.app.extra.PROVISIONING_SKIP_ENCRYPTION": true/false, "android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED": true/false,}

Power Automate – query existing Android dedicated enrollment profiles

This step is similar to last months post so I’m repurposing some of the flow because I need the token, however I only need the displayName and tokenValue attributes.

In the flow image below I follow a series of steps and similar to past posts using Power Automate to automate actions using data from Intune.

To get stared, create a new Power Automate flow and follow the steps below.

Step 1 add a the PowerApps trigger which will be called from Power Apps on app load and with a refresh button (more on this later).

Step 2 add the “Current time” action which I’ll use from dynamic content in the Graph query that way I only get valid enrollment profiles, not expired enrollment profiles.

Step 3 add HTTP action and add the query displayed in the URI. Select “Show advanced options” to configure Azure AD auth. Note, in the query I do all the filtering and ordering in the query vs in Power Apps so it comes over clean and ready to use. To recap on this, I covered how to configure the authentication and make the Graph call in a previous post. Basically, I have an app registered in Azure with API perms added so I can make calls to Graph using a client ID and client secret.

https://graph.microsoft.com/beta/DeviceManagement/androidDeviceOwnerEnrollmentProfiles?$filter=tokenExpirationDateTime gt @{body('Current_time')}&$select=displayName,tokenValue&$OrderBy=displayName

Step 4 add a “Parse JSON” action and copy and past the output from a Graph Explorer query using the query from the HTTP URI field, select “Generate from sample” and paste the Graph query output. Note, we can’t utilize the exact query above as we have to be more specific when using Graph Explorer as shown in the query below.

https://graph.microsoft.com/beta/deviceManagement/androidDeviceOwnerEnrollmentProfiles?$filter=tokenExpirationDateTime%20gt%202020-11-20T21:59:41.121Z%20and%20enrollmentMode%20eq%20%27corporateOwnedDedicatedDevice%27&$select=displayName,tokenValue&$OrderBy=displayName

 

JSON schema (copy and paste if you’d like)

{
"type": "object",
"properties": {
"@@odata.context": {
"type": "string"
},
"value": {
"type": "array",
"items": {
"type": "object",
"properties": {
"displayName": {
"type": "string"
},
"tokenValue": {
"type": "string"
}
},
"required": [
"displayName",
"tokenValue"
]
}
}
}
}

Step 5 add a “Response” action and copy only the array from the JSON schema:

{
"type": "array",
"items": {
"type": "object",
"properties": {
"displayName": {
"type": "string"
},
"tokenValue": {
"type": "string"
}
}
}
}


Power Automate flow (
query existing Android dedicated enrollment profiles)


Power Automate – create custom QR code

Let’s step through the Power Automate flow below (granular details and steps may be found in previous automation posts via https://uem4all.com):

Power Apps trigger – add this trigger to link Power Apps and the flow together.

Variables – I use seven variables for each optional QR code setting option in Power Apps. I use the same variable name as I do in Power Apps when I set the option to a variable. More on this later.

HTTP action – the HTTP action is utilized to make the call to the external QR code creator API using the JSON construct above populated with the options set in the variables.

Note: for some reason when a Boolean value is utilized in an action it capitalizes the first letter, for example “true” becomes “True” with a capital “T”. However, JSON doesn’t like capital letters in Boolean values so we need to transform the values to lowercase. I do this by using the following formulas for the three Boolean variables in the HTTP action:

  • if(equals(variables(‘WiFiHidden’),True),’true’,’false’)
  • if(equals(variables(‘SkipEncryption’),True),’true’,’false’)
  • if(equals(variables(‘LeaveSysAppsEnabled’),True),’true’,’false’)

Initialize variable – because the HTTP action response is not in JSON I need to convert the response to JSON and I do this by creating a variable in the form of an array.

Parse JSON – here’s where I parse the JSON created from the variable array and I needed to create by hand.

Parse JSON schema for the array

{
"type": "array",
"items": {
"type": "object",
"properties": {
"$content-type": {
"type": "string"
},
"$content": {
"type": "string"
}
},
"required": [
"$content-type",
"$content"
]
}
}

Response – this used to send the data back to the Power App in the form a collection, more on this later.

Response schema

{
"type": "array",
"items": {
"type": "object",
"properties": {
"$content-type": {
"type": "string"
},
"$content": {
"type": "string"
}
}
}
}

Power Automate flow (create custom QR code)

Power Apps


Power App layout


Home screen

We need to populate the token dropdown in a collection and create a collection for the WiFi security types (the dropdown that begins with NONE) available for QR code customization. I do this by adding the code below to the ACTION -> OnVisible field for the form and add the query below:

ClearCollect(WiFiOptions,{SecurityType:"NONE"},{SecurityType:"WEP"},{SecurityType:"WPA"},{SecurityType:"EAP"});ClearCollect(AndroidTokenCollection,{displayName:""});Collect(AndroidTokenCollection,'CustomQR-GetAndroidEnrollmentTokens'.Run());Set(JSONVariable, JSON(AndroidTokenCollection,JSONFormat.IncludeBinaryData))

Note: WPA covers WPA2 so when WPA is selected, WPA/WPA2 is implied.

Refresh token list

The “Refresh token list” dropdown is a modified version of last months post and was reviewed in the Power Automate section above. Nothing really changed other than the query which is identical to the query for the home screen:

ClearCollect(WiFiOptions,{SecurityType:"NONE"},{SecurityType:"WEP"},{SecurityType:"WPA"},{SecurityType:"EAP"});ClearCollect(AndroidTokenCollection,{displayName:""});Collect(AndroidTokenCollection,'CustomQR-GetAndroidEnrollmentTokens'.Run());Set(JSONVariable, JSON(AndroidTokenCollection,JSONFormat.IncludeBinaryData))

    Side note

Let’s break down the query above a little bit to clarify a few things… as shown in the image below the query creates collections and references the Power Automate flow to populate the collection. The WiFiOptions collection manually creates the items the SecurityType dropdown references. The reason why I add ClearCollect(AndroidTokenCollection,{displayName:””}) is because I want a blank entry at the top of the table and as a result, the first entry in the dropdown for the token profiles is blank. I then populate the same collection with the Power Automate flow using “Collect” to append the data. ClearCollect clears the collection, Collect adds to it.



WiFi Options

The WiFi fields consist of two text fields, one dropdown used to select the security type, and a WiFi hidden checkbox. The WiFi security type dropdown references the following collection WiFiOptions, add “WiFiOptions” to DATA -> Items for the dropdown.


Other Settings

For the two check boxes, “LEAVE ALL SYSTEM APPS ENABLED” is commonly asked for while “SKIP ENCRYPTION” isn’t asked for as much, however I added it anyway. There are two methods to bring back system apps to a devices enrolled via Android Enterprise Device Owner, one is to modify the QR code by adding “LEAVE ALL SYSTEM APPS ENABLED” and setting it to “true” or by adding individual apps back based on the app package name in the MEM admin center. Both provide the same outcome, however selectively adding apps in the MEM admin center provides a controlled approach to managing system apps. Some organizations aren’t as rigorous and use a lock screen such as the Managed Home Screen to only allow certain apps to be accessed. Regardless, “LEAVE ALL SYSTEM APPS ENABLED” option is in high demand as it’s what a lot of orgs are familiar with.


Image

Add an image field from the Insert -> Media option. To render the QR code properly we to transform the result from the Power Automate flow that’s stored in the QRCodeImage collection by using the formula below. Because the value is Base64 I needed to convert it to Text for the image to render it properly. This is slightly different from what I did in last month’s post because here I’m calling an external service to generate the QR code and needed to get creative on how the data is read and stored in a collection.

Concatenate("data:image/jpeg;base64,",Text(QRcodebase64))


Generate custom QR code

The “Generate customer QR code” button does the work of executing the Power Automate flow (i.e. “GeneratecustomQRcode” flow) and rendering the QR code:

Set(tokenID,'Intune Android enrollment profiles'.Selected.tokenValue);Set(SSID,WIFI_SSID_input.Text);Set(WiFiPassword,WIFI_PASSWORD_input.Text);Set(WiFiSecType,WIFI_SECURITY_TYPE_Dropdown.Selected.SecurityType);Set(WiFiHidden,WIFI_HIDDEN_Checkbox.Value);Set(LeaveSysAppsEnabled,LEAVE_ALL_SYSTEM_APPS_ENABLED_Checkbox.Value);Set(SkipEncryption,SKIP_ENCRYPTION_Checkbox.Value);ClearCollect(QRCodeImage,GeneratecustomQRcode.Run(tokenID, SSID, WiFiPassword, WiFiSecType, WiFiHidden, LeaveSysAppsEnabled, SkipEncryption));Set(QRcodebase64, Concat(QRCodeImage, '$content'))

  

Putting it all together

Once this process of building the Power App is completed we are ready to test it out.


Important

When populating fields the WiFi SSID and Password are case sensitive, any grammatical mistakes and the enrollment will not complete.

Video


Direct video link: https://www.screencast.com/t/RsKodoax

Conclusion

That was even more fun than last months post. We created a Power App to query for existing tokens, we then selected and populated additional options, and generated a custom QR code from the selections.

Appendix

MEM Android Enterprise enrollment options: Enroll Android Enterprise dedicated, fully managed, or corporate-owned work profile devices in Intune – Microsoft Intune | Microsoft Docs