Azure AD based protection for the WordPress REST API
Introduction
Use this guide if you want to protect your WordPress REST API endpoints with oauth access tokens for delegated or application access generated by Entra ID (Azure AD, AAD). If you enable WPO365's Entra ID endpoint protection for the WordPress REST API then applications requesting data from any of the protected endpoints will either receive a 401 (unauthorized) or 403 (forbidden) error, unless they present a valid oauth access token that:
- Has been signed by Entra ID.
- Was created for the right Audience, identified by the Entra ID Application ID (URI).
- Has been authorized to use permissions specified by the custom scope (delegated permissions) or custom App Role (application permissions), used to further restrict access to the API's data and functionality.
Supported scenarios
WPO365 supports the following two scenarios:
- Delegated permissions A user requesting data from the WordPress REST API using an access token obtained through methods such as the hybrid flow or authorization code flow; WPO365 will impersonate the user while processing the request.
- Application permissions An application requesting data from the WordPress REST API using an access token obtained through methods such as the client-credentials flow.
Before you start
- You are a Global Administrator for your company’s Microsoft Entra ID tenant, or have at least the ability to create or make changes to the App registration (= the Application Principal that represents the WordPress application in Entra ID).
- You are an Administrator for your WordPress website.
- You have installed one of the following extensions / bundles: ESSENTIALS, PROFESSIONAL, INTEGRATE (LOGIN+, SYNC, INTRANET). Check the website for further details and pricing.
Please note In the scenarios that follow below, two different App Registrations can be used:
Also note that it is possible to use the very same App Registration to represent both the API and the client-application. As a matter of fact: This guide will also be using the same App Registration to represent both the API and client-application. |
Scenario #1 | Application Permissions
Perform the following steps to secure your WordPress REST API using Entra ID and restrict access to authorized applications only.
Define a custom App Role for the API
- Navigate to Entra Portal, and continue to Identity > Applications > App Registrations and select the API App Registration from the All Applications list. If you have not yet created an App Registration, then please refer to this tutorial step.
- Open the App roles page and click + Create app role - for example - using the following parameters:
- Display name WP API Reader
- Allowed member types Applications
- Value Wp.Api.Reader
- Description Readers may read from the WordPress API.
- Do you want to enable this app role? Yes
- Click Apply to add the new App role.
- Find the Application ID URI input field at the top of the page and click the Set button. To ensure that the Application ID URI is globally unique you should use one of the custom domains that have registered with Entra ID and the App registration's own application client ID. As a prefix you should use api://. In the example below, the registered custom domain name is wpo365.site and the application's client ID 6f365615-b660-4499-8bdb-faf5657ab76e and thus the Application ID URI becomes api://wpo365.site/6f365615-b660-4499-8bdb-faf5657ab76e.
- Now the new App Role will be visible for other applications in Entra ID as api://wpo365.site/6f365615-b660-4499-8bdb-faf5657ab76e/Wp.Api.Reader.
Grant application permissions to consume the API
- Still in Entra Portal, continue to Identity > Applications > App Registrations and select the Consumer App Registration from the All Applications list.
- Open the API Permissions page, click + Add a permission and find the API Application Registration on the tab APIs my organization uses and select it. Verify that the Application ID URI that is displayed on the page just below the App Registration's display name is correct.
- Click Application permissions and select - for example - the Wp.Api.Reader permission (or any other permission matching your requirement and custom configuration).
- Click Add permissions to save the changes.
- Finally, click Grant admin consent ... to grant consent - as an administrator - to the App Registration in question, for this specific application permission.
With this configuration in place, half of the work is done. Please continue to the paragraph Enable Azure AD based WordPress REST API endpoint protection below.
Scenario #2 | Delegated permissions
Perform the following steps to secure your WordPress REST API using Entra ID and restrict access to authorized users only.
- Assuming that you have already created an App Registration in Entra ID to enable Microsoft based single sign-on (see the getting-started guide for OpenID Connect based SSO), you should be able to navigate to Entra Portal, and continue to Identity > Applications > App Registrations and select the API App Registration from the All Applications list. If you have not yet created an App Registration, then please refer to this tutorial step.
- Continue to the App registration's Expose an API page.
- Find the Application ID URI input field at the top of the page and click the Set button. To ensure that the Application ID URI is globally unique you should use one of the custom domains that have registered with Entra ID and the App registration's own application client ID. As a prefix you should use api://. In the example below, the registered custom domain name is wpo365.site and the application's client ID 6f365615-b660-4499-8bdb-faf5657ab76e and thus the Application ID URI becomes api://wpo365.site/6f365615-b660-4499-8bdb-faf5657ab76e.
- Scroll down to Scopes defined by this API and click + Add a scope.
- Fill out the form, for example with the following values.
- Scope name access_as_user
- Who can consent? Admins only
- Admin consent display name Apps can access the user’s profile.
- Admin consent description Apps can call the app’s web APIs as the current user.
- User consent display name Apps can access your profile and make requests on your behalf.
- User consent description Apps can call this app’s APIs with the same rights as you have.
- State Enabled
- Click Add scope to save and enable the new scope. This will create a new scope that is now referred to as api://wpo365.site/6f365615-b660-4499-8bdb-faf5657ab76e/access_as_user. Note the similarity to standard Microsoft scopes e.g. https://graph.microsoft.com/User.Read.
Please note In the example above, the App Registration's own ID has been added as an Authorized client application. This means that users that authenticate / sign in using this application, will also be able to authorize to be able to retrieve data from the (WordPress REST) API that is protected by WPO365's solution. If you are planning to use a different App Registration for users to use to sign in - for example into a mobile application - then you must add that App Registration's ID instead. Adding the ID will prevent Microsoft from requesting each and every user to consent to using this specific permission and API (which may not be possible if the request is made in an asynchronous way). |
Enable Entra ID based WordPress REST API endpoint protection
At this point you should have implemented measures in Entra ID that will help either applications or users to authorize successfully, so that they can retrieve data from the WordPress REST API.
Perform the following steps to enable Entra ID based authorization for the WordPress REST API.
- Open a new browser tab (leave the tab with your App registration open so you can easily copy some of the values) and go to WP Admin > WPO365 > Integration.
- Scroll down to Azure AD based protection for the WordPress REST API.
- Click to Enable Azure AD based WordPress REST API protection.
- Select the App registration's Application client ID that represents the (WordPress REST) API.
Please note This can either be the App Registration that you configured on the plugin's Single Sign-on configuration page, in case you opted for scenario #2 (delegated permissions). Alternatively (e.g. when you're did not enable SSO), you can select the App Registration that you configured on the plugin's Integration configuration page, in the section Application Access. Please note that you may need to check the option to Use app-only token to view or update this specific configuration section. |
- Copy and paste the Application ID URI from the App Registration's Expose an API page.
- If you configured for application permissions (see scenario #1 above) then you must check the option to Use App Roles.
- Protect an endpoint by entering the following details:
- The endpoint's path e.g. /wp-json/wp/v2/users/posts. If you enter an incomplete path e.g. /wp-json/wp/v2 then be aware that all requests to all endpoints starting with /wp-json/wp/v2 will be subject to the protection defined by this configuration. So if you want - for example - for all requests to the standard WordPress built-in WP REST API to be authorized, you should use a path with value /wp-json/wp/v2/.
- The HTTP methods for which the protection should be activated as a comma separated string e.g. post or get, post.
- The custom app role or delegated scope that is required to access this endpoint. This must be one of the custom scopes or App Roles that you defined in the previous step. In our example that would either be (for delegated permissions as a user) api://wpo365.site/6f365615-b660-4499-8bdb-faf5657ab76e/access_as_user or otherwise (for application permissions) api://wpo365.site/6f365615-b660-4499-8bdb-faf5657ab76e/Wp.Api.Reader.
- If you want to Block all other WordPress REST endpoints you can check the corresponding option.
- Click Save configuration.
If you selected the Intranet Authentication scenario (on the plugin's Single Sign-on configuration page) then the plugin will - by default - block access to all your WordPress REST API endpoints. To work-around this, you must add the path of each endpoint that you wish to protect to the list of Pages freed from authentication (also on the plugin's Single Sign-on configuration page). |
Test accessing a protected endpoint
Once the configuration of the registered application in Entra ID has been updated an WP REST API endpoint protection has been enabled, you are ready to test it - for example - using the following cURL request from a terminal on your local computer.
curl https://wpo365.site/wp-json/wp/v2 --header "Authorization: bearer eyJ0eXAiOi.[...]"
Please note that the access token can be copied from the Plugin self-test result page, when you click the View link for the test case Configuration of Azure AD based protection of the WordPress REST API appears valid, as shown below.
Please note that the Plugin self-test simply takes the first endpoint configuration item from the list.
You can of course also use a tool that allows you to compose requests manually - for example Fiddler - for this.
Troubleshooting
Authorization header not found
Some Apache servers and PHP modules such as mod_security may block / remove incoming Authorization headers. If you configured Azure AD based protection for WordPress API endpoints and the plugin cannot find the Authorization header it will generate an error which is visible when you navigate to WP Admin > WPO365.