<!-- ref:api-permissions-v1 -->
# API Permissions Guide

This document explains how to configure and manage API permissions for your Microsoft Entra app registration.

## Permission Types

### Delegated Permissions (User Context)

**What:** Application acts on behalf of a signed-in user

**When to use:**
- User is present and can consent
- App needs to access resources as the user
- Interactive authentication flows

**Examples:**
- Read user's email
- Update user's calendar
- Access user's OneDrive files

**Scope format:** User must consent (or admin pre-consents)

### Application Permissions (App Context)

**What:** Application acts with its own identity (no user)

**When to use:**
- Background services, daemons
- Scheduled jobs
- API-to-API calls without user

**Examples:**
- Read all users in organization
- Send mail as any user
- Access all SharePoint sites

**Requirement:** Always requires admin consent

## Permission Scopes

### Understanding Scopes

**Scope:** A string that defines what access is granted

**Format:**
```
{resource}/{permission_name}

Examples:
https://graph.microsoft.com/User.Read
https://graph.microsoft.com/Mail.Send
api://myapi-id/access_as_user
```

### .default Scope

Special scope that includes all configured permissions:

```
https://graph.microsoft.com/.default
api://your-api-id/.default
```

**When to use:**
- Client credentials flow (always)
- Want all pre-configured permissions
- Migrating from v1.0 endpoint

## Microsoft Graph Permissions

### Common Delegated Permissions

| Permission | What it allows | Admin Consent Required |
|------------|---------------|----------------------|
| `User.Read` | Read signed-in user's profile | No |
| `User.ReadWrite` | Read and update user profile | No |
| `User.ReadBasic.All` | Read basic info of all users | No |
| `User.Read.All` | Read all users' full profiles | Yes |
| `Mail.Read` | Read user's mail | No |
| `Mail.ReadWrite` | Read and write user's mail | No |
| `Mail.Send` | Send mail as user | No |
| `Calendars.Read` | Read user's calendars | No |
| `Calendars.ReadWrite` | Read and write calendars | No |
| `Files.Read.All` | Read all files user can access | No |
| `Sites.Read.All` | Read items in all site collections | Yes |
| `Directory.Read.All` | Read directory data | Yes |
| `Directory.ReadWrite.All` | Read and write directory data | Yes |

### Common Application Permissions

| Permission | What it allows | Admin Consent Required |
|------------|---------------|----------------------|
| `User.Read.All` | Read all users' full profiles | Yes (Always) |
| `User.ReadWrite.All` | Read and write all users' profiles | Yes (Always) |
| `Mail.Read` | Read mail in all mailboxes | Yes (Always) |
| `Mail.Send` | Send mail as any user | Yes (Always) |
| `Calendars.Read` | Read calendars in all mailboxes | Yes (Always) |
| `Directory.Read.All` | Read directory data | Yes (Always) |
| `Directory.ReadWrite.All` | Read and write directory data | Yes (Always) |
| `Group.ReadWrite.All` | Read and write all groups | Yes (Always) |

## Adding Permissions

### Azure Portal Method

1. Navigate to your app registration
2. Click **"API permissions"** in left menu
3. Click **"+ Add a permission"**
4. Choose API source:
   - **Microsoft APIs** (Graph, Office 365, etc.)
   - **APIs my organization uses** (custom APIs)
   - **My APIs** (your own APIs)

5. Select permission type:
   - **Delegated permissions** (user context)
   - **Application permissions** (app context)

6. Search and select permissions
7. Click **"Add permissions"**

See [cli-commands.md](cli-commands.md) for az cli commands to add API permissions programmatically.

## Finding Permission IDs

### Method 1: Azure Portal

1. Go to Microsoft Entra ID → Enterprise applications
2. Search for "Microsoft Graph"
3. Click on it → Permissions
4. Browse available permissions and copy IDs

### Method 2: Microsoft Graph Explorer

1. Visit https://developer.microsoft.com/graph/graph-explorer
2. Click "Modify permissions"
3. Browse and view permission details

### Method 3: Microsoft Documentation

Visit: https://learn.microsoft.com/en-us/graph/permissions-reference

### Method 4: Azure CLI Query

```bash
# List all Graph permissions (warning: long output)
az ad sp list --filter "appId eq '00000003-0000-0000-c000-000000000000'" \
  --query "[0].{delegated:oauth2PermissionScopes,application:appRoles}" -o json
```

## Granting Admin Consent

### When Admin Consent is Required

**Always required for:**
- All application permissions
- High-privilege delegated permissions
- When organization disables user consent

**Examples requiring admin consent:**
- `User.Read.All` (read all users)
- `Directory.Read.All` (read directory)
- `Mail.Read` (application permission)
- `Sites.Read.All` (read all SharePoint sites)

### How to Grant Admin Consent

**Portal Method:**
1. Go to API permissions
2. Click **"Grant admin consent for [Your Org]"**
3. Confirm the action
4. Check for green checkmarks next to permissions

**CLI Method:**
```bash
az ad app permission admin-consent --id $APP_ID
```

### Verifying Consent Status

