Grant API permissions in Office 365 without SharePoint Framework packages

Using SharePoint Framework packages, you can request access to APIs secured with Azure AD. But there is also another way to configure these additional permissions.

Building rich solutions on Office 365 just got easier

In a recent release of the SharePoint Framework, Microsoft added a new capability that allows you to more easily communicate with the Microsoft Graph and other APIs secured with Azure AD. Using the SharePoint Framework, you can easily obtain an access token to the specified API, and if you need additional permissions, you can request them too.

Requesting additional permissions to Azure AD-secured resources

By default, Office 365 doesn't allow access to the Microsoft Graph or other enterprise APIs secured with Azure AD. In order to access them, tenant administrators have to grant the access to the specific resources first. But they cannot just select which resources should be exposed to scripts. Instead, they can grant permissions only by approving permission requests. And the only way to issue a permission request at the moment, is through a SharePoint Framework solution package. So to grant access to the Microsoft Graph for example, a developer has to build a SharePoint Framework solution with the correct permission request. App catalog admin needs then to deploy this solution to the app catalog. This provisions the permission request, which can then be approved by the tenant administrator.

While defining permissions as a part of the solution package has its benefits, it is also inconvenient and here is why.

Incovenient testing SharePoint Framework solutions

Imagine, that you are a developer and want to test your solution using the Microsoft Graph in your developer tenant. Previously, you could build your solution, start the local web server calling gulp serve --nobrowser, open the hosted SharePoint Workbench and test your solution.

Following this new approach, you have to start with including permission requests for the Microsoft Graph and the necessary permissions in your solution. Next, you have to build and package your solution. Once that's done, you have to deploy it in your app catalog to issue the permission requests for the APIs and operations required by your solution. Finally, you have to approve these permission requests, which will then allow you to start the local web server and test your web part using the hosted SharePoint Workbench.

Inconvenient governance of API permissions

Another example. Imagine, that you are tenant administrator managing an Office 365 tenant. When new SharePoint Framework solutions are deployed to the app catalog, you see new permission requests appear in the API management list for you to either approve or reject. These permissions appear in the list no matter if the particular permission has already been granted or not. Also, once the permission has been granted, there is no way for you to tell which solutions issued the original request or which solutions require it.

So you end up managing ad-hoc permission requests that randomly pop-up in your tenant. But ideally, you would decide upfront which APIs and operations are available to be used by scripts in your tenant, grant them, and disregard any new permission requests coming from solutions. And while you could do this by creating a SharePoint Framework with the necessary permissions yourself, there is another way to achieve the same result.

Grant API permissions using the Office 365 CLI

Using the Office 365 CLI you can conveniently grant API permissions to scripts in your Office 365 tenant. All granted permissions are stored in Azure AD and using the Office 365 CLI you can easily manage them without having to use SharePoint Framework packages.

Connect to Azure AD

Start, by connecting to the Azure AD using the o365 aad connect command. You can verify that you're connected to Azure AD, using the o365 aad status command.

Get the service principal ID

All granted permissions are linked to a service principal named SharePoint Online Client Extensibility. To proceed, you have to know its objectId, which you can retrieve by executing the aad sp get command:

o365 aad sp get --displayName 'SharePoint Online Client Extensibility'

From the command output, note the value of the objectId property.

Scenario 1. Add permissions to Microsoft Graph

Let's assume you started working on a new tenant with no API permissions granted yet, and you want to allow access to people's calendars using the Microsoft Graph.

Step 1.1. Get Microsoft Graph ID

To grant permissions to the Microsoft Graph, you have to first get the ID of the service principal that represents it in your tenant. To do this, execute in the command prompt:

o365 aad sp get --displayName 'Microsoft Graph'

From the command output, note the value of the objectId property.

Step 1.2. Grant permissions to access calendars using the Microsoft Graph

With all information in place, to add permissions to the Microsoft Graph, execute the aad oauth2grant add command:

o365 aad oauth2grant add --clientId 0bc67b69-e63a-41cc-848c-9c386a8da5f7 --resourceId c2af2474-2c95-423a-b0e5-e4895f22f9e9 --scope Calendars.Read

The clientId option contains the value of the objectId property of the SharePoint Online Client Extensibility service principal. The resourceId option contains the value of the objectId property of the Microsoft Graph service principal. Finally, the scope option is a space-separated list of permissions you want to grant. In the above example you're granting access only to calendars, but if you wanted to include permissions to e-mail too, you would pass 'Calendars.Read Mails.Read' instead.

Scenario 2. Add more permissions to Microsoft Graph

While some permissions have already been granted to the Microsoft Graph, the solution you're building requires some other permissions. For this, you have to extend the list of currently granted permissions with the ones required by your solution.

Step 2.1. Get current Microsoft Graph permissions

Start, by checking which permissions to the Microsoft Graph have already been granted. For this, execute in the command prompt the aad oauth2grant list command:

o365 aad oauth2grant list --clientId 0bc67b69-e63a-41cc-848c-9c386a8da5f7

The clientId option contains the value of the objectId property of the SharePoint Online Client Extensibility service principal.

