microsoft-graph-apimicrosoft-graph-booking

Why is my Web API with Application Permissions to Bookings.ReadWrite.All unauthorized when querying Graph API Bookings endpoints


We are building an API to get and update Booking Appointments using the Microsoft Graph API and application permissions.

Admin Consent has been granted for Bookings.ReadWrite.All on the app in Azure.

When we query the endpoint with application permissions, we receive an Unauthorized error, but if we query using delegated permissions, it's fine.

var result = await _graphServiceClient
    .Solutions
    .BookingBusinesses[_BookingCalendarId]
    .Appointments[appointmentId]
    .GetAsync();

We have queried Appointments, StaffMembers, and Services, but all return the same result.

We're constructing our Graph Service Client this way:

public AppGraphService(IConfiguration config)
{
    _config = config ?? throw new ArgumentNullException(nameof(config));
    _client = new Lazy<GraphServiceClient>(() =>
    {
        var credential = new ClientSecretCredential(
        config["AzureAd:TenantId"],
        config["AzureAd:ClientId"],
        config["AzureAd:ClientSecret"]);

        return new GraphServiceClient(credential, new[] { "https://graph.microsoft.com/.default" });
    });
}

We inspected the Token for the Graph Client to ensure it had the expected scopes.

... 
  "roles": [
    "Bookings.ReadWrite.All",
    "OnlineMeetings.ReadWrite.All"
  ],
...

We retrieved the request URI and tried it in Graph Explorer, and that worked fine.

var uriinfo = _graphServiceClient
    .Solutions
    .BookingBusinesses[_BookingCalendarId]
    .Appointments[appointmentId]
    .ToGetRequestInformation();

return uriinfo.URI.AbsoluteUri;

Retrieving a token via Thunder Client returns a token with the correct roles, but when we use that token immediately, the request fails with a 500 error.

The same request with a User token is always successful.

// Sample from https://learn.microsoft.com/en-us/graph/auth-v2-service?tabs=http#token-request used to get an App token

POST https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token HTTP/1.1
Host: login.microsoftonline.com
Content-Type: application/x-www-form-urlencoded

client_id=535fb089-9ff3-47b6-9bfb-4f1264799865
&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
&client_secret=qWgdYA....L1qKv5bPX
&grant_type=client_credentials

According to the Devblog post from 2022-06

In this release, we are providing application permissions for a limited set of Bookings APIs. This includes application permissions support for read and write APIs for the ‘bookingCustomer ‘and ‘bookingAppointment’ entities. For other entities, including ‘bookingBusiness’, ‘bookingStaffMember’, ‘bookingCustomQuestion’ and ‘bookingService’, we are supporting the read APIs only. Because these tasks are for Bookings admins, delegated permissions are recommended for these use cases.

We should be able to work with the API using Application Permissions. Yes, it specifies beta and we have used both v1.0 and beta for our queries with the same result.

Why isn't the app able to query the Bookings endpoint at all? What else should we try in order to resolve this? Is there another permission, similar to an Application Access Policy in Exchange?


Solution

  • The issue is with the docs. Bookings.ReadWrite.All is not the correct Application permission, although it is listed as higher privilege.

    To solve this, use BookingsAppointment.ReadWrite.All.