Microsoft Entra Privileged Identity Management (PIM) allows administrators to manage role assignments efficiently, ensuring that users have the necessary permissions only when needed. By following a few simple steps, administrators can make users eligible for specific roles, activate roles as required, and manage both built-in and custom roles. This process enhances security by minimizing the duration and scope of privileged access, making it a crucial tool for maintaining a secure and compliant environment. In this article, we explore how to read a user's Microsoft Entra roles and history using PIM and the Microsoft Graph REST API.
You can find a description of the Microsoft Graph methods at Manage Microsoft Entra role assignments using PIM APIs.
PIM sample
In these samples, we want to get all PIM roles of a given user. Administrators can see and define the allowed roles for a user. The user can use the Azure portal at My roles | Microsoft Entra roles to see and activate his roles, as here.
The user has 5 eligible assignments. For example, he can activate the Power Platform Administrator role.
The Azure portal reloads, and the use gets the permissions defined in that activated role. The tab Active assignments shows the current roles.
Here we see that the Power Platform Administrator role is valid for an hour, while the Global Reader is a permanent role.
Get eligible role assignments of a user
In these samples, we want to get all PIM roles of a given user. Here the UserId is “a234…”. We can use Microsoft Graph REST API and filter for the principalId, and – this is cool - we can expand the roleDefinition to see what role the user can get:
https://graph.microsoft.com/v1.0/roleManagement/directory/roleEligibilitySchedules?$filter=principalId+eq+'a2345678-b345-c678-d901-e9876543210f'&$expand=roleDefinition
Note that your user or app requires at least the RoleManagement.Read.Directory or RoleManagement.ReadWrite.Directory permission.
So, the result shows all eligible role assignments. Stripped down to the Power Platform Administrator role, the JSON result looks as here:
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#roleManagement/directory/roleEligibilitySchedules(roleDefinition())",
"@microsoft.graph.tips": "Use $select to choose only the properties your app needs, as this can lead to performance improvements. For example: GET roleManagement/directory/roleEligibilitySchedules?$select=memberType,scheduleInfo",
"value": [
...{
"id": "<someid>",
"principalId": "a2345678-b345-c678-d901-e9876543210f",
"roleDefinitionId": "11648597-926c-4cf3-9c36-bcebb0ba8dcc",
"directoryScopeId": "/",
"appScopeId": null,
"createdUsing": "<someid>",
"createdDateTime": "2022-08-28T09:01:42.257Z",
"modifiedDateTime": "0001-01-01T08:00:00Z",
"status": "Provisioned",
"memberType": "Direct",
"scheduleInfo": {
"startDateTime": "2022-08-28T09:01:42.257Z",
"recurrence": null,
"expiration": {
"type": "noExpiration",
"endDateTime": null,
"duration": null
}
},
"roleDefinition": {
"id": "11648597-926c-4cf3-9c36-bcebb0ba8dcc",
"description": "",
"displayName": "Power Platform Administrator",
"isBuiltIn": true,
"isEnabled": true,
"templateId": "11648597-926c-4cf3-9c36-bcebb0ba8dcc",
"version": null,
"resourceScopes": [],
"rolePermissions": []
}
}
] }
principalId is the UserId, and roleDefinitionId is the eligbile role. Because we used expand we also see the name of the role in readable plain text.
All eligible roles are listed. Wait, all? Well, no! the permanent Global Reader role is missing.
Note: To get the roles assignment definition and the permissions, you can use the following request:
https://graph.microsoft.com/v1.0/roleManagement/directory/roleDefinitions?$filter=id eq '11648597-926c-4cf3-9c36-bcebb0ba8dcc'
This returns also the allowedResourceActions and inheritsPermissionsFrom permissions.
Get Active assignments
https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignmentSchedules?$filter=principalId+eq+'a2345678-b345-c678-d901-e9876543210f'&$expand=roleDefinition
The result shows the 2 currently active roles of the user: The Power Platform Administrator role which is valid for 1 hour, and the permanent Global Reader role.
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#roleManagement/directory/roleAssignmentSchedules(roleDefinition())",
"@microsoft.graph.tips": "Use $select to choose only the properties your app needs, as this can lead to performance improvements. For example: GET roleManagement/directory/roleAssignmentSchedules?$select=assignmentType,memberType",
"value": [
{
"id": "<someid>",
"principalId": "a2345678-b345-c678-d901-e9876543210f",
"roleDefinitionId": "11648597-926c-4cf3-9c36-bcebb0ba8dcc",
"directoryScopeId": "/",
"appScopeId": null,
"createdUsing": "<someid>",
"createdDateTime": "2024-08-03T13:06:18.927Z",
"modifiedDateTime": null,
"status": "Provisioned",
"assignmentType": "Activated",
"memberType": "Direct",
"scheduleInfo": {
"startDateTime": "2024-08-03T13:06:18.927Z",
"recurrence": null,
"expiration": {
"type": "afterDateTime",
"endDateTime": "2024-08-03T14:06:18.6Z",
"duration": null
}
},
"roleDefinition": {
"id": "11648597-926c-4cf3-9c36-bcebb0ba8dcc",
"description": "",
"displayName": "Power Platform Administrator",
"isBuiltIn": true,
"isEnabled": true,
"templateId": "11648597-926c-4cf3-9c36-bcebb0ba8dcc",
"version": null,
"resourceScopes": [],
"rolePermissions": []
}
},
{
"id": "<someid>",
"principalId": "a2345678-b345-c678-d901-e9876543210f",
"roleDefinitionId": "f2ef992c-3afb-46b9-b7cf-a126ee74c451",
"directoryScopeId": "/",
"appScopeId": null,
"createdUsing": null,
"createdDateTime": null,
"modifiedDateTime": null,
"status": "Provisioned",
"assignmentType": "Assigned",
"memberType": "Direct",
"scheduleInfo": {
"startDateTime": "2024-08-03T13:26:55.3091405Z",
"recurrence": null,
"expiration": {
"type": "noExpiration",
"endDateTime": null,
"duration": null
}
},
"roleDefinition": {
"id": "f2ef992c-3afb-46b9-b7cf-a126ee74c451",
"description": "",
"displayName": "Global Reader",
"isBuiltIn": true,
"isEnabled": true,
"templateId": "f2ef992c-3afb-46b9-b7cf-a126ee74c451",
"version": null,
"resourceScopes": [],
"rolePermissions": []
}
}
] }
Note that the StartDate contains the date when the role started for the temporary role, and the current date for the permanent role.
So the active role assignments can be queries as above and show also the permanent roles.
Get the PIM history
The following request returns when the user has used the PIM roles:
https://graph.microsoft.com/v1.0/roleManagement/directory/roleAssignmentScheduleRequests?$filter=principalId+eq+'a2345678-b345-c678-d901-e9876543210f'
The stripped result looks as here:
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#roleManagement/directory/roleAssignmentScheduleRequests",
"@microsoft.graph.tips": "Use $select to choose only the properties your app needs, as this can lead to performance improvements. For example: GET roleManagement/directory/roleAssignmentScheduleRequests?$select=action,appScopeId",
"value": [
...
{
"id": "<someid>",
"status": "Provisioned",
"createdDateTime": "2024-08-03T13:06:18.577Z",
"completedDateTime": "2024-08-03T13:06:18.6Z",
"approvalId": null,
"customData": null,
"action": "selfActivate",
"principalId": "a2345678-b345-c678-d901-e9876543210f",
"roleDefinitionId": "11648597-926c-4cf3-9c36-bcebb0ba8dcc",
"directoryScopeId": "/",
"appScopeId": null,
"isValidationOnly": false,
"targetScheduleId": "<someid>",
"justification": "Need to configure GT365 Power Platform tasks",
"createdBy": {
"application": null,
"device": null,
"user": {
"displayName": null,
"id": "a2345678-b345-c678-d901-e9876543210f"
}
},
"scheduleInfo": {
"startDateTime": "2024-08-03T13:06:18.5992359Z",
"recurrence": null,
"expiration": {
"type": "afterDuration",
"endDateTime": null,
"duration": "PT1H"
}
},
"ticketInfo": {
"ticketNumber": "",
"ticketSystem": ""
}
},
...
] }
The roleAssignmentScheduleRequests method returns the last activations.
The status property shows the activation (Provisioned) or deactivation (Revoked) of a role. If the action is selfActivate, the user has activated the role by himself. selfDeactivate means the use has ended the role activation himself. adminRemove means that an admin has removed the role, etc.
By following these steps using the Microsoft Graph API, administrators can get the PIM role permission assigned to an user for further processing or reports. This functionality is part of the governancetoolkit365.com as well.