Building a Custom Consent Policy from Scratch

To create a custom consent policy and understand how it works, you need to decide who can approve app permissions (User/Group). Then, create a custom role that links users or groups to the custom consent policy. This policy is defined by the scope of inclusions or exclusions for apps or permission types and specifies which app permissions can be approved.
In the next steps, you will notice that the process doesn't follow the same logical order, but you will start by:
Creating the Custom consent policy first.
Defining the scope of the policy to include/exclude specific apps, permissions, etc.
Creating the custom role.
Assigning the custom role to a group or user who will later consent to the permissions.
Below, we will continue to build a custom policy for an app. For example, creating a policy that allows users to consent only to the mail.send permission, enabling the contoso app to send emails from the user's mailbox using the API. This is just an example; you might want to make it more strict or more lenient depending on your specific situation.
Note: This is just an example, will not be accurate for you. You need to obtain and use the correct IDs for your tenant.
Prerequisites and Initial Setup
Before creating custom consent policies, ensure you have the appropiate permissions.
Required Roles:
Privileged Role Administrator directory role
Custom directory role with necessary permissions to manage app consent policies
Microsoft Graph app role (application permission)
Policy.ReadWrite.PermissionGrant
PowerShell Module Installation:
# Install Microsoft Graph PowerShell module
Install-Module Microsoft.Graph -Scope CurrentUser
# Connect to the Graph Module
Connect-MgGraph -Scopes "Policy.ReadWrite.PermissionGrant", "RoleManagement.ReadWrite.Directory","Group.ReadWrite.All", "Application.Read.All"
Step-by-Step Policy Creation Process
Step 1: Prepare the Object IDs
Unfortunetelly Graph api uses a lot of Id not text based identification therefore, you need to get the related Object Ids that you will use later.
# Get the application service principal ID
$ContosoApp = Get-MgServicePrincipal -Filter "displayName eq 'Contoso'"
# Get Microsoft Graph service principal for permission IDs
$GraphApp = Get-MgServicePrincipal -Filter "servicePrincipalNames/any(n:n eq 'https://graph.microsoft.com/')"
# Get the specific permission IDs for Mail.Send and User.Read
$MailSendPermission = $GraphApp.Oauth2PermissionScopes | Where-Object {$_.Value -eq "Mail.Send"}
$UserReadPermission = $GraphApp.Oauth2PermissionScopes | Where-Object {$_.Value -eq "User.Read"}
Step 2: Create the Base Consent Policy
Create a new empty consent policy that will serve as the foundation:
New-MgPolicyPermissionGrantPolicy `
-Id "Contoso-restricted-policy" `
-DisplayName "Contoso Application Restricted Access Policy" `
-Description "Custom policy to restrict Contoso application access to Mail.Send and User.Read permissions for specific user groups"
Step 3: Define Include Conditions
here is most of the configuration take place. you can define what to allow or what to exclude by using exclude scope instead of include. in this example, we will add include conditions that specify when consent should be allowed. For this example, we need to scope it for a specific application and a specific permissions only:
New-MgPolicyPermissionGrantPolicyInclude `
-PermissionGrantPolicyId "Contoso-restricted-policy" ` # The name of the policy we created earlier.
-PermissionType "delegated" `
-ResourceApplication $GraphApp.AppId ` # Graph api Id got from in step 1
-Permissions @($MailSendPermission.Id, $UserReadPermission.Id) `# The permissions IDs not the name that we got earlier in step 1.
-ClientApplicationIds @($ContosoApp.AppId) # This the ID of the app you want to use.
#here is other example without variable:
New-MgPolicyPermissionGrantPolicyInclude `
-PermissionGrantPolicyId "Contoso-restricted-policy" `
-ResourceApplication "00000003-0000-0000-c000-000000000000" `
-Permissions @{e383f46e-2787-4529-855e-0e479a3ffac0, e1fe6dd8-ba31-4d61-89e7-88639da4683d} `
-ClientApplicationIds "29106cd9-d63e-40db-as30-2fd98c6803ad"
However, you might scope it for only low classified permissions, or define the tenant to allow only apps from certin tenant or only from yours etc. here is a list of the supported Parameters: Manage app consent policies - Microsoft Entra ID | Microsoft Learn
Creating and Assigning Custom Roles
Step 4: Create Custom Role with Consent Permissions
Create a custom directory role that includes the consent policy. To allow users to grant consent to applications on behalf of themselves (user consent), subject to an app consent policy.
“microsoft.directory/servicePrincipals/managePermissionGrantsForSelf.{id}
“
Where {id}
is replaced by the ID of an app consent policy from step 2. In our example here the id is: Contoso-restricted-policy
"microsoft.directory/servicePrincipals/managePermissionGrantsForSelf.Contoso-restricted-policy"
$params = @{
description = "Allows users to consent to Contoso application with restricted permissions"
displayName = "Contoso Application Consent Manager"
rolePermissions = @(
@{
allowedResourceActions = @(
"microsoft.directory/servicePrincipals/managePermissionGrantsForSelf.Contoso-restricted-policy"
)
}
)
isEnabled = $true
}
New-MgRoleManagementDirectoryRoleDefinition -BodyParameter $params
Step 6: Assign Custom Role to Security Group
Assign the custom role to the security group containing authorized users by getting the Group Id using Get-MgGroup or Get-MgUser for users.
powershell# Get the security group
$ContosoGroup = Get-MgGroup -Filter "displayName eq 'Contoso Application Users'"
# Create role assignment for the group
New-MgRoleManagementDirectoryRoleAssignment `
-RoleDefinitionId $CustomRole.Id `
-PrincipalId $ContosoGroup.Id `
-DirectoryScopeId "/"
Validation and Testing
Step 9: Validate Policy Configuration
Verify that the policy is correctly configured:
powershell# Review the complete policy configuration
Get-MgPolicyPermissionGrantPolicy -PermissionGrantPolicyId "Contoso-restricted-policy" | fl
# Check include conditions
Get-MgPolicyPermissionGrantPolicyInclude -PermissionGrantPolicyId "Contoso-restricted-policy" | fl
# Verify role assignment then expand the RolePermissions.
Get-MgRoleManagementDirectoryRoleDefinition -Filter "displayName eq 'Scoped App Consent - Sendas Policy'" | fl
Get-MgRoleManagementDirectoryRoleDefinition -Filter "displayName eq 'Scoped App Consent - Sendas Policy'" | select -ExpandProperty RolePermissions | fl
The Role assignmet can be reviewed in GUI under Entra admin Center > Identity, Roles and admin:
Step 10: Test Policy Functionality
Test the policy with a user account in the authorized group:
Sign in as a user assigned to the "Contoso Application Users" group
Attempt to consent to the Contoso application
Verify that only Mail.Send and User.Read permissions can be consented to
Confirm that requests for additional permissions are blocked
Troubleshooting Common Issues
Policy Not Working:
Start Troubleshooting by reviewing the Signin Logs where you will get usually much details that will help you with troubleshooting like the APP ID, user ID, and the exact error. which can be used to compare against the policies.
Verify that the custom role is correctly assigned and that users are members of the appropriate security group.
Confirm if the role is active.
Verify that the target application (Contoso) exists in the tenant and has the correct display name or App ID same as in the policy.
Conclusion
Implementing custom app consent policies in Microsoft Entra ID requires careful planning and execution, but provides essential security controls for modern organizations. The example Contoso implementation demonstrates how to create granular consent policies that balance security requirements with user productivity. By following the step-by-step approach outlined in this guide, administrators can implement robust consent management systems that protect organizational data while enabling necessary business processes.
The investment in time and complexity required to implement custom consent policies is justified by the significant security benefits they provide. As threat actors continue to exploit consent-based attacks, organizations that implement proactive consent management will be better positioned to protect their data and maintain compliance with regulatory requirements.
Subscribe to my newsletter
Read articles from Mustafa Nassar directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
