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
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.
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.
Thanks for reading and happy testing 🙂
PS; I will share the flow with the additional steps soon on my GitHub repo next to the existing ones.