Close Menu
Peter Klapwijk – In The Cloud 24-7Peter Klapwijk – In The Cloud 24-7
    Facebook X (Twitter) Instagram
    Peter Klapwijk – In The Cloud 24-7Peter Klapwijk – In The Cloud 24-7
    • Home
    • Intune
    • Windows
      • Modern Workplace
    • macOS
    • Android
    • iOS
    • Automation
      • Logic Apps
      • Intune Monitoring
      • GitHub
    • Security
      • Passwordless
      • Security
    • Speaking
    • About me
    Peter Klapwijk – In The Cloud 24-7Peter Klapwijk – In The Cloud 24-7
    Home»Automation»Revoke user access in case of an emergency with a single click – on-premises AD integration
    Automation

    Revoke user access in case of an emergency with a single click – on-premises AD integration

    Peter KlapwijkBy Peter KlapwijkDecember 6, 2024Updated:February 14, 2025410 Mins Read

    Today I will show you how to revoke user access for an Active Directory user account in an automated way. This is a follow-up post to the initial blog post in which I described how to build automation to revoke user access in a single click. For example in case of employee termination or when a user account is compromised.

    If you have not already read that initial post, please do so as I’m describing in that post what the solution is, what actions the automated flow executes, and what the requirements are.

    The solution in short

    As described in the initial post the solution relies on Azure Logic Apps and Microsoft Graph. After a trigger, the flow executes several graph queries to initiate actions in Entra ID and Microsoft Intune to disable the user account, disable device accounts and additional actions.

    We expand this solution with Microsofts API-driven provisioning to on-premises Active Directory solution. This solution uses APIs to automate the creation, management, and deletion of user accounts and other directory objects within an on-premises AD environment. As this solution uses an API, we can integrate that into our Logic App flow to disable an on-prem user account.

    This solution contains two parts, an Enterprise Application in Azure and a connector that runs on an on-prem server with access to a Domain Controller.

    Actions taken by the flow

    If you implement the initial flow and expand the flow by the steps I later describe in this post, these are the actions the flow executes;

    • Disable user account  (in Entra ID and -on-prem AD)
    • Reset password 
    • Revoke sign-in sessions 
    • Delete authentication methods 
    • Disable Windows devices in Entra ID 
    • Reboot Windows device 
    • Retire Android, iOS and macOS devices 

    Requirements 

    Please refer to the initial post for a more detailed description of the requirements. This flow adds the need to assign two additional permissions to our managed identity:
    SynchronizationData-User.Upload
    AuditLog.Read.All

    This means our managed identity needs to be assigned (at least) the User administrator role and these permissions:
    Device.ReadWrite.All 
    DeviceManagementManagedDevices.PrivilegedOperations.All 
    DeviceManagementManagedDevices.Read.All 
    User.ReadWrite.All 
    UserAuthenticationMethod.ReadWrite.All
    SynchronizationData-User.Upload
    AuditLog.Read.All

    Besides that using the API-driven provisioning solution adds a license requirement. This feature is licensed under the Entra ID P1/P2 license.

    Setup API-driven provisioning to on-premises Active Directory

    We start the update from our red button solution by setting up the Enterprise Application. Therefore sign in to the Entra or Azure Portal and browse to Enterprise Applications.
    Click New application.

    Search for API-driven and select API-driven provisioning to on-premises Active Directory.

    Give the application a name and click Create.

    Open the app when it is created and browse to the Provisioning tab.

    On the provisioning tab, select Automatic as Provisioning mode.
    This allows us to download the connector agent we need to install on an on-premises server.

    Download the agent and switch to an on-prem server on which the Microsoft Entra provisioning agent can be installed.

    Select HR-driven provisioning.

    You will be asked to authenticate to Entra ID, sign in with an account with at least the Hybrid Identity Administrator role.

    After the authentication was successful a group managed service account needs to be created, therefore provide domain admin credentials.

    The configured domain is listed when connected to the Active Directory.

    Finishing up the configuration takes a few minutes.

    That’s all to configure the provisioning agent. Switch back to the Entra portal to configure the cloud part.

    Fill in the default OU for new users and you should be able to select the domain as the connector is installed.

    From this view you can also view the on-premises agents and test the connection.

    On the same tab, we also find mappings if we scroll down a little.

    The default mapping is done on the employeeID, but this can be changed to your needs. In the example of this blog post, I stick with the employeeID. This means I need to specify the employeeID later on in my Graph call to disable the on-prem user account.

    Don’t forget the Save button on the provisioning tab to finish the configuration!

    Open the Overview tab. Here we can start provisioning (1).

    Here we also find the Provisioning API Endpoint (2). This is the API endpoint we are going to use in our Logic Apps flow.

    Expanding the Logic Apps flow

    We are going to expand the existing Logic Apps flow created in the previous post (also available on GitHub).

    First, have a quick look at the Graph call and some details on the JSON we will use in the Logic Apps flow.
    As it’s a Microsoft Graph API call, we can also run the call using Microsoft Graph Explorer.

    In the URI field we enter the Provisioning API we found in the previous step.
    The body contains the values we want to change, in our case we specify the externalId (which is mapped to employeeID) and active (as we want to change that status to false to disable the AD user account). And we see the method, which is POST.

    The format of this information (payload) is in JSON SCIM format;

    {
      "schemas": [
        "urn:ietf:params:scim:api:messages:2.0:BulkRequest"
      ],
      "Operations": [
        {
          "method": "POST",
          "bulkId": "00aa00aa-bb11-cc22-dd33-44ee44ee44ee",
          "path": "/Users",
          "data": {
            "schemas": [
              "urn:ietf:params:scim:schemas:core:2.0:User",
              "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"
            ],
            "externalId": "0005",
            "active": false
          }
        }
      ],
      "failOnErrors": null
    }
    

    We also need to enter a request header as we need to specify we are using SCIM/ JSON format in our API call;

    Content-Type – application/scim+json

    Let’s go start editing our Logic Apps flow!

    We have several Initialize variable actions at the beginning of the flow, we are going to add another one for the disable user account actions. We do that to store the result of the disable action, as I disable the user account in AD and Entra ID, to not have to wait for a sync.

    Above the existing HTTP action that disables the user account in Entra ID, we add a new HTTP action.

    We are first going to get some more user details from the user which are stored in Entra ID, including the onPremisesSyncEnabled.
    We add an HTTP GET Action to the flow with the below URI:

    https://graph.microsoft.com/v1.0/users/[UserPrincipalName]?$select=id,userPrincipalName,displayName,givenName,surname,employeeId,onPremisesSyncEnabled
    

    Replace [UserPrincipalName] with the dynamic content value of the When an item is created action. And don’t forget to select the Authentication Type!

    We need to Parse the output of the HTTP action.

    This is the schema;

    {
        "type": "object",
        "properties": {
            "@@odata.context": {
                "type": "string"
            },
            "id": {
                "type": "string"
            },
            "userPrincipalName": {
                "type": "string"
            },
            "displayName": {
                "type": "string"
            },
            "givenName": {
                "type": "string"
            },
            "surname": {
                "type": "string"
            },
            "employeeId": {
                "type": "string"
            },
            "onPremisesSyncEnabled": {
                "type": [
                    "boolean",
                    "null"
                ]
            }
        }
    }

    Notice that I changed the onPremisesSyncEnabled type to boolean and null. This is because the value is/ could be null (instead of false) for an Entra ID user account that is not synced.

    Because of that, we need to use an expression to use the onPremisesSyncEnabled value, instead that we just easily use it as dynamic content from the Parse JSON action.

    We add a Condition action to the flow, to split up the flow between AD (synced) accounts and Entra ID accounts. This way we can use the flow in an environment with synced and non-synced accounts.

    In the left field we add the below expression to get the output value of onPremisesSyncEnabled;

    body('Parse_JSON')?['onPremisesSyncEnabled']

    We select is equal to from the drop-down list and enter true in the right field.

    We can now drag the existing HTTP action that disables the user account in Entra ID under True. Right click the action, choose Copy action. When you now click the plus button under False, you can paste to action.

    Under True, above the HTTP action click the plus button to add a parallel branch.

    This allows us to execute two HTTP actions at the same time when the account is synced. It disables the user account in the on-prem AD and in Entra ID.

    In the URI field of the new HTTP action paste the API Provisioning endpoint. As method select POST. And add the header:
    Content-Type – application/scim+json

    In the body field add the JSON I shared above. Replace the number for externalID with the employeeId.

    Add an Condition under True, under one of the HTTP action. On the Settings tab, make sure to also select the second HTTP action and Has failed. This way we make sure the condition runs even when one of the two HTTP actions fails.

    Change AND in OR.
    Add the body value from both HTTP actions in the left fields. Select is equal to from the drop-down list. Pay attention for the value in the right fields. The HTTP action to disable the on-prem account has a success status code 200 and the Entra ID action 204.

    Like we have done for other actions in the flow before (like described in the previous article), we add Append to string actions under the Condition.
    Select varDisableUserStatus and add Success in the action under True and Failed under False.

    Do the same under the one HTTP action to only disable the user account in Entra ID.
    Add a condition and two Append to string actions.

    Below the Append to string actions, outside of the condition to check the onPremisesSyncEnabled, add a Compose action.
    Add the varDisableUserStatus in the Inputs field.

    We have the existing Update item actions. We need to add the Outputs from the Compose action in the left field of both actions.

    Updating the flow is finished. We are ready to also disable on-premises user accounts!

    Disablement of the on-premises user account

    I have an account that is created in my on-premises Active Directory called onprem.user@peterklapwijk.com. As you can see it’s not in the OU I previously specified in the Enterprise app, that setting is only the default OU for new accounts (but that’s outside of this article).

    This account is synced to Entra ID and currently enabled.

    And the employeeID is 0005.

    After we initiated the red button action, the user account is disabled in the on-premises AD and Entra ID.
    When we open the Provisioning logs, which is found under the Enterprise application, we see an Update action with an Success status. Under identity we see the employeeID.
    If we click on the action we get some more information, like on the Modified Properties tab, it shows accountDisabled is changed to True.

    The account is indeed disabled in the on-prem AD.

    And the account is disabled in Entra ID as well.

    The API-driven provisioning to on-premises Active Directory application is very easy to setup. With only installing an easy to setup agent and some steps in the Enterprise app, we are able to connect from the cloud to our on-premises environment and expand the existing red button flow to disable on-prem user accounts.

    The JSON template to deploy the flow can be found on GitHub including a script to assign permissions to the Managed Identity.

    Hit the below button to directly upload the template to your Azure environment.

    Thanks for reading and happy testing 🙂

    Automation Entra Intune Logic Apps Microsoft Defender Microsoft Defender for Endpoint Microsoft Endpoint Manager Power Automate Security
    Share. Facebook Twitter LinkedIn Email WhatsApp
    Peter Klapwijk
    • Website
    • X (Twitter)
    • LinkedIn

    Peter is a Security (Intune) MVP since 2020 and is working as Modern Workplace Engineer at Wortell in The Netherlands. He has more than 15 years of experience in IT, with a strong focus on Microsoft technologies like Microsoft Intune, Windows, and (low-code) automation.

    Related Posts

    Revoke user access in case of an emergency with a single click 

    November 15, 2024

    Azure Logic Apps error; the template language expression is not valid

    November 12, 2024

    Get notified of new Microsoft EPM elevation requests

    August 28, 2024
    View 4 Comments

    4 Comments

    1. Andy on January 7, 2025 13:32

      Hi Peter. Great article, and something I am currently working on where I feel this could really benefit us. A question I do have, as I noticed the provisioning OU was different to where your test account resides. I assume the provisioning OU is just a means to configure the enterprise app API. Would this OU need to be excluded from Entra ID Connect sync, as my understanding is you can have both EID-C and Cloud Sync in place, but not for the same OU’s / objects.

      In my environment we already have EID-C in place, with specific OUs selected to sync those users to Entra.

      Reply
      • Peter Klapwijk on January 7, 2025 13:53

        Hi Andy,

        The OU filled in is indeed only a provisioning OU. As long as you can make a match, like I do on the default employeeID, the user account can be located on other OUs. I’m not aware of any requirement to exclude the provisioning OU. I have my provisioning OU synced with Entra ID Connect sync.

        Reply
    2. Andy on January 10, 2025 12:29

      Hi Peter, thanks for the reply. Thought I’d replied back but clearly not.

      What about using a different attribute? I’ve baked this config into an existing Logic App I have, and it works with employeeID, but if I switch the mapping to userPrincipalName, or displayName, I get and error in provisioning which is ‘
      Source identifier of an entry cannot be empty’. I’ve tried the expression mapping of UPN and even tried direct UPN to UPN but I get the same error.

      Reply
    3. Andy on January 14, 2025 09:46

      Don’t worry, I got it working. It was the primary key in the advanced API attribute mapping settings, within the enterprise app.

      Reply
    Leave A Reply Cancel Reply

    Peter Klapwijk

    Hi! Welcome to my blog post.
    I hope you enjoy reading my articles.

    Hit the About Me button to get in contact with me or leave a comment.

    Awards
    Sponsor
    Latest Posts

    Managing Windows 365 Link devices with Intune

    October 24, 2025

    Hard drive and partitions are not shown while installing Windows

    October 14, 2025

    Intune compliance for Windows 365 Cloud PCs

    September 12, 2025

    Intune connector for Active Directory configuration error

    August 29, 2025
    follow me
    • Twitter 4.8K
    • LinkedIn 6.1K
    • YouTube
    • Bluesky 1.5K
    Tags
    Administrative Templates Android Automation Autopilot Azure Azure AD Browser Conditional Access Edge EMS Exchange Online Feitian FIDO2 Flow Graph Graph API Identity Management Intune Intune Monitoring iOS KIOSK Logic Apps macOS MEM MEMMonitoring Microsoft 365 Microsoft Defender Microsoft Edge Microsoft Endpoint Manager Modern Workplace Office 365 OneDrive for Business Outlook Passwordless PowerApps Power Automate Security SharePoint Online Windows Windows 10 Windows10 Windows 11 Windows 365 Windows Autopilot Windows Update
    Awards
    Sponsor
    Follow me on Twitter
    Tweets by inthecloud_247
    Tags
    Administrative Templates Android Automation Autopilot Azure Azure AD Browser Conditional Access Edge EMS Exchange Online Feitian FIDO2 Flow Graph Graph API Identity Management Intune Intune Monitoring iOS KIOSK Logic Apps macOS MEM MEMMonitoring Microsoft 365 Microsoft Defender Microsoft Edge Microsoft Endpoint Manager Modern Workplace Office 365 OneDrive for Business Outlook Passwordless PowerApps Power Automate Security SharePoint Online Windows Windows 10 Windows10 Windows 11 Windows 365 Windows Autopilot Windows Update
    Archives
    Peter Klapwijk

    Hi! Welcome to my blog post.
    I hope you enjoy reading my articles.

    Hit the About Me button to get in contact with me or leave a comment.

    Copy right

    This information is provided “AS IS” with no warranties, confers no rights and is not supported by the authors, or In The Cloud 24-7.

     

    Copyright © 2025 by In The Cloud 24-7/ Peter Klapwijk. All rights reserved, No part of the information on this web site may be reproduced or posted in any form or by any means without the prior written permission of the publisher.

    Shorthand; Don’t pass off my work as yours, it’s not nice.

    Recent Comments
    • John on Connect to Azure file shares with Microsoft Entra Private Access
    • Luis on Application installation issues; Download pending
    • AndrewWak on Issues syncing SharePoint Online libraries with OneDrive for Mac
    • Peter Klapwijk on Deploy Microsoft Defender updates in deployment rings
    • Magnus on Deploy Microsoft Defender updates in deployment rings
    most popular

    Application installation issues; Download pending

    October 1, 2024

    How to change the Windows 11 language with Intune

    November 11, 2022

    Restrict which users can logon into a Windows 10 device with Microsoft Intune

    April 11, 2020

    How I solved a strange Kerberos issue

    December 12, 2024
    Recent Comments
    • John on Connect to Azure file shares with Microsoft Entra Private Access
    • Luis on Application installation issues; Download pending
    • AndrewWak on Issues syncing SharePoint Online libraries with OneDrive for Mac
    • Peter Klapwijk on Deploy Microsoft Defender updates in deployment rings
    • Magnus on Deploy Microsoft Defender updates in deployment rings
    Copy right

    This information is provided “AS IS” with no warranties, confers no rights and is not supported by the authors, or In The Cloud 24-7.

    Copyright © 2023 by In The Cloud 24-7/ Peter Klapwijk. All rights reserved. No part of the information on this web site may be reproduced or posted in any form or by any means without the prior written permission of the publisher.

    Shorthand: Don’t pass off my work as yours, it’s not nice.

    Peter Klapwijk – In The Cloud 24-7
    X (Twitter) LinkedIn YouTube RSS Bluesky
    © 2025 ThemeSphere. Designed by ThemeSphere.

    Type above and press Enter to search. Press Esc to cancel.

    Manage Cookie Consent
    To provide the best experiences, we use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us to process data such as browsing behavior or unique IDs on this site. Not consenting or withdrawing consent, may adversely affect certain features and functions.
    Functional Always active
    The technical storage or access is strictly necessary for the legitimate purpose of enabling the use of a specific service explicitly requested by the subscriber or user, or for the sole purpose of carrying out the transmission of a communication over an electronic communications network.
    Preferences
    The technical storage or access is necessary for the legitimate purpose of storing preferences that are not requested by the subscriber or user.
    Statistics
    The technical storage or access that is used exclusively for statistical purposes. The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
    Marketing
    The technical storage or access is required to create user profiles to send advertising, or to track the user on a website or across several websites for similar marketing purposes.
    Manage options Manage services Manage {vendor_count} vendors Read more about these purposes
    View preferences
    {title} {title} {title}