Tag Archives: Azure Active Directory

Watermarking & Session Capture Protection in Azure Virtual Desktop using Microsoft Intune and Azure AD Joined devices

31 Aug

In the July 2023 release for Azure Virtual Desktop, the Watermarking and Session capture protection features became generally available. Numerous blog posts already showcase how to enable the feature using Group Policy. In today’s post, I will showcase how to enable Watermarking and Session Capture protection using Microsoft Intune for Session Host Virtual machines that are Azure AD joined.


You’ll need the following things ready before you can rollout watermarking/session capture protection:

  • Azure Virtual Desktop: You must have Azure Virtual Desktop deployed (Pooled or Personal Desktops) and set up in your Azure environment.
  • Microsoft Intune: You should have an active subscription to Microsoft Intune, which is a cloud-based service that enables device management and security. The role within Intune Portal for creating and assigning the configuration profiles is – Policy and Profile manager built-in role-based access control (RBAC) role.
  • Azure Active Directory: Your Azure Virtual Desktop environment should be integrated with Azure Active Directory (AD) (The Host pools RDP properties – targetisaadjoined:i:1). The AAD Security groups must be in place, which has the members as the session’s host in AVD.
  • Azure AD Joined Devices: The session host virtual machines (VMs) you want to enable Watermarking and Session Capture protection for should be Azure AD joined. This means they must be connected to Azure AD and registered as members of your organization’s directory.
  • Admin Access: You need administrative access to the Azure portal (https://portal.azure.com) and Microsoft Intune (https://intune.microsoft.com).
  • Windows 11 operating system for the client along with the Azure Virtual Desktop Client or Remote Desktop Client versions 1.2.x and higher

Configuration Profiles – Intune

To enable the Watermarking and Session Capture protection features in Azure Virtual Desktop using Microsoft Intune Configuration profiles and Azure AD joined devices, you can follow these steps:

  • In the settings picker, browse to Administrative templates > Windows Components > Remote Desktop Services > Remote Desktop Session Host > Azure Virtual Desktop. You should see settings in the Azure Virtual Desktop subcategory available for you to configure, such as “Enable watermarking” and “Enable screen capture protection”
  • Select the “Enable screen capture protection” settings, too and leave the values as defaults. (Feel free to tweak it based on your requirements)
  • Assigning the configuration to the AAD group, which has all the session host devices
  • Reboot the session host after applying or wait until the next maintenance cycle

Client Validation

Connect to a remote session with a supported client (Azure Virtual Desktop Client or Remote Desktop Client versions 1.2.x), where you should see QR codes appear.

The QR code only works for Windows 11 Multi-session\Windows 11 Enterprise (pooled or personal desktops). The RemoteApps will not show the QR code as its not supported.

Screenshot protection – In the session, it will be completely blank if you try to take a screenshot. Below is an example. I was trying to take a screenshot of the text file, and the screenshot was completely blank.

Mobile Phone Photo

When you try to take a screenshot from the mobile phone, this is how it will look, and it will pop the Connection ID. You have this connection ID you can match in Azure Insights.

Azure Virtual Desktop Insights

To find out the session information from the QR code by using Azure Virtual Desktop Insights:

  1. Open a web browser and go to https://aka.ms/avdi to open Azure Virtual Desktop Insights. Sign-in using your Azure credentials when prompted.
  2. Select the relevant subscription, resource group, host pool and time range, then select the Connection Diagnostics tab.
  3. In the section Success rate of (re)establishing a connection (% of connections), there’s a list of all connections showing First attemptConnection IdUser, and Attempts. You can look for the connection ID from the QR code in this list, or export to Excel.

I hope you will find this helpful information for getting started with Watermarking and Screenshot protection for the Azure Virtual Desktop – Session Host. Please let me know if I have missed any steps or details, and I will be happy to update the post.

Aresh Sarkari

Windows 365 Cloud PC – Alert Monitoring – Get your alerts in a Microsoft Teams Channel using Azure Logic Apps

23 Mar

If you’re managing Windows 365 Cloud PCs, keeping track of alerts can be a daunting task. Fortunately, Azure Logic Apps can help automate this process by sending alerts directly to your Microsoft Teams channel. In this blog post, we’ll explore how to set up this integration, so you can stay on top of your Windows 365 environment without constantly checking the portal or notifications within the Intune portal.

Note – Within the Microsoft Intune admin center portal you can already send notifications via email.

Set up your Microsoft Teams channel

To start, you’ll need to create a Microsoft Teams channel where you want to receive alerts. If you don’t have one already, create a new channel and name it something like “Windows365Alerts.”

Next, within the newly created channel, add the Connector – Incoming Webhook

Click on Configure of the Incoming Webhook connectors by entering the Name – Win365Alerts and custom image. Why not use the Windows 365 Cloud PC Logo and click on create.

Please copy the link and save it for all future reference purposes. We will be using this URL within the Azure Logic Apps.


Azure Active Directory Enterprise App (MS Graph API)

Let’s pre-create the application ID and client secret we will use to connect and leverage the Microsoft Graph APIs via Powershell

  • Connect to Azure Portal and go to Azure Active Directory
  • Click on App Registrations and select – New Registration
  • Give the App a Name – GraphAPI-App
  • You will get two important information created for later use within Powershell
    • Application ID
    • Tenant ID
  • Now let’s grant this App GraphAPI-App Permission. Click on Add a permission and select MS Graph and search for Cloud PC– CloudPC.ReadAll and select read permissions and Add Permissions
  • Select Grant admin consent for domain
  • We are using client secret so now lets enable that. Click on Certificates & Secrets – Client Secrets and select New client secret\
  • Give it a name (Deviceconfig_secret) and expiry date (12 months)
  • Copy the Secret Value

Azure Key Vault – (Store the Secret)

This is an optional step, and I highly recommend this step for all production environments as the secret is stored within the Azure Key Vault, and within the Azure Logic Apps, you will call this secret.

After creating the value, go to Secret and click on Generate/Import, and under manual, enter a name and paste the secret key we created in the above step.

Additionally, I will dedicate a service account(svc_kv_api) specifically for this secret retrieval for the Azure Logic Apps. Let’s add the service account with the necessary permissions under the Access Policies and give it Get and List permissions.

Create an Azure Logic App

Next, you’ll need to create an Azure Logic App. In the Azure portal, search for “Logic Apps” and click “Create.” Give your Logic App a name and select your desired subscription, resource group, and location. Then click “Review + Create” and “Create” to create your Logic App.

Configure your Logic App

Once your Logic App is created, click “Logic App Designer” and select blank logic app template and add the other operations shown below:

Step 1 – Recurrence (A schedule that will be triggered)

Depending upon your SLA agreements, put a trigger. In this example, I have selected every 3 min.

Step 2 – Fetch the Secret from the Azure Key Vault

In the earlier step, we created the Azure Key vault and stored the secret there. In this step, we will make the Azure Logic Apps Fetch the Secret

  • Tenant ID – Copy from the above steps
  • KeyVault Name – Copy from the above steps
  • Click on Sign and use the dedicated service account to fetch this Secret

Step 3 – HTTP Get the Alerts for Windows 365 Using MS Graph API

We shall create the HTTP request using the Windows 365 Alert API – List and authenticate the call using the secret. Enter all the information shown in the screenshot.


Step 4 – We shall Parse the JSON output from the above API GET request

Create the Parse JSON operation, and we will enter the below sample JSON output. Note I have run the GET and got the output from the API. Paste the below code into the schema example. It will auto-generate the below output for your use without values inside.

    "properties": {
        "@@odata.context": {
            "type": "string"
        "value": {
            "items": {
                "properties": {
                    "alertImpact": {
                        "properties": {
                            "aggregationType": {
                                "type": "string"
                            "value": {
                                "type": "integer"
                        "type": "object"
                    "alertRuleId": {
                        "type": "string"
                    "alertRuleTemplate": {
                        "type": "string"
                    "detectedDateTime": {
                        "type": "string"
                    "displayName": {
                        "type": "string"
                    "id": {
                        "type": "string"
                    "lastUpdatedDateTime": {
                        "type": "string"
                    "resolvedDateTime": {
                        "type": "string"
                    "severity": {
                        "type": "string"
                    "status": {
                        "type": "string"
                "required": [
                "type": "object"
            "type": "array"
    "type": "object"

Step 5 – Post the Alert to Microsoft Teams using the HTTP operation

Create the HTTP Operation, select POST, enter the webhook URL from the above step on MS Teams, and paste it within the URL. With the Headers add Content-Type: application/json and paste the below body code.

  "text": "**Alert name:** @{items('For_each')?['displayName']} \n\n **Status:** @{items('For_each')?['status']} \n\n **Severity:** @{items('For_each')?['severity']} \n\n **Detect Date:** @{items('For_each')?['detectedDateTime']} \n\n **Resolved Date:** @{items('For_each')?['resolvedDateTime']} \n\n **Alert Rule Template:** @{items('For_each')?['alertRuleTemplate']} \n\n **Alert Impact:** @{items('For_each')?['alertImpact']}",
  "title": "Windows 365 Cloud PC Alerts  with status and Severity "

Step 6 – Run the workflow

The above will now start running the Azure Logic Apps every 3 mins and keep sending the alerts to Microsoft teams

I need help filtering the alerts based on specific Status and Severity. If you manage to get to that, please message me, and I will happily include those bits in the blog post.

I hope you will find this helpful information for enabling Windows 365 Alerts within the MS Teams using the Azure Logic Apps. Please let me know if I have missed any steps or details, and I will be happy to update the post.

Aresh Sarkari

PowerShell Enable Remote Help in Microsoft Intune

7 Mar

Remote Help in Microsoft Intune works by enabling IT administrators to remotely control a user’s mobile device, allowing them to view the device’s screen and interact with it in real-time. This enables administrators to quickly diagnose and fix issues on the device, without needing to be physically present with the user.

To use Remote Help in Microsoft Intune, IT administrators first need to enable the feature in the Intune console. Once enabled, administrators can initiate a remote session with a user’s device by sending an invitation link to the user via email or text message. The user then clicks on the link to join the remote session, allowing the administrator to remotely control the device.

In the blog post I will showcase how to enable this feature via PowerShell instead of the Microsoft Intune admin center portal.


  • An active Microsoft Intune subscription.
  • An Azure AD (Active Directory) subscription with administrative access.
  • The Azure AD application registration credentials, including client ID and secret.
  • Permissions to access and manage Microsoft Intune and Microsoft Graph API resources.
  • PowerShell and AzureAD PowerShell module installed on the local machine to run PowerShell scripts.
  • A valid Azure AD authentication token to authenticate and authorize Microsoft Graph API requests.

Create the Client Secret for MS Graph

Let’s pre-create the application ID and client secret we will use to connect and leverage the Microsoft Graph APIs via Powershell

  • Connect to Azure Portal and go to Azure Active Directory
  • Click on App Registrations and select – New Registration
  • Give the App a Name – MSGraph-DeviceMgmt-Secret
  • You will get two important information created for later use within Powershell
    • Application ID
    • Tenant ID
  • Now let’s grant this App MSGraph Permission. Click on Add a permission and select MS Graph and search for Device – DeviceManagementConfiguration and select read-write permissions and Add Permissions
  • Select Grant admin consent for domain

Note that RemoteSettings, aka Remote Help, falls under Device Management Configurations. We will use that for the permissions (read-write)

  • We are using client secret so now lets enable that. Click on Certificates & Secrets – Client Secrets and select New client secret\
  • Give it a name (Deviceconfig_secret) and expiry date (12 months)
  • Copy the Secret Value

Variable Region

Delcare all the variable within this section. Lets take a look at what we are declaring within the script:

  • GraphEndpoint and resource URL if you notice we are using the remoteAssistanceSettings
$graphEndpoint = "https://graph.microsoft.com"
$resourceUrl = "$graphEndpoint/beta/deviceManagement/remoteAssistanceSettings"
  • From the above section we have the values for Client ID, Secret and tenant id which we will paste in here.
$authority = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"
$scope = "https://graph.microsoft.com/.default"

Execution block

Execution code block within this section. Lets take a look at what we are we executing within the script:

  • The body payload to enable disable the Remote Help Assistance settings
    • RemoteAssistanceState – Enabled/Disabled
    • AllowSession to Unenrolled Devices – $true or $false
    • Block chat – $true or $false
$payload = @{
    "@odata.type" = "#microsoft.graph.remoteAssistanceSettings"
    "remoteAssistanceState" = "disabled"
    "allowSessionsToUnenrolledDevices" = $false
    "blockChat" = $false
} | ConvertTo-Json

Final Script

Here I will paste the entire script block for seamless execution in a single run. Following is the link to my GitHub for this script – https://github.com/askaresh/avdwin365mem/blob/main/enableremotehelpmem

# Define the Graph API endpoint and resource URL
$graphEndpoint = "https://graph.microsoft.com"
$resourceUrl = "$graphEndpoint/beta/deviceManagement/remoteAssistanceSettings"

# Define the authentication parameters
$authority = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"
$scope = "https://graph.microsoft.com/.default"

# Authenticate to the Graph API and obtain an access token
$tokenResponse = Invoke-RestMethod -Method Post -Uri $authority `
    -Body @{
        client_id = $clientId
        client_secret = $clientSecret
        scope = $scope
        grant_type = "client_credentials"
    } `
    -Headers @{
        "Content-Type" = "application/x-www-form-urlencoded"

$accessToken = $tokenResponse.access_token

# Define the payload for the PATCH request
$payload = @{
    "@odata.type" = "#microsoft.graph.remoteAssistanceSettings"
    "remoteAssistanceState" = "enabled"
    "allowSessionsToUnenrolledDevices" = $false
    "blockChat" = $false
} | ConvertTo-Json

# Send a PATCH request to the remoteAssistanceSettings resource with the updated payload
$headers = @{
    "Authorization" = "Bearer $accessToken"
    "Content-Type" = "application/json"
    "Content-length" = $payload.Length

Invoke-RestMethod -Method Patch -Uri $resourceUrl -Headers $headers -Body $payload


After running the powershell script now check the portat it will be enabled

Overall, Remote Help in Microsoft Intune is a powerful tool for IT administrators, enabling them to quickly diagnose and fix issues on mobile devices, improving productivity and reducing downtime. If you’re using Microsoft Intune, be sure to take advantage of this powerful feature to improve your device management capabilities.

Useful LinksCredits
Update remoteAssistanceSettings – https://learn.microsoft.com/en-us/graph/api/intune-remoteassistance-remoteassistancesettings-update?view=graph-rest-betaMicrosof
Enabling Remote Help and Supporting Users with Intune – Microsoft Community HubMicrosoft

I hope you will find this helpful information for enabling Remote Help using PowerShell. Please let me know if I have missed any steps or details, and I will be happy to update the post.

Aresh Sarkari

Restrict Cloud Apps (ServiceNow, GitHub Enterprise, Atlassian Cloud & Office 365) access to Windows 365 Cloud PC/Azure Virtual Desktop

15 Dec

A good security practice would restrict the access of business-critical applications only to trusted devices within the organizations. On personal and untrusted devices, there should deny access to business applications. This strategy helps in Data Loss Prevention and company information compromise, which is vital in today’s landscape.

In our scenario, we will allow Access to Cloud Apps – ServiceNow, GitHub & Atlassian Cloud only on the Windows 365 Cloud PC/Azure Virtual Desktop (AVD) and all other devices will block access. To achieve this outcome, we shall be using Azure Active Directory (AAD) Conditional Access Policies & further use device filtering on “Cloud PC”


  • You have Enterprise Apps integrated with Azure Active Directory (ServiceNow, GitHub Enterprise, Atlassian Cloud & Office 365)
    • Make sure these applications are working with Azure AD credentials and assigned multi-factor authentication
  • Azure AD Group with end-users to whom you want to apply the restrictions
  • Necessary Azure AD P1 or P2 license

Portals on AAD Conditional Access Policy (CAP)

Following are all the portals where you can configure the CAP via different consoles. However, the outcome is going to be the same.

Microsoft Endpoint Manager admin Center (Microsoft Intune)

Azure Portal – Azure Active Directory – Security – Conditional Access

Microsoft Entra admin center

New Policy

Details of all the configurations we are entering within the policy and followed by screenshots:

  • Name of the CAP – Restrict CloudApps access to CPCs
  • Assignments
    • Users or workloads Identities – AAD group, called Win365-Users
    • Cloud apps or action
      • Include – Select – ServiceNow, GitHub Enterprise, Atlassian Cloud & Office 365
      • Exclude – Select – Windows 365, Azure Virtual Desktop and Microsoft Remote Desktop
    • Conditions – Filter for devices – We are selecting model ‘Cloud PC’
  • Access Controls – Block Access
  • Enable Policy – Report-only

AAD Group used for restrictions

Inlcude Cloud Apps (ServiceNow, GitHub Enterprise, Atlassian Cloud & Office 365)

Exclude Windows 365 and AVD

Conditions (Select Model Cloud PC)

Access Controls (Block Access)

Before rolling out in production at this phase, only use the report-only mode. Once satisfied with your testing, you can select Enable Policy – On. Final click on Create

Insights & Reporting

You can notice my user name shows the blocking policy is applying when I access the CloudApp -Office365 from a personal device.

I hope you will find this helpful information for restricting Cloud Apps access to only Cloud PC. Please let me know if I have missed any steps or details, and I will be happy to update the post.

Aresh Sarkari

SAML Authentication Flow – Azure Active Directory and VMware Workspace ONE Access

28 Sep

Many blogs discuss and show in detail how to integrate the Azure Active Directory (AAD) with VMware Workspace ONE Access (WoA) as a 3rd party IDP, and the following are my top post on that topic:

However, in this blog post, I would like to shed more light on the SAML Authentication Flow between the Azure Active Directory (Identity Provider) and VMware Workspace ONE Access (Service Provider). When designing the WoA and AAD integration, the below flow helped me understand what is happening behind the scenes, and I thought of sharing my knowledge with you all.

  • SAML Authentication Flow
  • AuthnRequest
  • Issuer
  • NameIDPolicy
  • RequestAuthnContext
  • SAML Response that AAD sends to WoA

#ProTip – I use a Chrome/Edge extension called SAML-tracer to inspect the SAML responses back and forth within the browser.

SAML Authentication Flow

The diagram below describes the single sign-on sequence. The VMware Workspace ONE Access (the service provider) uses an HTTP Redirect binding to pass an AuthnRequest (authentication request) element to Azure AD (the 3rd party identity provider in case of WoA). Azure AD then uses an HTTP post binding to post a Response element to the cloud service.

SAML Authentication Flow – AAD and WoA
S. No.Description Flow
1.End-user tries to access the VMware Workspace ONE Access portal
2.VMware Workspace ONE Access finds the identity provider to authenticate the user
3.VMware Workspace ONE Access generates a SAML 2.0 AuthnRequest and redirects the user’s browser to the Azure AD SAML single sign-on URL
4.If the end-user is not signed in, Azure AD authenticates the user using multi-factor authentication & generates a SAML token
5.Azure AD posts the SAML response to the WoA application via the user’s browser
6.VMware Workspace ONE Access verifies the SAML Response
7.VMware Workspace ONE Access completes the end-user sign-in and presents the desktop/app entitlements

Note – I have randomly created the GUID within the XML response just for demonstration purposes.


To request a end-user authentication, from WoA portal send an AuthnRequest element to Azure AD.  Following is the SAML SAML 2.0 AuthnRequest from WoA portal:

<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"


The Issuer element in an AuthnRequest must exactly match one of the ServicePrincipalNames in the cloud service in Azure AD. Typically, this is set to the App ID URI that is specified during application registration. (When the Enterprise Application is created under AAD portal)

<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">https://askaresh.com/SAAS/API/1.0/GET/metadata/sp.xml</saml:Issuer>


This element requests a particular name ID format in the response and is optional in AuthnRequest elements sent to Azure AD. A NameIdPolicy element looks like the following from WoA portal:

<samlp:NameIDPolicy AllowCreate="false"


The RequestedAuthnContext element specifies the desired authentication methods. It is optional in AuthnRequest elements sent to Azure AD. Azure AD supports AuthnContextClassRef values snippet from WoA portal:

    <saml:AuthnContextClassRef xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>

SAML Response AAD sends to WoA portal (Step 5-6)

The SAML Repsonse that AAD sends back to WoA portal:

<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
    <Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">https://sts.windows.net/se13edsadsadasdasdasd2342342dasdas/</Issuer>
        <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
    <Assertion xmlns="urn:oasis:names:tc:SAML:2.0:assertion"
        <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
                <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
                <Reference URI="#_54fb024a-f2f0-4495-99c7-f47e3fd37701">
                        <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
                        <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
                    <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
            <NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">aresh@askaresh.com</NameID>
            <SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
                <SubjectConfirmationData InResponseTo="_aasdwqewqsadsadasdsa-asdasd-asdasd"
        <Conditions NotBefore="2021-08-04T02:34:04.318Z"
            <Attribute Name="http://schemas.microsoft.com/identity/claims/tenantid">
            <Attribute Name="http://schemas.microsoft.com/identity/claims/objectidentifier">
            <Attribute Name="http://schemas.microsoft.com/identity/claims/identityprovider">
            <Attribute Name="http://schemas.microsoft.com/claims/authnmethodsreferences">
            <Attribute Name="email">
            <Attribute Name="ExternalID">
            <Attribute Name="userName">
            <Attribute Name="userPrincipalName">
        <AuthnStatement AuthnInstant="2021-08-04T02:38:59.239Z"

Reference Link

The above flow I learnt from an excellent Microsoft page – Azure Single Sign On SAML Protocol – Microsoft identity platform | Microsoft Docs. Without this article, it wouldn’t have been possible to understand this under the hood.

I hope you will find the above information helpful in your journey with AAD/WoA. A small request if you see any scope of improvisation or refinements. I hope you can share it back with me?

Aresh Sarkari