Skip to main content

Overview

The OAuth2PermissionGrants API provides operations to manage delegated permission grants that authorize client applications to access APIs on behalf of signed-in users. Access through graphClient.Oauth2PermissionGrants.

Request Builder

public Oauth2PermissionGrantsRequestBuilder Oauth2PermissionGrants { get; }
Accessed via: graphClient.Oauth2PermissionGrants

Operations

List OAuth2 Permission Grants

Retrieve all delegated permission grants.
var grants = await graphClient.Oauth2PermissionGrants.GetAsync();

foreach (var grant in grants.Value)
{
    Console.WriteLine($"Client ID: {grant.ClientId}");
    Console.WriteLine($"Resource ID: {grant.ResourceId}");
    Console.WriteLine($"Consent Type: {grant.ConsentType}");
    Console.WriteLine($"Principal ID: {grant.PrincipalId}");
    Console.WriteLine($"Scope: {grant.Scope}");
    Console.WriteLine();
}

// Filter grants
var userGrants = await graphClient.Oauth2PermissionGrants.GetAsync(config =>
{
    config.QueryParameters.Filter = $"principalId eq '{userId}'";
});

var clientGrants = await graphClient.Oauth2PermissionGrants.GetAsync(config =>
{
    config.QueryParameters.Filter = $"clientId eq '{servicePrincipalId}'";
});
Query Parameters:
$filter
string
Filter expression (e.g., "clientId eq 'sp-id'")
$select
string[]
Properties to return
$expand
string[]
Related entities to expand
$top
int
Number of grants to return

Get Permission Grant by ID

var grant = await graphClient.Oauth2PermissionGrants["grant-id"].GetAsync();

Console.WriteLine($"Client: {grant.ClientId}");
Console.WriteLine($"Resource: {grant.ResourceId}");
Console.WriteLine($"Permissions: {grant.Scope}");

Create Permission Grant

Grant delegated permissions to a client application.
// Admin consent (all users)
var adminGrant = new OAuth2PermissionGrant
{
    ClientId = "client-service-principal-id",
    ConsentType = "AllPrincipals", // Admin consent for all users
    ResourceId = "resource-service-principal-id", // Usually Microsoft Graph SP
    Scope = "User.Read Mail.Send Calendars.Read"
};

var grant = await graphClient.Oauth2PermissionGrants.PostAsync(adminGrant);

// User consent (specific user)
var userGrant = new OAuth2PermissionGrant
{
    ClientId = "client-service-principal-id",
    ConsentType = "Principal", // User consent
    PrincipalId = "user-id",
    ResourceId = "resource-service-principal-id",
    Scope = "User.Read openid profile"
};

var grant = await graphClient.Oauth2PermissionGrants.PostAsync(userGrant);
Properties:
ClientId
string
required
Object ID of the service principal (client application) being authorized
Type of consent: AllPrincipals (admin) or Principal (user)
ResourceId
string
required
Object ID of the resource service principal (API)
Scope
string
required
Space-separated list of delegated permissions (e.g., "User.Read Mail.Send")
PrincipalId
string
User object ID (required when ConsentType is Principal)

Update Permission Grant

Modify the scope of an existing grant.
var updateGrant = new OAuth2PermissionGrant
{
    Scope = "User.Read Mail.Read Calendars.Read Files.Read"
};

await graphClient.Oauth2PermissionGrants["grant-id"].PatchAsync(updateGrant);

Delete Permission Grant

Revoke delegated permissions.
await graphClient.Oauth2PermissionGrants["grant-id"].DeleteAsync();
Grants permissions for all users in the organization.
var adminConsent = new OAuth2PermissionGrant
{
    ClientId = "sp-id",
    ConsentType = "AllPrincipals",
    ResourceId = "resource-sp-id",
    Scope = "User.Read.All",
    PrincipalId = null // Not used for admin consent
};
Grants permissions for a specific user.
var userConsent = new OAuth2PermissionGrant
{
    ClientId = "sp-id",
    ConsentType = "Principal",
    ResourceId = "resource-sp-id",
    Scope = "User.Read",
    PrincipalId = "user-id" // Required
};

Common Scenarios

// First, find Microsoft Graph service principal
var graphSps = await graphClient.ServicePrincipals.GetAsync(config =>
{
    config.QueryParameters.Filter = "appId eq '00000003-0000-0000-c000-000000000000'";
});
var graphSpId = graphSps.Value.First().Id;

// Grant admin consent
var grant = new OAuth2PermissionGrant
{
    ClientId = "your-app-service-principal-id",
    ConsentType = "AllPrincipals",
    ResourceId = graphSpId,
    Scope = "User.Read.All Group.Read.All"
};

