Using WordPress? Every integration here is also available as a plugin. Browse the plugin store →

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

  • azure-ad
  • office 365 plugin
  • app registration
  • tenant
  • setup

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:

CheckWanted
CurlON
PHP7+
Server execution timeMinimum 1500
MySqlMySql or MySqli
HTTP_AUTHORIZATIONEnable

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 Settingswp-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) IDclient_id. From the app registration.
  • Application Keyclient_secret. Rendered as a password field with a show/hide toggle.
  • Tenant Nametenant_name. The prefix only. The hint under the field is explicit: [dwsnow].onmicrosoft.com should be entered as dwsnow. The plugin builds <tenant_name>.onmicrosoft.com and <tenant_name>.sharepoint.com from it and stores both as application_tenant_domain_name and sharePoint_tenant_domain_name.
  • Authorization Endpointo365_national_endpoints, defaulting to https://login.microsoftonline.com.
  • Graph Endpointo365_graph_endpoints, defaulting to https://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.

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

Back to the knowledge base