Git Product home page Git Product logo

aad-sso-wordpress's Introduction

Sign Sign-on with Microsoft Entra ID (for WordPress)

A WordPress plugin that allows organizations to use their Microsoft Entra ID (formerly known as Azure Active Directory) user accounts to sign in to WordPress. Organizations with Office 365 already have Microsoft Entra ID (Microsoft Entra ID) and can use this plugin for all of their users.

  • Microsoft Entra ID group membership can be used to determine access and role.
  • New users can be registered on-the-fly based on their Microsoft Entra ID profile.
  • Can always fall back to regular username and password login.

This is a work in progress, please feel free to contact me for help. This plugin is provided as-is, with no guarantees or assurances.

In the typical flow:

  1. User attempts to log in to the blog. At the sign in page, they are given a link to sign in with their Microsoft Entra ID work or school account (e.g. a Microsoft 365 account).
  2. After signing in, the user is redirected back to the blog with an authorization code, which the plugin exchanges for a ID token, containing a minimal set of claims about the signed in user, and an access token, which can be used to query Microsoft Entra ID for additional details about the user.
  3. The plugin uses the claims in the ID token to attempt to find a WordPress user with an email address or login name that matches the Microsoft Entra ID user.
  4. If one is found, the user is authenticated in WordPress as that user account. If one is not found, the WordPress user will (optionally) be auto-provisioned on-the-fly.
  5. (Optional) Membership to certain groups in Microsoft Entra ID can be mapped to roles in WordPress, and group membership can be used to restrict access.

Getting Started

The following instructions will get you started. In this case, we will be configuring the plugin to use the user roles configured in WordPress.

1. Download and activate the plugin

This plugin is not yet registered in the WordPress plugin directory (coming soon!), but you can still install it manually:

  1. Download the plugin using git or with the 'Download ZIP' link on the right.
  2. Place the aad-sso-wordpress folder in your WordPress' plugin folder. Normally, this is <your-blog>/wp-content/plugins.
  3. Activate the plugin in the WordPress admin console, under Plugins > Installed Plugins.

2. Register a Microsoft Entra ID application

With these steps, you will create a Microsoft Entra ID app registration. This will provide your WordPress site with an application identity in your organization's Microsoft Entra ID tenant.

  1. Sign in to the Azure portal, and ensure you are signed in to the directory which has the users you'd like to allow to sign in. (This will typically be your organization's directory.) You can view which directory you're signed in to (and switch directories if needed) by clicking on your username in the upper right-hand corner.

  2. Navigate to the Microsoft Entra ID blade, and enter the App registrations section.

    Clicking Microsoft Entra ID
    Clicking App registrations

  3. Choose New registration.

    Clicking New registration

  4. Fill out the initial form as follows:

    • Name: Enter your site's name. This will be displayed to users at the Microsoft Entra ID sign-in page, in the sign-in logs, in the list of Microsoft Entra apps, and in any consent prompt users may come across.

    • Supported account types: Choose "Accounts in this organizational directory" if you only expect users in your organization (including guest users who have been invited) to sign in to your app. Otherwise, choose "Accounts in any organizational directory" to allow users from any Microsoft Entra ID tenant to sign in.

      Note: This plugin does not yet support the third option, "Accounts in any organizational directory and personal Microsoft accounts".

    • Redirect URI: Leave the redirect URI type set to "Web", and provide a URL matching the format https://<your blog url>/wp-login.php, or whichever page your blog uses to sign in users.

      Note: If you're not sure what to enter here, you can leave it empty for now and come back and update this (under Microsoft Entra ID > App registrations > Authentication) later. The plugin itself will tell you exactly what URL to use.

      Note: The URL you provide must invoke the authenticate action. (By default, this will be wp-login.php.)

  5. After clicking Register, enter the API permissions section.

    API permissions

  6. Verify that the delegated permission User.Read for Microsoft Graph is already be selected. This permission is all you need if you do not require mapping Microsoft Entra ID group membership to WordPress roles.

    User.Read delegated permission for Microsoft Graph

    Note: If you do wish to map Microsoft Entra ID groups to WordPress roles, you must also select the delegated permission Directory.Read.All (click "Add a permission" > Microsoft Graph > Delegated > Directory.Read.All).

    Important: Some permissions require administrator consent before it can be used, and in some organizations, administrator consent is required for any permission. A tenant administrator can use the Grant admin consent option to grant the permissions (i.e. consent) on behalf of all users in the organization.

  7. Under Certificates & secrets, create a new client secret. Provide a description and choose a duration (I recommend no longer than two years). After clicking Add, the secret value will appear. Copy it, as this is the only time it will be available.

    Creating a new secret key

  8. Switch to the Overview section and keep the tab open, as you will need to copy some fields when configuring the plugin.

    App overview page

