This solution automates Endpoint Privilege Management (EPM) approval workflows using Azure Logic Apps and Microsoft Teams. When elevation requests require approval in Microsoft Intune, an Adaptive Card is automatically posted to a Teams channel, allowing approvers to approve or deny requests directly from Teams.
┌─────────────────────────────────────────────────────────────────┐
│ EPM Approval Workflow │
└─────────────────────────────────────────────────────────────────┘
1. Logic App (Recurrence Trigger - every 5 minutes)
│
├──> GET Microsoft Graph API
│ /deviceManagement/elevationRequests
│
├──> Filter requests with status = "supportApproved"
│
├──> For each approved request:
│ └──> Post Adaptive Card to Teams channel
│ ├──> Approve button
│ └──> Deny button
│
└──> When button clicked:
└──> PATCH elevation request via Graph API
- Automated Polling: Checks for new EPM elevation requests every 5 minutes
- Teams Integration: Posts Adaptive Cards with rich request details
- One-Click Approval: Approve or deny requests directly from Teams
- Managed Identity: Secure authentication to Microsoft Graph API
- Least Privilege: Uses minimal required Graph API permissions
- Monitoring: Integrated diagnostics with Log Analytics
- Secure by Design: No secrets stored, outputs secured
- Azure subscription with permissions to create:
- Resource Groups
- Logic Apps
- Managed Identities
- API Connections
- Log Analytics Workspace (optional, for diagnostics)
- Microsoft Intune subscription with EPM configured
- Microsoft Teams with a dedicated channel for approvals
- Global Administrator or Intune Administrator role
- Azure CLI or Azure PowerShell
- Bicep CLI (version 0.20.0 or later)
- Visual Studio Code with Bicep extension (recommended)
-
Get Teams Team ID:
- Open Microsoft Teams
- Click the "..." menu next to your team name
- Select "Get link to team"
- Extract the
groupIdfrom the URL:https://teams.microsoft.com/l/team/19%3a...%40thread.tacv2/conversations?groupId=TEAM_ID&tenantId=...
-
Get Teams Channel ID:
- Right-click the channel name
- Select "Get link to channel"
- Extract the channel ID from the URL (URL decoded portion after
/channel/)
Edit main.bicepparam and update:
# Required Parameters
param teamsTeamId = 'YOUR_TEAMS_TEAM_ID'
param teamsChannelId = 'YOUR_TEAMS_CHANNEL_ID'
# OAuth Authentication (optional - defaults to current tenant)
param tenantId = '' # Leave empty to use deployment tenant
param graphApiAudience = 'https://graph.microsoft.com' # Default, usually no change needed
# Diagnostics (optional)
param logAnalyticsWorkspaceId = '/subscriptions/.../workspaces/YOUR_WORKSPACE'Note on OAuth Authentication: The Logic App uses Azure AD OAuth with the Managed Identity to authenticate to Microsoft Graph API. The tenantId parameter defaults to your current deployment tenant, and graphApiAudience should remain as https://graph.microsoft.com unless you have specific requirements.
The deployment script automates everything:
# Run the automated deployment script
.\deploy.ps1
# Optional: Specify custom resource group and location
.\deploy.ps1 -ResourceGroupName "rg-epm-approval" -Location "westeurope"
# Optional: Skip Graph API permissions (for manual setup later)
.\deploy.ps1 -SkipGraphPermissions
# Optional: Preview changes without deploying
.\deploy.ps1 -WhatIfThe script will automatically:
- Check prerequisites (Azure CLI, Bicep, login status)
- Create the resource group if it doesn't exist
- Deploy the Bicep template (Logic App, Managed Identity, API Connections)
- Assign Microsoft Graph API permissions to the Managed Identity
- Open browser for Teams connection authorization
- Display deployment summary and next steps
What happens during deployment:
-
Graph API Permissions: The script uses Microsoft Graph PowerShell to automatically assign:
DeviceManagementConfiguration.ReadWrite.All- To read and update elevation requestsDeviceManagementManagedDevices.Read.All- To read device information
-
Teams Connection: The script opens a consent link in your browser where you must sign in to authorize the Teams connection with your account
After deployment completes, verify everything is set up correctly.
- Go to Azure Portal → Resource Groups →
rg-epm-approval - Find the Logic App → API Connections →
teams-connection - Click "Edit API connection"
- Click "Authorize" and sign in with your Microsoft 365 account
- Save the connection
- Create an EPM elevation request in Intune that requires approval
- Wait for the Logic App to run (check after 5 minutes)
- Verify the Adaptive Card appears in your Teams channel
- Click "Approve" or "Deny" to test the workflow
Change how often the Logic App checks for new requests:
param recurrenceIntervalMinutes = 5 // Check every 5 minutesBy default, the beta endpoint is used (required for EPM):
param graphApiBaseUrl = 'https://graph.microsoft.com/beta'# Azure Portal
Navigate to: Logic App → Overview → Runs history
# Azure CLI
az logicapp show-run-history --resource-group "rg-epm-approval" --name "logic-epm-approval"# In Log Analytics Workspace
AzureDiagnostics
| where ResourceType == "WORKFLOWS"
| where Resource == "logic-epm-approval"
| order by TimeGenerated desc| Issue | Solution |
|---|---|
| No cards appearing in Teams | Check Teams connection is authorized, verify Team/Channel IDs |
| 401 Unauthorized from Graph API | Ensure Graph API permissions are assigned to Managed Identity |
| Logic App not running | Verify Logic App is enabled, check recurrence trigger |
| Buttons not working | Verify callback URL is accessible, check Logic App run history |
- Managed Identity: Uses Azure Managed Identity for authentication (no secrets)
- Least Privilege: Only requests
DeviceManagementConfiguration.ReadWrite.All - Secure Outputs: Sensitive data is marked with
@secure()decorator - Audit Trail: All approvals/denials are logged in Intune and Logic App run history
- Network Security: Consider using Private Endpoints for Logic Apps in production
| Permission | Type | Reason |
|---|---|---|
DeviceManagementConfiguration.ReadWrite.All |
Application | Read and update EPM elevation requests |
| Resource | Tier | Estimated Cost |
|---|---|---|
| Logic App (Consumption) | Pay-per-execution | ~$0.50/month (5-min intervals) |
| Managed Identity | Free | $0/month |
| Teams API Connection | Free | $0/month |
| Log Analytics (optional) | Pay-per-GB | ~$2-5/month |
Total: ~$2-6/month (varies by usage)
Edit workflow.json to customize the Adaptive Card appearance:
{
"type": "TextBlock",
"text": "Custom Title",
"weight": "Bolder",
"color": "Accent"
}Add more actions to the workflow, such as:
- Send email notifications
- Log to Azure Monitor
- Update a SharePoint list
- Create a ticket in ServiceNow
- Microsoft Graph API - Elevation Requests
- Azure Logic Apps Documentation
- Adaptive Cards Documentation
- Endpoint Privilege Management
For issues or questions:
- Check the Troubleshooting section
- Review Logic App run history in Azure Portal
- Check Intune EPM logs
- Open an issue in this repository
This project is licensed under the MIT License.