For each granted permissions, you will see the objectId, resourceId and scope. You have to know the value of the objectId if you want to modify or remove existing permissions. The resourceId is the objectId of the service principal for which the permissions are granted. Finally, the scope option lists the permissions that have been granted.

From the command output, note the value of the objectId property for the grant you want to update.

Step 2.2. Add more permissions to Microsoft Graph

Assuming, that previously you set the Calendars.Read permissions to the Microsoft Graph, and wanted to add the Mails.Read permission, execute the aad oauth2grant set command:

o365 aad oauth2grant set --grantId aXvGCzrmzEGEjJw4ao2l93Qkr8KVLDpCsOXkiV8i-ek --scope 'Calendars.Read Mails.Read'

The grantId option contains the value of the objectId of the permission grant for the Microsoft Graph. The scope option contains the permissions that you want to grant.

Automating granting API permissions using the Office 365 CLI

You've just seen how you can easily grant API permissions using the Office 365 CLI without having to build and deploy SharePoint Framework packages. Alternatively, rather than issuing the different commands manually, you could run a script that automatically executes the necessary commands for you.

Here is a simple script you could use in Bash:

#!/usr/bin/env bash

# resource to which you want to grant permissions
resource='Microsoft Graph'
# permissions you want to grant
new_scopes='Mails.Read'

echo "Retrieving SharePoint Online Client Extensibility service principal..."
spid=$(o365 aad sp get -n 'SharePoint Online Client Extensibility' -o json | jq -r '.objectId')
echo "  $spid"

echo "Retrieving $resource service principal..."
resourceid=$(o365 aad sp get -n "$resource" -o json | jq -r '.objectId')
if [ -z "$resourceid" ]; then
    echo "Service principal $resource not found"
    exit 1
else
    echo "  $resourceid"
fi

echo "Checking if permissions for $resource are already granted..."
grants_raw=$(o365 aad oauth2grant list -i $spid -o json)
scopes=$(echo $grants_raw | jq --arg resourceid $resourceid -r '.[] | select(.resourceId == $resourceid) | {scope} | .[]')

if [ -z "$scopes" ]; then
    echo "No existing permissions found. Setting new permissions..."
    o365 aad oauth2grant add -i $spid -r $resourceid -s "$new_scopes"
    echo "  DONE"
else
    echo "Found permissions: $scopes"
    if [[ "$scopes" = *"$new_scopes"* ]]; then
        echo "Permissions $new_scopes already set"
    else
        grantid=$(echo $grants_raw | jq --arg resourceid $resourceid -r '.[] | select(.resourceId == $resourceid) | {objectId} | .[]')
        echo "Setting new permissions '$scopes $new_scopes'..."
        o365 aad oauth2grant set -i $grantid -s "$scopes $new_scopes"
        echo "  DONE"
    fi
fi

In lines 4 and 6 you specify respectively the API and the permissions you want to allow the scripts in your tenant to use. Next, the script will retrieve the SharePoint service principal, check if the particular permission is granted and grant it if it's not. Because Bash doesn't have a native support for processing JSON strings, the script uses jq.

If you prefer to use PowerShell, the same script would look as follows:

# resource to which you want to grant permissions
$resource = 'Microsoft Graph'
# permissions you want to grant
$new_scopes = 'Calendars.Read'

Write-Host "Retrieving SharePoint Online Client Extensibility service principal..."
$spid = $(o365 aad sp get -n 'SharePoint Online Client Extensibility' -o json | ConvertFrom-Json).objectId
Write-Host "  $($spid)"

Write-Host "Retrieving $($resource) service principal..."
$resourceid = $(o365 aad sp get -n "$resource" -o json | ConvertFrom-Json).objectId
If ($resource -eq $null) {
    Write-Host "Service principal $($resource) not found"
    exit
}
Else {
    Write-Host "  $($resourceid)"
}

Write-Host "Checking if permissions for $($resource) are already granted..."
$grant = $(o365 aad oauth2grant list -i $spid -o json | ConvertFrom-Json | ? { $_.resourceId -eq $resourceid } | Select -First 1)

If (-not $grant) {
    Write-Host "No existing permissions found. Setting new permissions..."
    o365 aad oauth2grant add -i $spid -r $resourceid -s "$($new_scopes)"
    Write-Host "  DONE"
}
Else {
    $scopes = $grant.scope
    Write-Host "Found permissions: $($scopes)"
    If ($scopes -like "*$($new_scopes)*") {
        Write-Host "Permissions $new_scopes already set"
    }
    Else {
        $grantid = $grant.objectId
        Write-Host "Setting new permissions '$($scopes) $($new_scopes)'..."
        o365 aad oauth2grant set -i $grantid -s "$scopes $new_scopes"
        Write-Host "  DONE"
    }
}

Using the Office 365 CLI you can not only grant and update permissions. It also allows you to remove previously granted permissions as well as manage SharePoint API permission requests. For more information check the Office 365 CLI documentation at https://aka.ms/o365cli.

Photo by James Sutton on Unsplash

Comments

comments powered by Disqus