Skip to content

Installing and configuring the module

This page assumes you already have an app registration and its credentials. If not, start at Setting up an Azure app.

Installing

composer require drupal/o365

The module needs OAuth2 Client and External Authentication, plus the Microsoft Graph SDK and Mimey on the PHP side. Composer pulls all of that in.

Enable o365 and the submodules you need. On its own o365 only registers the connector service and the admin pages, so a site with just the base module enabled looks like nothing happened. For login, enable o365_sso as well. The Submodules page lists what the rest do.

One submodule has an extra dependency: o365_groups needs the Group module, which is not installed by default.

Configuring

There are two halves to the configuration and they have to line up. The credentials sit in settings.php. Everything else sits on a connector entity, which is normal configuration and moves between environments with a config export.

1. Credentials in settings.php

If you followed the Azure page you already have this:

$settings['o365'] = [
  'default' => [
    'client_id' => '<client id>',
    'client_secret' => '<client secret>',
    'tenant_id' => '<tenant id>',
  ],
];

2. Create a connector

Go to Configuration › System › Microsoft 365 Settings › Microsoft 365 connectors, or straight to /admin/config/system/o365/settings/o365-connectors, and add one.

The machine name has to match

The machine name of the connector has to be identical to the key you used in settings.php. This is the single most common mistake: the connector exists, the credentials exist, but the names differ by a character and nothing works. The status report tells you when a connector has no matching credentials, so check /admin/reports/status if you are unsure.

Two fields on the form matter:

Authorization scopes
A space separated list of extra Microsoft Graph scopes. The scopes the enabled submodules add through hook_o365_auth_scopes() are listed under the field and do not have to be repeated here. offline_access is always added, with or without you.
Redirect after login URL
The absolute URL a user lands on after logging in, for example https://www.example.com/intranet. A redirect_login key in settings.php overrides this.

You can create as many connectors as you have tenants. Each one needs its own key in settings.php and its own redirect URI in Azure.

3. Permissions

Go to People › Permissions. The base module ships these:

Permission Gives access to
Access Microsoft 365 Connector settings page The settings page, the role settings and the authorization scopes report
Access Microsoft 365 Connector debugger page The Graph debugger
Access Microsoft 365 connectors The connector overview
Create / Edit / Delete Microsoft 365 connector Managing connectors
Administer Microsoft 365 connectors Everything above, marked as restricted

Submodules add their own, such as Access Microsoft 365 SSO settings page. Give these to an administrator role, not to authenticated users.

4. Check the scopes

Open /admin/reports/o365-auth-scopes. It shows, per connector, the complete list of scopes the site will request. Make sure the app registration in Azure has all of them as delegated Microsoft Graph permissions. Go back here whenever you enable another submodule, because most of them add scopes.

Where the settings live

Page Path
Microsoft 365 settings /admin/config/system/o365/settings
Microsoft 365 connectors /admin/config/system/o365/settings/o365-connectors
SSO settings /admin/config/system/o365/settings/sso
User sync settings /admin/config/system/o365/settings/sso_user
Application links /admin/config/system/o365/settings/o365-links
Calendar settings /admin/config/system/o365/settings/outlook-calendar
Teams links /admin/config/system/o365/settings/teams-links
Role settings /admin/config/system/o365/role-settings
Debugger /admin/config/system/o365/debugger
Authorization scopes report /admin/reports/o365-auth-scopes

The submodule pages only exist once that submodule is enabled.

When something does not work

Turn on verbose logging at /admin/config/system/o365/settings. Every Graph request and every step of the login is then written to the o365 channel, which you read at /admin/reports/dblog. Turn it off again on production once you are done; it is chatty.

The debugger at /admin/config/system/o365/debugger fires a Graph request as the current user and shows you the raw response. It is the quickest way to tell a permission problem from a code problem.

A few failures and what they usually mean:

The status report says no API settings are provided
$settings['o365'] is missing, or none of its keys match a connector machine name.
Login ends on a Microsoft error page about the reply URL
The redirect URI in Azure does not match the callback route. Remember that any connector other than default has its machine name in the URI.
Login works, but a block stays empty
Almost always a missing scope. Compare the scopes report with the API permissions in Azure, and check whether one of them needs admin consent.
Everything broke at once, months after it was working
Check the expiry date of the client secret.