3. Configure the plugin

Once the plugin is activated in WordPress (step 1), update your settings from the WordPress admin console under Settings > Microsoft Entra ID. Basic settings to include are:

Display name
The display name of the organization, used in the link on the WordPress login page which will start the Microsoft Entra ID sign-in process.
Client ID
The Application ID. (Copy this from the Microsoft Entra ID app registration's **Overview** page.)
Client Secret
The client secret. (You copied this from the Microsoft Entra ID app registration's **Certificates & secrets** page.)
Reply URL
The URL that Microsoft Entra ID will send the user to after authenticating. This is usually the blog's sign-in page, which is the default value. Ensure that the reply URL configured in Microsoft Entra ID matches this value.

4. (Optional) Set WordPress roles based on Microsoft Entra ID group membership

The Single Sign-on with Microsoft Entra ID plugin can be configured to set different WordPress roles based on the user's membership to a set of user-defined groups. This is a great way to control who has access to the site, and under what role.

This is also configured Settings > Microsoft Entra ID (from the WordPress admin console). The following fields should be included:

Enable Microsoft Entra ID group to WordPress role association
Check this to enable Microsoft Entra ID group-based WordPress roles.
Default WordPress role if not in Microsoft Entra ID group
This is the default role that users will be assigned to if matching Microsoft Entra ID group to WordPress roles is enabled. If this is not set, and the user authenticating does not belong to any of the groups defined, they will be denied access.
WordPress role to Microsoft Entra ID group map
For each of the blog's WordPress roles, there is a field for the ObjectId of the Microsoft Entra ID group that will be associated with that role.

Note: For the Microsoft Entra ID group to WordPress role mapping to work, the app in Microsoft Entra ID needs the delegated permission Directory.Read.All for Microsoft Graph. See step 5 of Register a Microsoft Entra ID application, above, for more details.

Example settings

The different fields that can be defined in the settings JSON in Settings > Microsoft Entra ID are documented in Settings.php. The following may give you an idea of the typical scenarios that may be encountered.

Minimal

Users are matched by their email address in WordPress, and whichever role they have in WordPress is maintained.

Setting Example value
Display name Contoso
Client ID 9054eff5-bfef-4cc5-82fd-8c35534e48f9
Client Secret NTY5MmE5Yj...
Reply URL https://www.example.com/blog/wp-login.php
Field to match to UPN Email Address

Match on username alias

Users are matched by their login names in WordPress and the alias portion of their Microsoft Entra ID UserPrincipalName. Whichever role they have in WordPress is maintained.

Setting Example value
Display name Contoso
Client ID 9054eff5-bfef-4cc5-82fd-8c35534e48f9
Client Secret NTY5MmE5Yj...
Reply URL https://www.example.com/blog/wp-login.php
Field to match to UPN Login Name
Match on alias of the UPN Yes

Group membership-based roles, no default role

Users are matched by their login names in WordPress, and WordPress roles are dictated by membership to a given Microsoft Entra ID group. Access is denied if they are not members of any of these groups.

Setting Example value
Display name Contoso
Client ID 9054eff5-bfef-4cc5-82fd-8c35534e48f9
Client Secret NTY5MmE5Yj...
Reply URL https://www.example.com/blog/wp-login.php
Field to match to UPN Login Name
Enable Microsoft Entra ID group to WordPress role association Yes
Default WordPress role if not in Microsoft Entra ID group (None, deny access)
WordPress role to Microsoft Entra ID group map
Administrator5d1915c4-2373-42ba-9796-7c092fa1dfc6
Editor21c0f87b-4b65-48c1-9231-2f9295ef601c
Authorf5784693-11e5-4812-87db-8c6e51a18ffd
Contributor780e055f-7e64-4e34-9ff3-012910b7e5ad
Subscriberf1be9515-0aeb-458a-8c0a-30a03c1afb67

Group membership-based roles with default role

Users are matched by their login names in WordPress, and WordPress roles are dictated by membership to a given Microsoft Entra ID group. If the user is not a part of any of these groups, they are assigned the Author role.

Setting Example value
Display name Contoso
Client ID 9054eff5-bfef-4cc5-82fd-8c35534e48f9
Client Secret NTY5MmE5Yj...
Reply URL https://www.example.com/blog/wp-login.php
Field to match to UPN Login Name
Enable Microsoft Entra ID group to WordPress role association Yes
Default WordPress role if not in Microsoft Entra ID group Author
WordPress role to Microsoft Entra ID group map
Administrator5d1915c4-2373-42ba-9796-7c092fa1dfc6
Editor21c0f87b-4b65-48c1-9231-2f9295ef601c
Authorf5784693-11e5-4812-87db-8c6e51a18ffd
Contributor780e055f-7e64-4e34-9ff3-012910b7e5ad
Subscriberf1be9515-0aeb-458a-8c0a-30a03c1afb67

Group membership-based roles, default role, auto-provision

Users are matched by their email in WordPress, and WordPress roles are dictated by membership to a given Microsoft Entra ID group. If the user doesn't exist in WordPress yet, they will be auto-provisioned. If the user is not a part of any of these groups, they are assigned the Subscriber role.

Setting Example value
Display name Contoso
Client ID 9054eff5-bfef-4cc5-82fd-8c35534e48f9
Client Secret NTY5MmE5Yj...
Reply URL https://www.example.com/blog/wp-login.php
Field to match to UPN Email Address
Enable auto-provisioning Yes
Enable Microsoft Entra ID group to WordPress role association Yes
Default WordPress role if not in Microsoft Entra ID group Subscriber
WordPress role to Microsoft Entra ID group map
Administrator5d1915c4-2373-42ba-9796-7c092fa1dfc6
Editor21c0f87b-4b65-48c1-9231-2f9295ef601c
Authorf5784693-11e5-4812-87db-8c6e51a18ffd
Contributor780e055f-7e64-4e34-9ff3-012910b7e5ad
Subscriberf1be9515-0aeb-458a-8c0a-30a03c1afb67

Groups

As described above, you can map Microsoft Entra ID groups to WordPress roles. Users who are members of the Microsoft Entra ID group will be granted the WordPress role(s) the groups were mapped to.

There are several ways Microsoft Entra ID groups can be created/managed. Some of them require the group owner/creator to be a tenant administrator, others not necessarily (depending on your organization's policy):

  • Azure portal. The Azure portal (https://portal.azure.com), under Microsoft Entra ID > Groups > New group, allows admins and (optionally) users to create and manage groups.
  • Access Panel. The Microsoft Entra ID Access Panel (https://myapps.microsoft.com) provides an interface for users to create and manage groups.
  • Outlook. The Outlook web interface (https://outlook.office.com/) offers users the option to create Office 365 Groups. These groups are stored in Microsoft Entra ID and can be used with this plugin.
  • Microsoft Teams. Creating a team in Microsoft Teams (https://teams.microsoft.com) also results in an Office 365 Group getting created.
  • Microsoft Graph PowerShell. The Microsoft Graph PowerShell module allows admins and (optionally) users to create and manage groups. (e.g. New-MgGroup, and New-MgGroupMember cmdlets.)
  • On-premises. Many large organizations use Microsoft Entra Connect (formerly known as Azure AD Connect) to sync their on-premises AD to Microsoft Entra ID. This usually includes all on-premises AD groups and memberships. Once these groups are synced to Azrue AD, they can be used with this plugin.

Advanced

Refreshing the OpenID Connect configuration cache

Most of the OpenID Connect endpoints and configuration (e.g. signing keys, etc.) are obtained from the OpenID Connect configuration endpoint. These values are cached for one hour, but can always be forced to re-load by adding aadsso_reload_openid_config=1 to the query string in the login page. (This shouldn't really be needed, but it has shown to be useful during development.)

Bypassing automatic redirect to Microsoft Entra ID to prevent lockouts

If you've configured this plugin to automatically redirect to Microsoft Entra ID for sign-in, but something is misconfigured, you may find yourself locked out of your site's admin dashboard.

To log in to your site without automatically redirecting to Microsoft Entra ID (thus giving you an opportunity to enter a regular username and password), you can append ?aadsso_no_redirect=please to the login URL. For example, if your login URL is https://example.com/wp-login.php, navigating to https://example.com/wp-login.php?aadsso_no_redirect=please will prevent any automatic redirects.

aad-sso-wordpress's People

Contributors

blobaugh avatar bradkovach avatar christianhennen avatar dustinrue avatar hajekj avatar hotsaucejake avatar jtsternberg avatar npnigro avatar ntonyho avatar psignoret avatar stephen-kainos avatar waffle-iron avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aad-sso-wordpress's Issues

Where do I find the Azure Group Object ID?

Thank you for a wonderful plugin that has so far worked well for authenticating users without groups. We are trying to connect users to groups but cannot find the Azure Group Object ID for the groups we want to map into WordPress.

Can you direct me as to where I can find these IDs?

Switch user permissions to subscriber when user deleted from AD

Users deleted from an AD group currently potentially still have access to WordPress via the lost password form. This could, for instance, allow an admin who is no longer with an organization to regain admin access to the website.

When user login fails AAD does not report back about the user, only that login has failed, thus there is no easy way to determine the user has been removed.

Here are a few possible options I thought of. Please debate, smack down, heckle, cajole, and add your own.

  • Setup a wp-cron task that will periodically query AAD to ensure users are still valid. This would probably require the plugin to set a marker as to which accounts logged in via AAD initial. Should differentiate between pre-existing users and new users created via AAD. This also means that access to query for users from AAD needs to exist somehow.
  • Add an option to block access to the password reset form. This could be easiest, however it prevents users from resetting their own password if AAD is not the only login method. Thus an option the site admin can set.
  • Add an option to remove the login form entirely when using AAD. Again this method assumes AAD is the only login method. It also means if AAD settings went haywire the regular site admin would not be able to get into the site to fix it without editing code or the db to reenable the default login form.

Another plugin to look at that has attempted to implement similar scenarios is the WordPress.com SSO by Jetpack. For reference https://github.com/Automattic/jetpack/blob/master/modules/sso.php

Did everything

Hello,

I did everything and now when i am at the /wp-admin i try and log in with my active directory login and then it just gives the normal wordpress failed password.

Add checkbox to dis/enable AD group to role mapping in wp-admin

Right now mapping the authenticating user's AD group to a WP role is enabled by default and can only be changed by altering the plugin at runtime. We should add in a checkbox to the settings page in wp-admin to dis/enable mapping easily by the site admin.

ANTIFORGERY_ID mismatch. Expecting

I have setup latest stable wordpress on blank cPanel server and created Azure AD as your instructions.
I have setup successfully about 7 sites, but two of them are not working.
I have tried replacing your wp-plugin, and recreating in Azure AD side, however no success.

The error after login is on wp-login.php form showing error: ANTIFORGERY_ID mismatch. Expecting
without any ID.

What can be the issue ? how can I clean and place again your plugin without any cache, cookies or smth, please give me more to troubleshoot, otherwise its a bug error.

my Settings.json same for all sites (different url and IDs of course):

  {
    "org_display_name": "My company site",

    "client_id":        "66cec22g-ac19-4201-acbd-73e4477f8bc8",
    "client_secret":    "D8Nk3tTiU2cMfiNHh4VwPJ7jfQ49BsCBDc05xaUZ4QM=",

    "field_to_match_to_upn": "email",
    "enable_auto_provisioning": true,

    "enable_aad_group_to_wp_role": true,
    "default_wp_role": null,
    "aad_group_to_wp_role_map": {
            "21e0165b-085e-4z4b-a965-e7bfed9deef0": "administrator"
    }
 }

Settings.json contains Azure AD access tokens/secrets and can be viewed publicly.

It is possible to load and view the Settings.json file by navigating to it with an HTTP request. For the most part, these credentials SHOULD BE read-only, but there is a possibility that these credentials would include the ability to write to AD.

This could be expose a serious attack vector for users that haven't properly configured their Azure AD tokens.

  1. Saving these credentials to a PHP constant in wp-config.php.
  2. Saving these credentials to a PHP environment variable $_ENV['ad_client_token']
  3. Mimic WordPress' behavior where these settings files can be placed one directory above the public html directory
  4. Save these credentials to WordPress DB and allow configuration via WordPress administration.

Matching by email is case sensitive

Hi,

when testing this out, we discovered that some users with existing accounts in WP had lowercase email addresses, but the email address stored in Azure AD was Proper case... and this failed to log users in.

Other than that - awesome plugin - great work!

When matching by email, users can lock themselves out by changing their profile

When matching AAD's UPN to WordPress' email, a users can easily lock themselves out by updating their profile to change their email. Since an average AAD user can't change their own UPN, this would be a bad thing.

(On the next login, the user would not be matched via email, but might not be auto-provisioned because of a conflict with login field (see issue #13)).

Feature request - ability to change redirect_uri via settings

Hi Philippe,

Great plugin, thank you for your efforts.

I ran in to an issue when configuring it on our site, as we have enhanced security using iThemes Security Pro plugin which allows you to hide the typical wordpress login urls /wp-admin/, /wp-login.php, etc and replace them with a custom one such as /secretloginpage/. This means I have to set the reply url in my azure ad application to /secretloginpage/ instead of /wp-login.php. However this creates an issue because the redirect_uri parameter in the login link query string is harded coded on line 49 of aad-sso-wordpress.php to wp_login_url() which produces a url ending in /wp-config.php. This causes an error in Azure AD - Error: AADSTS50011: The reply address ‘https://someurlhere’ does not match the reply addresses configured for the application: xxxxxxxx.

It would be very handy if redirect_uri variable could be overridden on the settings page instead of resorting to modifying the plugin code which I've done as a temporary work around.

Many thanks

Use OpenID Connect

We might want to consider using OpenID Connect.

(There are some arguments not to do so, but creating this as a tracking item just in case.)

Localize.

Make sure all strings are localized properly.

Please add steps for granting Azure permissions on behalf of users

When every user first logs into the Wordpress site via SSO, Azure requests permissions for the app:
"[App Name] needs permission to:
Sign you in and read your profile
You're signed in as: [User Name]"
It's not clear how to grant permission on behalf of our organization's users. If you have worked through this already, it would be an excellent addition to your setup instructions. After granting permission individually, SSO works great!

Autoprovision fails when matching by login because email can be taken

We can't create a user in WordPress if the email address is taken. If we are matching by email (field_to_match_to_upn = 'email'), then the auto-provisioning code is never invoked. However, if we are matching by login (field_to_match_to_upn = 'login'), then it is possible that there exists a user with the same email, but with a different login.

E.g.
field_to_match_to_upn: login
User in WP: (login: admin, email: [email protected])
User signing in: (UPN: [email protected])
Will attempt to auto-provision because no users were found where login == '[email protected]', but auto-provision will fail because there already exists a user where email == '[email protected]'.

Proposal: Better error message, and (optionally) fall back to alternate matching method if preferred one fails.

ANTIFORGERY_ID debacle

I feel like I have all the settings set properly. Two nearly identical instances: one works fine, the other is having issues. The two Azure applications are set-up identically. I am very open to ideas and suggestions.

Consistently getting:
ANTIFORGERY_ID mismatch. Expecting {5001CD3E-DD9E-7999-EECA-14B6A9F6606D}

Refresh readme

The entire process for setting up the plugin has changed and the readme file should be updated to reflect these changes

ERROR: Invalid id_token

I have the plugin installed on my site for more than 6 months, this week we started to receive the following error when trying to login
ERROR: Invalid id_token. Cannot handle token prior to 2015-12-01T10:39:32+0000
(the time stamp is when you tried to login)

I haven't made any changes to the server or the application in Azure.

Why is this happening but more important how do i fix this ???

Thanks
Josef

Validate token

Should validate the access to token (otherwise, open to MITM).

Prep for WordPress plugin directory

I have found the following helpful resources for prepping a plugin for the plugin directory

Todo...

  • Create README.txt
  • Logo?
  • GitHub <-> WordPress SVN sync mechanism

The current version of the plugin in the WP plugin directory is from a Subversion repository (assigned by wordpress.org), so an automated way to push commits from GitHub to Subversion would be nice. This service seems to handle the process nicely: http://ship.getherbert.com/ If we don't want a third party service, building our own Git<->SVN plugin sync shouldn't be too hard. GitHub Webhooks would make this totally automatic.

Flip AAD groups to WP roles map in settings

Current implementation has the group ObjectId as key, and WP role as value. WP roles are the ones that are unique, and thus should be the keys. This would avoid awkward flipping and non-deterministic behavior.

Unable to login locally once SSO created account

When a new user authenticates via SSO (office 365) the plugin creates the users account in wordpress and authenticates them for access. If the user logs out of office 365 and attempts to login, this time using the wordpress login form and enters their office 365 email/password they are not authenticated to the wordpress site.

This came about when trying to setup a blogging software (MS Word and LIve Writer) to authenticate to the blog.

Bad resource requests in login page can cause state value to reset

Need to explore a mechanism to generate state values only when generating the sign-in link, not necessarily on every request to wp-login.php.

As a case study: The MAYO - Login Screen plugin allows the user to set a background image for the login page. In doing so, it adds this style:

.login { /* ... */ background-image: url('http://url/to/background/image.png'); /* ... */ }

However, if the user does not set a background image, this will result in the following CSS:

.login { /* ... */ background-image: url(''); /* ... */ }

The issue is introduced by url(''). When the browser tries to load the image at '', it makes a request to the current page (typically .../wp-login.php). This loads and invokes all plugins (including the AADSSO plugin) a second time, which will re-generate the ANTIFORGERY_ID value in the session.

But since the value in the sign-in link was generated before all this happened, the Authorization Request goes ahead using the original value of the ANTIFORGERY_ID, which results in the mismatch and error message: "ANTIFORGERY_ID mismatch".

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.