Authorization scopes¶
An app registration in Azure only hands out the data it has permission for, and the connector only asks for the scopes it knows about. The base module and the submodules register the scopes they need themselves. When your own code calls an endpoint that none of them cover, you have to add the scope.
There are two places to do that, and you generally need both.
On the connector¶
For a one-off, type the scope into the Authorization scopes field on the
connector at /admin/config/system/o365/settings/o365-connectors. It is a space
separated list. This is configuration, so it exports with the rest of your config
and travels between environments.
In code¶
For a scope that belongs to a module, so that enabling the module is enough and
nobody has to remember to edit a field, implement hook_o365_auth_scopes():
<?php
use Drupal\o365\O365ConnectorInterface;
/**
* Implements hook_o365_auth_scopes().
*/
function my_module_o365_auth_scopes(array &$scopes, ?O365ConnectorInterface $connector) {
$scopes[] = 'Group.Read.All';
}
The second argument is the connector the scopes are being collected for. Use it when a scope should only be requested for one tenant:
function my_module_o365_auth_scopes(array &$scopes, ?O365ConnectorInterface $connector) {
$scopes[] = 'Group.Read.All';
if ($connector && $connector->id() === 'intranet') {
$scopes[] = 'Sites.Read.All';
}
}
It can be NULL, so check before you call anything on it. And an unsaved
connector has no ID yet, which the $connector && above already covers but the
id() comparison would not.
You do not have to worry about duplicates or about offline_access.
\Drupal\o365\HelperService::getAuthScopes() runs the collected list through
array_unique(), drops empty values, and adds offline_access if it is not
there, because the connector cannot refresh its token without it.
The declaration in o365.api.php is the reference for the signature.
Then grant it in Azure¶
Adding a scope only changes what Drupal asks for. If the app registration does not have the matching delegated Microsoft Graph permission, the authorization request fails or the token comes back without the scope, and the call returns a 403 that does not mention scopes at all.
After adding a scope, open /admin/reports/o365-auth-scopes. That page shows the
full list per connector, which is what you copy into API permissions in Azure.
Some scopes, Group.Read.All and Sites.Read.All among them, need an
administrator to grant consent for the tenant before anyone can use them.
Log out and back in while testing
Users who logged in before you added the scope keep their old token until it is refreshed. If the new scope seems to be ignored, that is usually why.