Knowledge base WordPress plugins Authentication and access
Connecting the Office 365 plugin to an Azure app registration
The four fields on the Office 365 base plugin's General tab, what the Save button actually does with them, and why an unverified connection silently deactivates every add-on.
Published 12 August 2026
The Office 365 base plugin is the piece that holds your Azure credentials. Every add-on in the line — SharePoint Display, OneDrive Display, Outlook Display, Microsoft Booking, CRM Display, User Auth and the rest — reads its client ID, secret and tenant from the base plugin’s settings rather than carrying its own. Configure this once and the add-ons inherit it.
This page covers the app-level connection the base plugin makes on its own. Signing WordPress users in with Microsoft accounts is a separate add-on with its own tab, and is not what the fields below do.
Before you start
The plugin header declares Requires at least: 5.0, tested up to 6.9.1. The plugin’s own Server Info tab (same settings screen) checks five things and prints what it found next to what it wants:
| Check | Wanted |
|---|---|
| Curl | ON |
| PHP | 7+ |
| Server execution time | Minimum 1500 |
| MySql | MySql or MySqli |
HTTP_AUTHORIZATION | Enable |
You also need an app registration in the Azure portal with a client secret, because step 2 asks for both halves of it.
Where the settings live
Activating the base plugin adds a top-level admin menu called Microsoft 365, whose
first item is Settings — wp-admin/admin.php?page=o365_settings. The menu is
registered for the administrator role. Until a client ID and secret are both saved,
every admin screen shows a yellow notice: “The plugin Office 365 currently needs to be
configured.”
Step 1 — fill in the General tab
Five fields on the General tab are the connection. The labels below are the ones
printed on the screen; the names in backticks are the keys they are stored under inside
the single o365_settings option.
- Application (client) ID —
client_id. From the app registration. - Application Key —
client_secret. Rendered as a password field with a show/hide toggle. - Tenant Name —
tenant_name. The prefix only. The hint under the field is explicit:[dwsnow].onmicrosoft.comshould be entered asdwsnow. The plugin builds<tenant_name>.onmicrosoft.comand<tenant_name>.sharepoint.comfrom it and stores both asapplication_tenant_domain_nameandsharePoint_tenant_domain_name. - Authorization Endpoint —
o365_national_endpoints, defaulting tohttps://login.microsoftonline.com. - Graph Endpoint —
o365_graph_endpoints, defaulting tohttps://graph.microsoft.com.
Three more fields are on the same table but only appear when the add-on that needs them
is active: Application Object ID (client_object, User Auth), M365 User ID
(o365_display_user_id, OneDrive or Outlook Display) and M365 Dynamic CRM
(o365_dynamic_crm_url, CRM Display).
Directory (tenant) ID is not an input, despite looking like one. The save routine
never reads that box. When the tenant name you submit differs from the stored one, the
plugin looks the tenant ID up itself by fetching
https://login.windows.net/<tenant_name>.onmicrosoft.com/.well-known/openid-configuration
and taking the GUID out of the returned authorization_endpoint. Typing a tenant ID in
by hand will be overwritten; correcting the Tenant Name is what changes it.
Step 2 — press “Save settings & Get Authentication”
That button is not a form submit. It is a jQuery handler that checks three values in the browser before sending anything, and stops with an alert if any are blank:
Plesae input the Application ID.Plesae input the Application Key.Plesae input the tenant name.
(The typo is in the shipped string; it is a validation message, not a failure of the connection.)
If all three are present it posts the settings over AJAX, and the server then does two things in order: saves them, and immediately tries a client-credentials token request to prove they work —
POST https://login.windows.net/<tenant_name>.onmicrosoft.com/oauth2/token?api-version=1.0
grant_type=client_credentials
resource=https://graph.windows.net
client_id / client_secret
An access_token in the reply sets o365_base_plugin_is_verify to 1; anything else
sets it to 0. Either way the page reloads back to the settings screen, so the result
is only visible as the Verification Status row:
- ✅ This plugin has been verified
- ⚠ This plugin is not verified
Note what that check does not use: the Authorization Endpoint field. The
verification request is hard-coded to login.windows.net and the
https://graph.windows.net resource, so pointing the endpoint field at a national cloud
does not move this call.
Step 3 — consent, so the add-ons can get tokens
The base plugin’s own verification only proves the credentials exist. Each add-on that calls Microsoft on your behalf builds its own admin-consent link when it has no stored token yet:
https://login.microsoftonline.com/<tenant id>/adminconsent
?client_id=<client_id>&state=<plugin state>&redirect_uri=<your wp-admin URL>
The redirect target is your WordPress admin URL, so the app registration has to list it
as a redirect URI or Microsoft will reject the consent round-trip. The settings save
also records redirect_uri as …/wp-admin/admin.php?page=o365_settings.
The plugin does not request named Graph permissions anywhere in its code — it asks for consent to whatever API permissions are already configured on the app registration. Set those on the Azure side, per the data each add-on needs to read.
Troubleshooting
All of my add-on plugins deactivated themselves. This is the single loudest
consequence of a failed connection, and it does not announce itself. On every init,
the base plugin reads o365_base_plugin_is_verify, and if it is 0 it calls
deactivate_plugins() on the whole add-on list. Activation also seeds that flag to 0,
so a freshly installed stack behaves this way until the first successful save. Fix the
credentials, get a verified status, then re-activate the add-ons.
Status stays “not verified” with credentials you know are right. The token call is
made against <tenant_name>.onmicrosoft.com. If the tenant name was entered as a full
domain instead of the prefix, both that call and the tenant-ID lookup are pointed at a
hostname that does not exist. Network failures are swallowed silently — there is no
error text, only the unverified badge.
You changed the app registration and things stopped working. The settings screen
says it outright: “If you changed the Application ID, Application Key or Tenant Name,
please create and configure a new app registration in your azure portal.” With User
Auth active it adds that its settings must be re-configured too, and saving fires
delete_access_token_on_base_setting_changed.
Stale or wrong-scoped tokens. When an active add-on uses access tokens, a Token
Manager tab appears on the settings screen with a Revoke Tokens list. Deleting one
clears that add-on’s stored token, refresh token and expiry, and answers “An access
token has been deleted. Please reload the page for a new token.” The keys it is allowed
to clear are fixed: sp_calendar_access_token, sp_video_access_token,
crm_view_access_token, onedrive_search_access_token, outlook_search_access_token,
ms_booking_access_token, o365_wp_sp_access_token, o365_embed_access_token,
o365_user_auth_access_token, search_access_token.
“Security check failed.” or “Permission denied.” Both are 403s from the save and
token-delete handlers. The first means the o365_settings_save nonce was missing or
expired — reload the settings page. The second means the logged-in user lacks
manage_options.
Multisite
On a network install the settings screen gains a Multisite Shared Settings checkbox
(shared_settings) in network admin, plus a separate User Auth Multisite Shared
Settings (b2b_shared_settings) when User Auth is active. With sharing on, settings
and tokens are read from and written to the network options; with it off, each sub-site
configures its own.
Toggling that checkbox is destructive on purpose: the save routine resets
o365_base_plugin_is_verify to 0 for every blog and deletes all ten stored access
tokens across all of them, so every add-on re-consents against the newly authoritative
settings. On a sub-site while sharing is on, the Save button is rendered disabled.
One more switch worth knowing
Delete Settings on Deactivation (delete_settings) is off by default. Turned on,
deactivating the base plugin deletes the o365_settings option outright — every field
on this page, including the client ID and secret. Leave it off unless you are
deliberately tearing the install down.
Read next
-
WordPress plugins · Getting started
Setting up the Office 365 Microsoft Booking plugin
Base plugin, Azure token, licence, then a shortcode — the order the plugin actually enforces, with every [msb_booking] attribute and its default.
-
WordPress plugins · Getting started
SharePoint Calendar Display: setup, shortcodes and room booking
Installing Office 365 SharePoint Calendar Display, the order the plugin requires, every attribute of [o365_sp_events] and [o365_sp_booking], and what each failure message means.
-
WordPress plugins · Embedding
Embedding Power BI Reports in WordPress
The [o365_powerbi] shortcode: the attributes it reads, the token it needs before it renders anything, and the error strings it prints when one of those is missing.