**Portal:** Look for green checkmarks in "Status" column

**CLI:**
```bash
az ad app permission list --id $APP_ID
```

Look for `consentType: "AllPrincipals"` (admin consented)

## Custom API Permissions

### Exposing Your API

If you're building an API that other apps will call:

1. In your API's app registration, go to **"Expose an API"**
2. Set **Application ID URI**: `api://your-api-id`
3. Click **"+ Add a scope"**
4. Configure scope:
   - **Scope name:** `access_as_user`
   - **Who can consent:** Admins and users
   - **Display name:** "Access MyAPI as user"
   - **Description:** Clear description of what this allows
5. Click **"Add scope"**

## Effective Permissions

### User + App Permissions

**Delegated permissions:** Intersection of user's permissions and app's permissions

Example:
- User can: Read all users
- App granted: User.Read.All
- **Effective:** Read all users ✅

- User can: Only read their own profile
- App granted: User.Read.All
- **Effective:** Only read own profile (limited by user's rights)

**Application permissions:** Only app's permissions matter (no user context)

## Troubleshooting Permissions

### "Insufficient privileges" Error

**Causes:**
- Permission not added to app registration
- Admin consent not granted
- User lacks permission in directory
- Accessing resource outside permission scope

**Solutions:**
1. Check API permissions in portal
2. Grant admin consent if needed
3. Verify user has access to resource
4. Use correct permission scope

### "Consent required" Error

**Causes:**
- User hasn't consented to permissions
- Admin consent required but not granted
- Token obtained before permission added

**Solutions:**
1. Request user consent (interactive flow)
2. Admin grants consent (portal or CLI)
3. Acquire new token after adding permissions

### Permission Appears Granted but Doesn't Work

**Possible issues:**
- Using old cached token (get new one)
- Permission is delegated but user lacks rights
- API requires additional configuration
- Permission deprecated (use new one)

**Debug steps:**
1. Decode access token: https://jwt.ms
2. Check `scp` claim (delegated) or `roles` claim (application)
3. Verify permission is present in token
4. Check if permission is correct type (delegated vs application)

## Permission Best Practices

### Development

✅ **Do:**
- Start with minimal permissions
- Add incrementally as features require
- Test with non-admin accounts
- Document why each permission is needed

❌ **Don't:**
- Request all permissions "just in case"
- Use admin account for testing only
- Forget to grant admin consent for app permissions

### Production

✅ **Do:**
- Review permissions quarterly
- Remove unused permissions
- Use least privilege principle
- Monitor permission usage
- Document all permissions in README

❌ **Don't:**
- Grant excessive permissions for convenience
- Use application permissions when delegated would work
- Forget to rotate admin consent approvals

### Security

✅ **Do:**
- Prefer delegated over application permissions
- Implement proper scope validation
- Log permission usage
- Handle consent errors gracefully

❌ **Don't:**
- Hardcode permission scopes in multiple places
- Skip token validation
- Ignore scope mismatches
- Cache permissions indefinitely

## Reference Tables

### Microsoft Graph Permission IDs

**Delegated Permissions:**
```
User.Read                     : e1fe6dd8-ba31-4d61-89e7-88639da4683d
User.ReadWrite                : b4e74841-8e56-480b-be8b-910348b18b4c
User.ReadBasic.All            : b340eb25-3456-403f-be2f-af7a0d370277
Mail.Read                     : 570282fd-fa5c-430d-a7fd-fc8dc98a9dca
Mail.ReadWrite                : 024d486e-b451-40bb-833d-3e66d98c5c73
Mail.Send                     : e383f46e-2787-4529-855e-0e479a3ffac0
Calendars.Read                : 465a38f9-76ea-45b9-9f34-9e8b0d4b0b42
Calendars.ReadWrite           : 1ec239c2-d7c9-4623-a91a-a9775856bb36
Files.Read.All                : df85f4d6-205c-4ac5-a5ea-6bf408dba283
```

**Application Permissions:**
```
User.Read.All                 : df021288-bdef-4463-88db-98f22de89214
User.ReadWrite.All            : 741f803b-c850-494e-b5df-cde7c675a1ca
Mail.Read                     : 810c84a8-4a9e-49e6-bf7d-12d183f40d01
Mail.Send                     : b633e1c5-b582-4048-a93e-9f11b44c7e96
Directory.Read.All            : 7ab1d382-f21e-4acd-a863-ba3e13f7da61
Directory.ReadWrite.All       : 19dbc75e-c2e2-444c-a770-ec69d8559fc7
```

**Note:** Permission IDs may change. Always verify against the official [Microsoft Graph Permissions Reference](https://learn.microsoft.com/en-us/graph/permissions-reference) for the most current values.

## Additional Resources

- [Microsoft Graph Permissions Reference](https://learn.microsoft.com/en-us/graph/permissions-reference)
- [Permission Types](https://learn.microsoft.com/en-us/entra/identity-platform/permissions-consent-overview)
- [Admin Consent Workflow](https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/configure-admin-consent-workflow)
- [Consent Framework](https://learn.microsoft.com/en-us/entra/identity-platform/consent-framework)