await graphClient.Oauth2PermissionGrants.PostAsync(grant);

Check User’s Consented Permissions

var userGrants = await graphClient.Oauth2PermissionGrants.GetAsync(config =>
{
    config.QueryParameters.Filter = 
        $"principalId eq '{userId}' and clientId eq '{clientSpId}'";
});

foreach (var grant in userGrants.Value)
{
    Console.WriteLine($"Permissions: {grant.Scope}");
}

Revoke All Permissions for Application

var grants = await graphClient.Oauth2PermissionGrants.GetAsync(config =>
{
    config.QueryParameters.Filter = $"clientId eq '{servicePrincipalId}'";
});

foreach (var grant in grants.Value)
{
    await graphClient.Oauth2PermissionGrants[grant.Id].DeleteAsync();
    Console.WriteLine($"Revoked grant: {grant.Id}");
}

Add Permissions to Existing Grant

// Get existing grant
var grants = await graphClient.Oauth2PermissionGrants.GetAsync(config =>
{
    config.QueryParameters.Filter = 
        $"clientId eq '{clientId}' and resourceId eq '{resourceId}' and consentType eq 'AllPrincipals'";
});

var existingGrant = grants.Value.FirstOrDefault();

if (existingGrant != null)
{
    // Parse existing scopes
    var scopes = existingGrant.Scope.Split(' ').ToList();
    
    // Add new scopes
    var newScopes = new[] { "Mail.Read", "Calendars.Read" };
    scopes.AddRange(newScopes.Where(s => !scopes.Contains(s)));
    
    // Update grant
    var updateGrant = new OAuth2PermissionGrant
    {
        Scope = string.Join(" ", scopes.Distinct())
    };
    
    await graphClient.Oauth2PermissionGrants[existingGrant.Id].PatchAsync(updateGrant);
}

Grant Permissions for Custom API

// Find your API's service principal
var apiSps = await graphClient.ServicePrincipals.GetAsync(config =>
{
    config.QueryParameters.Filter = $"appId eq '{yourApiAppId}'";
});
var apiSpId = apiSps.Value.First().Id;

// Grant permissions
var grant = new OAuth2PermissionGrant
{
    ClientId = "client-sp-id",
    ConsentType = "AllPrincipals",
    ResourceId = apiSpId,
    Scope = "Data.Read Data.Write"
};

await graphClient.Oauth2PermissionGrants.PostAsync(grant);

Delegated vs Application Permissions

OAuth2 Permission Grants are for delegated permissions only (permissions that require a signed-in user).For application permissions (app-only access without a user), use App Role Assignments instead:
await graphClient.ServicePrincipals["sp-id"]
    .AppRoleAssignments
    .PostAsync(new AppRoleAssignment { ... });

Permission Scope Format

The Scope property is a space-separated list of permission values:
Scope = "User.Read Mail.Send Calendars.Read Files.ReadWrite"
Common scopes:
  • User.Read - Read user profile
  • User.ReadWrite.All - Read and write all users
  • Mail.Read - Read user mail
  • Mail.Send - Send mail as user
  • Calendars.Read - Read calendars
  • Files.ReadWrite.All - Read and write all files
  • Group.Read.All - Read all groups

Delta Query

var delta = await graphClient.Oauth2PermissionGrants.Delta.GetAsync();

foreach (var grant in delta.Value)
{
    Console.WriteLine($"Changed grant: {grant.Id}");
}

var deltaLink = delta.OdataDeltaLink;

Error Handling

using Microsoft.Graph.Models.ODataErrors;

try
{
    var grant = await graphClient.Oauth2PermissionGrants.PostAsync(newGrant);
}
catch (ODataError error)
{
    if (error.Error.Code == "Request_BadRequest")
    {
        Console.WriteLine("Invalid grant configuration");
    }
    else if (error.Error.Code == "Authorization_RequestDenied")
    {
        Console.WriteLine("Insufficient privileges to grant consent");
    }
    else
    {
        Console.WriteLine($"Error: {error.Error.Message}");
    }
}

Required Permissions

To manage OAuth2 permission grants, your application needs:
  • DelegatedPermissionGrant.ReadWrite.All - Read and write all delegated permissions
  • Directory.ReadWrite.All - Full directory access

See Also

OAuth2PermissionGrant Model

Permission grant properties

Service Principals

Service principal management

Applications

Application registrations

Permissions Reference

Microsoft Graph permissions

Build docs developers (and LLMs) love