# 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)
