# Microsoft Graph API Permissions This document lists all required Microsoft Graph API permissions for TenantPilot to function correctly. ## Required Permissions The Azure AD / Entra ID **App Registration** used by TenantPilot requires the following **Application Permissions** (not Delegated): ### Core Policy Management (Required) - `DeviceManagementConfiguration.Read.All` - Read Intune device configuration policies - `DeviceManagementConfiguration.ReadWrite.All` - Write/restore Intune policies - `DeviceManagementApps.Read.All` - Read app configuration policies - `DeviceManagementApps.ReadWrite.All` - Write app policies ### Scope Tags (Feature 004 - Required for Phase 3) - **`DeviceManagementRBAC.Read.All`** - Read scope tags and RBAC settings - **Purpose**: Resolve scope tag IDs to display names (e.g., "0" → "Default") - **Missing**: Backup items will show "Unknown (ID: 0)" instead of scope tag names - **Impact**: Metadata display only - backups still work without this permission ### Group Resolution (Feature 004 - Required for Phase 2) - `Group.Read.All` - Resolve group IDs to names for assignments - `Directory.Read.All` - Batch resolve directory objects (groups, users, devices) ## How to Add Permissions ### Azure Portal (Entra ID) 1. Go to **Azure Portal** → **Entra ID** (Azure Active Directory) 2. Navigate to **App registrations** → Select your TenantPilot app 3. Click **API permissions** in the left menu 4. Click **+ Add a permission** 5. Select **Microsoft Graph** → **Application permissions** 6. Search for and select the required permissions: - `DeviceManagementRBAC.Read.All` - (Add others as needed) 7. Click **Add permissions** 8. **IMPORTANT**: Click **Grant admin consent for [Your Organization]** - ⚠️ Without admin consent, the permissions won't be active! ### PowerShell (Alternative) ```powershell # Connect to Microsoft Graph Connect-MgGraph -Scopes "Application.ReadWrite.All" # Get your app registration $appId = "YOUR-APP-CLIENT-ID" $app = Get-MgApplication -Filter "appId eq '$appId'" # Add DeviceManagementRBAC.Read.All permission $graphServicePrincipal = Get-MgServicePrincipal -Filter "appId eq '00000003-0000-0000-c000-000000000000'" $rbacPermission = $graphServicePrincipal.AppRoles | Where-Object {$_.Value -eq "DeviceManagementRBAC.Read.All"} $requiredResourceAccess = @{ ResourceAppId = "00000003-0000-0000-c000-000000000000" ResourceAccess = @( @{ Id = $rbacPermission.Id Type = "Role" } ) } Update-MgApplication -ApplicationId $app.Id -RequiredResourceAccess $requiredResourceAccess # Grant admin consent # (Must be done manually or via Graph API with RoleManagement.ReadWrite.Directory scope) ``` ## Verification After adding permissions and granting admin consent: 1. Go to **App registrations** → Your app → **API permissions** 2. Verify status shows **Granted for [Your Organization]** with a green checkmark ✅ 3. Clear cache in TenantPilot: ```bash php artisan cache:clear ``` 4. Test scope tag resolution: ```bash php artisan tinker >>> use App\Services\Graph\ScopeTagResolver; >>> use App\Models\Tenant; >>> $tenant = Tenant::first(); >>> $resolver = app(ScopeTagResolver::class); >>> $tags = $resolver->resolve(['0'], $tenant); >>> dd($tags); ``` Expected output: ```php [ [ "id" => "0", "displayName" => "Default" ] ] ``` ## Troubleshooting ### Error: "Application is not authorized to perform this operation" **Symptoms:** - Backup items show "Unknown (ID: 0)" for scope tags - Logs contain: `Application must have one of the following scopes: DeviceManagementRBAC.Read.All` **Solution:** 1. Add `DeviceManagementRBAC.Read.All` permission (see above) 2. **Grant admin consent** (critical step!) 3. Wait 5-10 minutes for Azure to propagate permissions 4. Clear cache: `php artisan cache:clear` 5. Test again ### Error: "Insufficient privileges to complete the operation" **Cause:** The user account used to grant admin consent doesn't have sufficient permissions. **Solution:** - Use an account with **Global Administrator** or **Privileged Role Administrator** role - Or have the IT admin grant consent for the organization ### Permissions showing but still getting 403 **Possible causes:** 1. Admin consent not granted (click the button!) 2. Permissions not yet propagated (wait 5-10 minutes) 3. Wrong tenant (check tenant ID in app config) 4. Cached token needs refresh (clear cache + restart) ## Feature Impact Matrix | Feature | Required Permissions | Without Permission | Impact Level | |---------|---------------------|-------------------|--------------| | Basic Policy Backup | `DeviceManagementConfiguration.Read.All` | Cannot backup | 🔴 Critical | | Policy Restore | `DeviceManagementConfiguration.ReadWrite.All` | Cannot restore | 🔴 Critical | | Scope Tag Names (004) | `DeviceManagementRBAC.Read.All` | Shows "Unknown (ID: X)" | 🟡 Medium | | Assignment Names (004) | `Group.Read.All` + `Directory.Read.All` | Shows group IDs only | 🟡 Medium | | Group Mapping (004) | `Group.Read.All` | Manual ID mapping required | 🟡 Medium | ## Security Notes - All permissions are **Application Permissions** (app-level, not user-level) - Requires **admin consent** from Global Administrator - Use **least privilege principle**: Only add permissions for features you use - Consider creating separate app registrations for different environments (dev/staging/prod) - Rotate client secrets regularly (recommended: every 6 months) ## References - [Microsoft Graph API Permissions](https://learn.microsoft.com/en-us/graph/permissions-reference) - [Intune Graph API Overview](https://learn.microsoft.com/en-us/graph/api/resources/intune-graph-overview) - [App Registration Best Practices](https://learn.microsoft.com/en-us/azure/active-directory/develop/security-best-practices-for-app-registration)