From eec106b50e85a742a14a0456044470a3cd0a60de Mon Sep 17 00:00:00 2001 From: Jonathan Daggerhart Date: Sun, 4 Nov 2018 09:51:29 -0500 Subject: [PATCH] Documenting hooks and other internals for contributors --- openid-connect-generic.php | 2 +- readme.md | 305 ++++++++++++++++++++++++++++++++++++- readme.txt | 11 ++ 3 files changed, 316 insertions(+), 2 deletions(-) diff --git a/openid-connect-generic.php b/openid-connect-generic.php index 6dcff74..83403e9 100644 --- a/openid-connect-generic.php +++ b/openid-connect-generic.php @@ -14,7 +14,7 @@ Notes Spec Doc - http://openid.net/specs/openid-connect-basic-1_0-32.html Filters - - openid-connect-generic-alter-request - 3 args: request array, plugin settings, specific request op + - openid-connect-generic-alter-request - 2 args: request array, specific request op - openid-connect-generic-settings-fields - modify the fields provided on the settings page - openid-connect-generic-login-button-text - modify the login button text - openid-connect-generic-user-login-test - (bool) should the user be logged in based on their claim diff --git a/readme.md b/readme.md index 42cc942..1420ef4 100644 --- a/readme.md +++ b/readme.md @@ -31,9 +31,312 @@ Installation: ### Frequently Asked Questions -**What is the client's Redirect URI?** +#### What is the client's Redirect URI? Most OAuth2 servers should require a whitelist of redirect URIs for security purposes. The Redirect URI provided by this client is like so: `https://example.com/wp-admin/admin-ajax.php?action=openid-connect-authorize` Replace `example.com` with your domain name and path to WordPress. + +#### Can I change the client's Redirect URI? + +Some OAuth2 servers do not allow for a client redirect URI to contain a query string. The default URI provided by +this module leverages WordPress's `admin-ajax.php` endpoint as an easy way to provide a route that does not include +HTML, but this will naturally involve a query string. Fortunately, this plugin provides a setting that will make use of +an alternate redirect URI that does not include a query string. + +On the settings page for this plugin (Dashboard > Settings > OpenID Connect Generic) there is a checkbox for +**Alternate Redirect URI**. When checked, the plugin will use the Redirect URI +`https://example.com/openid-connect-authorize`. + +### Hooks + +This plugin provides a number of hooks to allow for a significant amount of customization of the plugin operations from +elsewhere in the WordPress system. + +#### Filters + +Filters are WordPress hooks that are used to modify data. The first argument in a filter hook is always expected to be +returned at the end of the hook. + +WordPress filters API - [`add_filter()`](https://developer.wordpress.org/reference/functions/add_filter/) and +[`apply_filters()`](https://developer.wordpress.org/reference/functions/apply_filters/). + +Most often you'll only need to use `add_filter()` to hook into this plugin's code. + +##### `openid-connect-generic-alter-request` + +Hooks directly into client before requests are sent to the OpenID Server. + +Provides 2 arguments: the request array being sent to the server, and the operation currently being executed by this +plugin. + +Possible operations: + +- get-authentication-token +- refresh-token +- get-userinfo + +``` +add_filter('openid-connect-generic-alter-request', function( $request, $operation ) { + if ( $operation == 'get-authentication-token' ) { + $request['some_key'] = 'modified value'; + } + + return $request; +}, 10, 2); +``` + +##### `openid-connect-generic-login-button-text` + +Modify the login button text. Default value is `__( 'Login with OpenID Connect' )`. + +Provides 1 argument: the current login button text. + +``` +add_filter('openid-connect-generic-login-button-text, function( $text ) { + $text = __('Login to my super cool IDP server'); + + return $text; +}); +``` + +##### `openid-connect-generic-auth-url` + +Modify the authentication URL before presented to the user. This is the URL that will send the user to the IDP server +for login. + +Provides 1 argument: the plugin generated URL. + +``` +add_filter('openid-connect-generic-auth-url', function( $url ) { + // Add some custom data to the url. + $url.= '&my_custom_data=123abc'; + return $url; +}); +``` + +##### `openid-connect-generic-user-login-test` + +Determine whether or not the user should be logged into WordPress. + +Provides 2 arguments: the boolean result of the test (default `TRUE`), and the `$user_claim` array from the server. + +``` +add_filter('openid-connect-generic-user-login-test', function( $result, $user_claim ) { + // Don't let Terry login. + if ( $user_claim['email'] == 'terry@example.com' ) { + $result = FALSE; + } + + return $result; +}, 10, 2); +``` + +##### `openid-connect-generic-user-creation-test` + +Determine whether or not the user should be created. This filter is called when a new user is trying to login and they +do not currently exist within WordPress. + +Provides 2 arguments: the boolean result of the test (default `TRUE`), and the `$user_claim` array from the server. + +``` +add_filter('', function( $result, $user_claim ) { + // Don't let anyone from example.com create an account. + $email_array = explode( '@', $user_claim['email'] ); + if ( $email_array[1] == 'example.com' ) { + $result = FALSE; + } + + return $result; +}, 10, 2) +``` + +##### `openid-connect-generic-alter-user-claim` + +Modify the `$user_claim` before the plugin builds the `$user_data` array for new user created. + +**Deprecated** - This filter is not very useful due to some changes that were added later. Recommend not using this +filter, and using the `openid-connect-generic-alter-user-data` filter instead. Practically, you can only change the +user's `first_name` and `last_name` values with this filter, but you could easily do that in +`openid-connect-generic-alter-user-data` as well. + +Provides 1 argument: the `$user_claim` from the server. + +``` +// Not a great example because the hook isn't very useful. +add_filter('openid-connect-generic-alter-user-claim', function( $user_claim ) { + // Use the beginning of the user's email address as the user's first name. + if ( empty( $user_claim['given_name'] ) ) { + $email_array = explode( '@', $user_claim['email'] ); + $user_claim['given_name'] = $email_array[0]; + } + + return $user_claim; +}); +``` + +##### `openid-connect-generic-alter-user-data` + +Modify a new user's data immediately before the user is created. + +Provides 2 arguments: the `$user_data` array that will be sent to `wp_insert_user()`, and the `$user_claim` from the +server. + +``` +add_filter('openid-connect-generic-alter-user-claim', function( $user_data, $user_claim ) { + // Don't register any user with their real email address. Create a fake internal address. + if ( !empty( $user_data['user_email'] ) ) { + $email_array = explode( '@', $user_data['user_email'] ); + $email_array[1] = 'my-fake-domain.co'; + $user_data['user_email'] = implode( '@', $email_array ); + } + + return $user_data; +}, 10, 2); +``` + +##### `openid-connect-generic-settings-fields` + +For extending the plugin with a new setting field (found on Dashboard > Settings > OpenID Connect Generic) that the site +administrator can modify. Also useful to alter the existing settings fields. + +See `/includes/openid-connect-generic-settings-page.php` for how fields are constructed. + +New settings fields will be automatically saved into the wp_option for this plugin's settings, and will be available in +the `\OpenID_Connect_Generic_Option_Settings` object this plugin uses. + +**Note:** It can be difficult to get a copy of the settings from within other hooks. The easiest way to make use of +settings in your custom hooks is to call +`$settings = get_option('openid_connect_generic_settings', array());`. + +Provides 1 argument: the existing fields array. + +``` +add_filter('openid-connect-generic-settings-fields', function( $fields ) { + + // Modify an existing field's title. + $fields['']['title'] = __(''); + + // Add a new field that is a simple checkbox. + $fields['block_terry'] = array( + 'title' => __('Block Terry'), + 'description' => __('Prevent Terry from logging in'), + 'type' => 'checkbox', + 'section' => 'authorization_settings', + ); + + // A select field that provides options. + + $fields['deal_with_terry'] = array( + 'title' => __('Manage Terry'), + 'description' => __('How to deal with Terry when he tries to log in.'), + 'type' => 'select', + 'options' => array( + 'allow' => __('Allow login'), + 'block' => __('Block'), + 'redirect' => __('Redirect'), + ), + 'section' => 'authorization_settings', + ); + + return $fields; +}); +``` +"Sections" are where your setting appears on the admin settings page. Keys for settings sections: + +- client_settings +- user_settings +- authorization_settings +- log_settings + +Field types: + +- text +- checkbox +- select (requires an array of "options") + +#### Actions + +WordPress actions are generic events that other plugins can react to. + +Actions API: [`add_action`](https://developer.wordpress.org/reference/functions/add_action/) and [`do_actions`](https://developer.wordpress.org/reference/functions/do_action/) + +You'll probably only ever want to use `add_action` when hooking into this plugin. + +##### `openid-connect-generic-user-create` + +React to a new user being created by this plugin. + +Provides 2 arguments: the `\WP_User` object that was created, and the `$user_claim` from the IDP server. + +``` +add_action('openid-connect-generic-user-create', function( $user, $user_claim ) { + // Send the user an email when their account is first created. + wp_mail( + $user->user_email, + __('Welcome to my web zone'), + "Hi {$user->first_name},\n\nYour account has been created at my cool website.\n\n Enjoy!" + ); +}, 10, 2); +``` + +##### `openid-connect-generic-user-update` + +React to the user being updated after login. This is the event that happens when a user logins and they already exist as +a user in WordPress, as opposed to a new WordPress user being created. + +Provides 1 argument: the user's WordPress user ID. + +``` +add_action('openid-connect-generic-user-update', function( $uid ) { + // Keep track of the number of times the user has logged into the site. + $login_count = get_user_meta( $uid, 'my-user-login-count', TRUE); + $login_count += 1; + add_user_meta( $uid, 'my-user-login-count', $login_count, TRUE); +}); +``` + +##### `openid-connect-generic-update-user-using-current-claim` + +React to an existing user logging in (after authentication and authorization). + +Provides 2 arguments: the `WP_User` object, and the `$user_claim` provided by the IDP server. + +``` +add_action('openid-connect-generic-update-user-using-current-claim', function( $user, $user_claim) { + // Based on some data in the user_claim, modify the user. + if ( !empty( $user_claim['wp_user_role'] ) ) { + if ( $user_claim['wp_user_role'] == 'should-be-editor' ) { + $user->set_role( 'editor' ); + } + } +}, 10, 2); +``` + +##### `openid-connect-generic-redirect-user-back` + +React to a user being redirected after a successful login. This hook is the last hook that will fire when a user logs +in. It will only fire if the plugin setting "Redirect Back to Origin Page" is enabled at Dashboard > Settings > +OpenID Connect Generic. It will fire for both new and existing users. + +Provides 2 arguments: the url where the user will be redirected, and the `WP_User` object. + +``` +add_action('openid-connect-generic-redirect-user-back', function( $redirect_url, $user ) { + // Take over the redirection complete. Send users somewhere special based on their capabilities. + if ( $user->has_cap( 'edit_users' ) ) { + wp_redirect( admin_url( 'users.php' ) ); + exit(); + } +}, 10, 2); +``` + +#### User Meta Data + +This plugin stores meta data about the user for both practical and debugging purposes. + +* `openid-connect-generic-subject-identity` - The identity of the user provided by the IDP server. +* `openid-connect-generic-last-id-token-claim` - The user's most recent `id_token` claim, decoded and stored as an array. +* `openid-connect-generic-last-user-claim` - The user's most recent `user_claim`, stored as an array. +* `openid-connect-generic-last-token-response` - The user's most recent `token_response`, stored as an array. diff --git a/readme.txt b/readme.txt index 951b30c..7d91924 100644 --- a/readme.txt +++ b/readme.txt @@ -36,6 +36,17 @@ by this client is like so: https://example.com/wp-admin/admin-ajax.php?action=o Replace `example.com` with your domain name and path to WordPress. += Can I change the client's Redirect URI? = + +Some OAuth2 servers do not allow for a client redirect URI to contain a query string. The default URI provided by +this module leverages WordPress's `admin-ajax.php` endpoint as an easy way to provide a route that does not include +HTML, but this will naturally involve a query string. Fortunately, this plugin provides a setting that will make use of +an alternate redirect URI that does not include a query string. + +On the settings page for this plugin (Dashboard > Settings > OpenID Connect Generic) there is a checkbox for +**Alternate Redirect URI**. When checked, the plugin will use the Redirect URI +`https://example.com/openid-connect-authorize`. + == Changelog ==