littlewonders / wordpress-oauth
Dead simple OAuth login for Wordpress
Requires
- composer/installers: ^2.2
README
A bare-minimum Wordpress plugin to allow single-sign-on via OAuth. Tested with Amazon Cognito but should work with any OAuth compliant server.
Originally forked from the wordpress plugin (oauth-client-for-user-authentication)[https://wordpress.org/plugins/oauth-client-for-user-authentication/], as when testing that plugin I found many security vulnerabilities so I decided to use it as a base and strip it back as much as possible to make the code easy to audit and understand.
The plugin scope is designed to be deliberately very simple. It supports:
- Adding a button to the login form to begin SSO
- Authenticating with a single Identity Provider
- Automatically redirecting /wp-login.php to begin the OAuth process with the IDP
- Finding a user by any attribute returned by your IDP, against any wordpress_users column
- Redirecting a user to your IDP's logout endpoint after logging out of Wordpress
It does not, and will not, support:
- Editing plugin settings from the wp-admin interface
- Registering/making new users for IDP users
- Syncing from / authenticating to LDAP
- Multiple Identity Providers
- OpenID Connect
It does not currently support, but support is planned in future for:
- Correctly redirecting the user to the page they were trying to access after completing authentication
- Fully disabling the user login page, so logging in with username&password is impossible
Configuration
All configuration is defined statically in your wp-config.php
. You will need to add a section as follows:
define('OAUTHCLIENT_CONFIG', [
// OAuth identity provider URLs
"client_authorization" => "https://youridp.com/oauth2/authorize",
"client_token_endpoint" => "https://youridp.com/oauth2/token",
"client_logout_endpoint" => "https://youridp.com/logout",
"client_userinfo_endpoint" => "https://youridp.com/oauth2/userInfo",
// Whether to include the client_id and client_secret in the request body of the /token call
"client_request_in_body" => true,
// Client ID & Client Secret
"client_id" => "example",
"client_secret" => "exampleexample",
// Which scope to include in the call to /authorize. Should normally be openid
"scope" => "openid",
// See "Modes" section
"scope" => "id_token",
// See "User Lookup" section
"user_lookup_column" => "user_login",
"user_lookup_attribute" => "custom:wordpress-username",
// Whether to allow sign-in via normal Wordpress form
//
// Note that this only redirects the user to SSO automatically, it doesn't disable
// the normal sign-in mechanisms so a malicious user could still perform a
// username/password signin
"force_sso" => true
]);
Modes
The plugin supports two different authentication methods/modes.
id_token will expect an id_token parameter to be returned after calling the client_token_endpoint
. It expects a JSONWebToken.
Note that this mode does NOT verify the validity or expiry of the JSONWebToken however since the token is obtained in a HTTPS call from Wordpress directly to the OpenID server, there is not a chance for the user to modify it.
access_token mode will expect an access_token to be returned after calling the client_token_endpoint
. It will then use this access token as a Bearer token to call the client_userinfo_endpoint
and will use the response data from this endpoint to match the user.
User Lookup
The "User Lookup" options allow you to compare any Identity Provider attribute against any column in the wp_users table to find a matching user.
Common values for user_lookup_column
are:
Value | Description |
---|---|
ID | The wordpress user ID |
user_login | The wordpress username |
user_email | The wordpress user's email |
For the user_lookup_attribute
option, this will depend on the structure of your Identity Provider's data. Nested attributes will be flattened into underscore-separated array keys. For example if the userInfo request returns:
{
"sub": "248289761001",
"name": "Jane Doe",
"given_name": "Jane",
"family_name": "Doe",
"preferred_username": "j.doe",
"email": "janedoe@example.com",
"someAttributes": {
"wordpressUsername": "jane.d"
}
}
Then you could set the following configuration values to allow users to authenticate:
Key | Value |
---|---|
user_lookup_column | user_login |
user_lookup_attribute | someAttributes_wordpressUsername |