Giter VIP home page Giter VIP logo

openid-connect-generic's People

Contributors

bookchiq avatar chris-schreyer avatar daggerhart avatar dependabot[bot] avatar drzraf avatar flat235 avatar gassan avatar glowsome avatar jkouris avatar ksimunovic avatar maybejustjames avatar menno-ll avatar moriyoshi avatar mullikine avatar mvarblow avatar pjeby avatar rkcreation avatar robertstaddon avatar robjs avatar rwasef1830 avatar schanzen avatar skidos avatar slykar avatar snyk-bot avatar svenvanhal avatar szepeviktor avatar thijskh avatar timnolte avatar wgengarelly avatar xdavidwu 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

openid-connect-generic's Issues

Google provider: "Missing required parameter: token" on disconnect

error: "invalid_request"
error_description: "Missing required parameter: token"

This is the json (instead of a HTTP redirect) that I got at:
https://accounts.google.com/o/oauth2/revoke?id_token_hint=XXXXXX&post_logout_redirect_uri=http%3A%2F%2Fmy-domain%2Fwp-login.php%3Floggedout%3Dtrue
after I clicked the disconnect link.
(But I observe that I've been actually disconnected when I get back on the website)

Settings

$ wp option get openid_connect_generic_settings
array (
  'login_type' => 'button',
  'client_id' => 'XXX.apps.googleusercontent.com',
  'client_secret' => '',
  'scope' => 'email profile openid',
  'endpoint_login' => 'https://accounts.google.com/o/oauth2/v2/auth',
  'endpoint_userinfo' => 'https://www.googleapis.com/oauth2/v3/userinfo',
  'endpoint_token' => 'https://www.googleapis.com/oauth2/v4/token',
  'endpoint_end_session' => 'https://accounts.google.com/o/oauth2/revoke',
  'identity_key' => 'preferred_username',
  'no_sslverify' => '0',
  'http_request_timeout' => '5',
  'enforce_privacy' => '0',
  'alternate_redirect_uri' => '0',
  'nickname_key' => 'preferred_username',
  'email_format' => '{email}',
  'displayname_format' => '',
  'identify_with_username' => '0',
  'link_existing_users' => 1,
  'redirect_user_back' => '0',
  'redirect_on_logout' => '1',
  'enable_logging' => '1',
  'log_limit' => '150',
)

last token response (keys)

$ wp user meta get 1 openid-connect-generic-last-token-response --format=json | jq '. | 1keys'
[
  "access_token",
  "expires_in",
  "id_token",
  "token_type"
]

last id token claim (keys)

$ wp user meta get 1 openid-connect-generic-last-id-token-claim --format=json|jq '.|keys'
[
  "at_hash",
  "aud",
  "azp",
  "email",
  "email_verified",
  "exp",
  "family_name",
  "given_name",
  "hd",
  "iat",
  "iss",
  "locale",
  "name",
  "picture",
  "sub"
]

Some provider does not implement the partial logout spec. They expect the initial token as a "token" parameter to the /revoke endpoint. Google is one of them (Facebook/Twitter may be too)

See:

WordPress Plugin Directory?

This is more a question than an "issue," though it's an issue for me. I'm wondering whether we can get this plugin added to the WordPress Plugin Directory (https://wordpress.org/plugins/developers/). This would allow novice WordPress users to use this plugin without going to GitHub, cloning the repo, and uploading to their server.

The reason this is an issue for me is that I want to recommend this plugin to the before-mentioned novices, and believe it or not, not being in the directory is an issue. Without being in the directory, it's too difficult for some to install, and others give it side-eye, wondering why it's not in the directory. The combination of non-standard installation and perceived sketchiness means that I can't currently recommend it broadly to my (potential) users.

Why do I want to recommend this plugin? Actually, what I want to recommend is for certain people to use this plugin to configure their WP sites to use my OIDC service, Globus. Globus (www.globus.org) is a non-profit research data management SaaS/PaaS system for the academic and scientific research community, and part of our service is an OIDC/OAuth-based authentication service. We currently have 50,000+ researchers at 200+ institutions using Globus to login and manage data for their work. Globus allows researchers to use their campus login services (think: Berkeley, Harvard, University of Maryland--almost all of which are SAML-based--see https://www.incommon.org/federation/basics.html) to login, and it provides an OIDC/OAuth authentication service based on that. And, because academics often have accounts at more than one institution, Globus allows them to link their OIDC/OAuth identities so they can use them interchangeably and in combination.

I want to show these researchers how to use Globus to allow their colleagues to log in to their WordPress blogs and websites using their local campus logins, and that means they need a solid, generic OIDC plugin. I've got the instructions written and I've trained early adopters to do it using this plugin already. It works great! My personal blog (https://home.leeandkristin.net/rll/) is configured this way. The sticking point is that it's not in the "official" WordPress Plugin Directory, which means something to some people.

I'd be happy to help make this happen if it would be helpful. On the other hand, I can imagine many reasons why you might prefer to not take that step. So...my question: Is this something you want done or are you intentionally avoiding it or just not ready yet for other reasons?

link_existing_users flag causes orphans sessions if a concurrent session logs out

Currently, the openid-connect-generic-user meta flag is set to false when a user logs out (if link_existing_users is set), but this doesn't work correctly if a user has more than one login session, because then the other sessions will stop refreshing tokens and act like ordinary Wordpress sessions. (And thus will remain live with current permissions even if those permissions have been revoked at the IdP.)

Steps to reproduce:

  1. Set up a site with Auto-SSO login mode and "link existing users"
  2. Log into the site from two different browsers using OIDC, then explicitly log out of one.
  3. Wait for the refresh token to expire, then access the site in the second browser. You should get a refresh error, but instead you get a plain WP session unconnected to OIDC.

The problem is that a user meta flag is global to the user, but what is really needed is to know whether the session is linked to an OIDC session, not the user as a whole.

For my own purposes, I'm working around this with a get_user_meta hook which checks that the session is actually OIDC-linked; it does this by adding data to the WP session token in the database (via the attach_session_information hook). This then results in the OIDC plugin seeing a fake openid-connect-generic-user value that reflects whether the session was started with OIDC, instead of a global flag whose value might be corrupt.

This workaround could be avoided, though, by having ensure_tokens_still_fresh() check for a flag in WP_Session_Tokens::get_instance($user_id)->get(wp_get_session_token()). The flag would be set by login_user(), either via an attach_session_information hook, or by directly creating the session token and passing it through to wp_set_auth_cookie().

wp_logout before wp_loaded causes problems w/other plugins (e.g. woocommerce)

Currently, the plugin can fire a wp_logout() before all plugins have fully loaded. This can create problems when there are logout hooks which make use of plugins that are not yet loaded; for example, the Woocommerce Follow-Up Emails plugin tries to access the Woocommerce cart on logout, but the main plugin complains that the cart can't be accessed yet.

Changing the direct call of ensure_tokens_still_fresh() to an add_action('wp_loaded', ...) instead, resolves the problem by ensuring that all WP plugins are fully loaded before the logout hook fires.

Timeouts

Hi,
I am using your plugin to connect to an OpenID Connect server (in my case Keycloak), but I am finding that users that login that way are timing out very quickly (in a few minutes), whereas users that login with a username/password don't have the same issue. Any ideas what I need to change to increase this timeout? I can see a timeout in the plugin settings for requests, but my issue is with the session timing out.
Adam.

mismatch-identity after successful user creation

Hi, thanks for taking up the work of @unagi! 👍

Before investigating the code closer, maybe my problem is a known issue already: After logging in, I get an "ERROR: Mismatch identity" message. The log says "New user created" and "Successful login for", but then comes the "mismatch-identity" error. I tried with sub, preferred_username or name, all give the same error. Our OIDC provider is available here: https://api.learning-layers.eu/o/oauth2/

Any help appreciated! Cheers

Improve autoloader with a prefix check

Taken from this comment

The autoloader should check for a prefix instead of the existence of a file; PHP does cache stat calls but only for a few seconds. (Autoloader functions get called for every class use, not just the classes in the same plugin!)

Sending the wrong id_token_hint at logout

As with #49, this is a problem where the plugin assumes only one session is active at a time. It sends the id_token from the most recent login, rather than the login relevant to the current session. Depending on the IdP, this may or may not log out the correct session.

In the case of Keycloak, this results in a "We're sorry... An internal server error has occurred" when you:

  • log in via browser A
  • log in via browser B
  • log out in browser A

The session in browser A is logged out, and browser B's session is unaffected, but the error message and failure to redirect properly should be fixed.

With some modification to PR #52, the relevant id token could be saved as part of the session for use at logout. Unfortunately, wp_logout() destroys the current session before invoking the wp_logout action, making it impossible to access the token.

For the plugin's own use of wp_logout, this is easily worked around. And for the standard WP logout process via wp-login.php, a hook could be added to the login_form_logout action.

Probably the way to do this would be to store the id_token in a variable from ensure_tokens_still_fresh(), and in another method tied to the login_form_logout action. Then instead of querying the user metadata, it would use the contents of the variable. This should cover all uses of wp_logout that don't happen during init.

(All that being said, it's going to be kind of a PITA to implement. The alternative would be to just not send the token hint at all, unless there aren't any other WP sessions active for that user. The OIDC spec doesn't require the hint, after all...)

Any way of forcing the standard WP login screen when Auto Login is enabled?

I'm planning to enable the Auto Login option so that all Logins to our WP site go through OpenId Connect.

But just suppose that something goes wrong with the OpenId Connection server. Is there then a way of forcing the standard WP login screen to be shown so that I can log in the normal way?

I'm assuming that if I couldn't login via Open Id connect I wouldn't then be able to get to the admin dashboard to change the Login Type setting.

logout url

Hi,

We have openid-connect-generic running in combination with keycloak. Works very nicely, thank you very much!

One issue though: Logging out doesn't work properly:
After installing your plugin, the wordpress logout url has been changed into https://www.oursite.com/wp-login.php?loggedout=true

However, we had disabled wordpress default links, such as /wp-admin and /wp-login url (using the WP Cerber plugin, as a basic security measure) causing the logout link above to generate an error.

Without the openid-connect-generic plugin, the logout url goes to:
https://www.oursite.com/randomstring/?action=logout

Our login url, is also https://www.oursite.com/randomstring, and this works fine, also with the openid-connect-generic plugin activated.

So, can we somehow define a different logout url..?

admin-ajax returning 0

Hi Daggerhart,

Many thanks for all your work on this. I have installed the plugin and after authentication I just get a "0" which I understand is a problem with admin-ajax action not matching a wordpress hook.

An example of my response that fails is:
https://mywebsite/wp-admin/admin-ajax.php?action=openid-connect-authorize?code=bbdae34ac6a040e5712fe78c9a11b828d76e08b355c618b45e9c68e05453078a&state=c2d772e1ce5c7a64eadbb758db6bdee1

The console is showing a 200 response. I am running php 7.0.18 and SSL extensions are enabled.
I saw the other thread on this issue and there does not seem to be a problem with the server returning the "action=openid-connect-authorize". I have tried turning SSL verify ON/OFF.

On another topic :) In the settings you request the End Session Endpoint URL. The OpenID Connect service I am using does not have sessions and many of the other OpenID Connect Plugins I have seen don't request this setting. Perhaps in future versions of the plugin you can make this optional?

Many Thanks
Keith

Alternate method to route callback?

Thanks authors for this great library!

I'm experimenting with it to connect a WordPress site (client) with a Django-based site that serves as the OP.

However, after the Django site authenticates the user, it returns to the WP site where the page just has a "0" ... nothing more. The url is https://(my test WP site).org/wp-admin/admin-ajax.php?state=(some long string of numbers)&code=(some long string of numbers).

I do know the authentication went through ok, as if I go back to the Django site my user is logged in.

I checked the "Enabled logging" feature in the OpenID Connect Client admin page, but no log messages are showing under the "Log" header at the bottom of the page.

I'll keep digging but just wanted to see if anybody had thoughts on how to approach this particular issue?

Attempting to refresh expired refresh_token

Currently, the plugin doesn't check the expiration time of the refresh token, leaving that to the IdP. This results in an error message always being displayed when the refresh token has timed out, even if you don't have the login redirect flag set. (Also, the error message comes from the IdP, and thus can't be themed or translated within Wordpress.)

The plugin should keep track of the refresh_expires_in value, the way it does the expires_in value, and refrain from attempting to refresh an already-expired refresh token.

Register Sequence

Hello,
I try to add register via sso to my site but it seem that it's not working properly.
Let me explain :

  1. I click register on my site
  2. I am redirected to sso provider page
  3. User create his account and receive a mail (parameter sign and data-info are send to the auth server to change the redirect uri)
  4. User click in the mail and he is redirected to our site.
  5. Website(plugin actually) should create a token and send to specific page (/welcome)

here we have a problem. we are redirected to an output 0 (url : https://[mysite]/wp-admin/admin-ajax.php?action=openid-connect-authorize&state=[mystate]&code=[mycode])
image

Plugin seem to not process parameters to generate an access token. It should get a state and code in a local storage to redirect user and create new suscriber... This is quite different from a common login sequence...

Can you please assist on this ?
Thanks

Session refresh should happen in determine_current_user

The current strategy for refreshing tokens and expiring the current session is to run at init or wp_loaded, but after observing the many corner cases for logout and token timeouts (I haven't posted them all as issues yet, believe it or not!), I think that the root of the problems with logout scenarios is that the user is first logged in, and then logged back out.

However, Wordpress has a determine_current_user filter that is used to tell if the user is logged in in the first place. If token refresh/validation runs there, it would be able to simply return false if the session couldn't be continued, just as if their session had timed out normally due to cookie expiration. The request would then proceed just as it would have normally.

The upside to this approach is consistency in interaction with Wordpress as a whole. Rather than some plugins seeing a logged-in user followed by a logout, plugins would simply see no user at all.

The downsides are twofold: first, the filter would need to be added very early in the bootstrapping process instead of init. And there'd need to be some error checking to detect whether the current user has already been loaded when the filter is added, and to then add an admin message warning that there's an incompatible plugin in use. (Or possibly just die(), since the result is an untethered session that can't be terminated.)

Second, we'd have to give up the current way of displaying token refresh errors when the refresh fails. Wordpress has no way that I know of to add user-visible error messages to the current page, so we'd have to rely solely on logging for identifying such errors. (And we could add an action hook so other plugins could act on the errors, perhaps by using a specific plugin or theme support for user-visible messages.)

I think this second issue may be a blessing in disguise, though: the end user has no idea WTF they can do about any error that happens with the IdP anyway; silently logging them out is actually pretty reasonable behavior that has minimal risk of user confusion. The downside would be that it would take a longer time for an admin running a buggy IdP to find out about the issue, as people might just think the timeout was a bit irregular. 😁

Anyway, that's my current thought process on logging the user out. There would still be one corner case this doesn't fix, which is clicking "Log out" when your token has expired. Just as it does currently, that would lead to getting a confirmation prompt, and if you agreed to the prompt, getting an error from the IdP about the session not being active. (I think figuring out a fix for that will have to wait until the rest of this is done, though.)

Host header in user info request ignores port

The "Host" header that is set by request_userinfo ignores the parsed port.
With Keycloak, it resulted in invalid issuer errors.
Modifying line 207 to $host = $parsed_url['host'].':'.$parsed_url['port']; seems to fix it.

Don't force re-login after token expiration

When a user is logged in and the access token expires, the user is redirected to the login page and a notification ("Session expired. Please login again.") is displayed.

It's not always necessary / desirable to be redirected to the login page. When a user was logged in, leaves the site and returns at a later moment, the user is currently -always- redirected to the login page if the access token has expired.

I would like to propose to make this error redirect optional.

Identity Key problem.

Greetings, I have little trouble with Identity Key. After user_info is queried and authorization is performed. On main page wordrpress shows 'sub' as currently logged in user's name, no matter which Identity Key I set up in plugins configurations. Thanks in advance!

Usage with League OAuth2 server?

I'm trying to use your plugin with laravel passport - which is built on top of the League OAuth2 server.
After logging in to my app (the redirect works) I don't see the expected "authorize" window but another login window which looks like a simple .htaccess login window.

I'm just checking out your plugin / looking for a generic oauth2 client

I was wondering if this should work or not and if you have a hint where I should look or let me know if the question is too specific.

Thanks,
Walter

Login URL has a ? in it...

Our Login Endpoint URL has a ? in it so that it breaks the plugin:
https://example.com/authorize.php?request=authorize

When the authentication link is then built it becomes:
https://example/authorize.php?request=authorize?response_type=code&scope=....

Becuase there are two question marks it doesn't work.

I don't consider myself a strong programmer but my suggestion is to change the make_authentication_url() function to check for a ? and then set a variable to use as either a ? or & based on the result:

function make_authentication_url() {
	if(strpos($this->endpoint_login,'?') !== false){$separator = "&";}else{$separator = "?";}
	$url = sprintf( '%1$s%2$sresponse_type=code&scope=%3$s&client_id=%4$s&state=%5$s&redirect_uri=%6$s',
		$this->endpoint_login,
		$separator,
		urlencode( $this->scope ),
		urlencode( $this->client_id ),
		$this->new_state(),
		urlencode( $this->redirect_uri )
	);
		
	return apply_filters( 'openid-connect-generic-auth-url', $url );
}

I've tested this with no ? in the URL and with one and it created the correct authentication url both times. I'd put this in as a pull request but honestly, I'm not sure how to do that... :)

Is this plugin compatible with a multi-site setup?

We have employed this plugin on two sites, one being a single site, the other a multisite setup with two sites in the network. The single site works correctly.

The multisite allows us to log in just fine, but logging out is not working. Checking the network traffic in the browser developer tools, it seems the multi-site logout process doesn't redirect to the authorisation server, so the user is only logged out of WordPress and when requesting the login form, the user is still logged in.

Should the plugin work on a multi-site instance of WordPress?

Auto login error

If I choose autologin option I get:

Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/wp-login.php:63) in /var/www/html/wp-includes/pluggable.php on line 1174

sample configurations

It's supposed that Google is a supported openid provider.
It already provides a metadata URL which should ease configuration:
https://accounts.google.com/.well-known/openid-configuration
Anyway the "End Session Endpoint URL" is not clear. Is it actually what Google calls a "revocation_endpoint"?

Samples of configuration for common providers would be welcome or, better, make use of the metadata URL to automatically fill the fields.

invalid user claim

Hi,

I am continuously facing an 'invalid user claim' error after successfully authentication with our OpenID Connect provider... I have tested my token and checked the return values and made sure it matches what wordpress is expecting as the username..

My setup is correct as it's working on the original 'Generic OpenID Connect' plugin however the only issue with the original version is that it does not create a user if it does not exist inside wordpress.

validate_token_response token_type check should be case-insensitive (fails with keycloak)

Hello,
Thanks for a very useful WordPress plugin. Was just testing it with KeyCloak 2.3.0 final and noticed a very minor bug. In the validate_token_response there is a check that compares the token_type value to Bearer using !==.

This does a case-sensitive check that fails with implementations that return bearer such as keycloak and causes login to fail with "Invalid token response".

Relevant keycloak bug: https://issues.jboss.org/browse/KEYCLOAK-1855

According to the OpenID Connect specification, this check should be case-insensitive.
https://tools.ietf.org/html/rfc6749#section-4.2.2

Thank you.

LemonLDAP SSO + OpenID Connect

I installed OpenID Connect and login working but when returning back to WordPress i get on plugin debug log:

object(WP_Error)#10206 (2) {
["errors"]=>
array(2) {
["http_request_failed"]=>
array(1) {
[0]=>
string(21) "URL was incorrect."
}
["request_authentication_token"]=>
array(1) {
[0]=>
string(40) "Request for authentication token failed."
}
}
["error_data"]=>
array(0) {
}
}

Logout fails

You log in with openid connect and wordpress creates a user if there is not one and then logs in. After selecting to log out, wordpress logs out the user but when you try to login again with openid connect then you login automatically like you didn't log out. This problem can be solved only by cleaning browser's cache (Ctrl + Shift + Del).

Auto login SSO does not work ?

Hi,

I don't know if it is a bug report, a feature request or if I don't understand how to use it but it seems to me that the "auto login SSO" mode is not working, at least not as I expected it to work.

I installed and configured the wordpress plugin in order to communicate with a Keycloak OpenID provider.
I chose the "auto login SSO" because the provider is already used by other applications but in the case of a user having already logged in (from another application), my wordpress site does not detect there is already an open session.

If I check the "Enforce Privacy" option, the previous case works : user is automatically logged in as expected (thus communication with the provider is ok). However, I cannot keep this option because the main parts of my wordpress site should remain public, most content should be readable without authentication.

In other words, I need automatic authentication check (without triggering login on the wordpress site). If the user needs to login twice, this is not SSO and the OpenID provider seems useless.

This plugin is great (thanks for your work) and I'd like to use it. I tried to modify the code to achieve this goal and maybe post a contribution but without success, probably because my knowledge of php, wordpress and openID is limited.
Could you please help me to implement this case ? Thanks in advance.

Frédéric

Integrating with wso2 IS

Hi!
Congrats for the plugin!!
I am trying to integrate it with WSO2 but I get:

ERROR: Incorrect user claim 

Any help?

Logout Url : Adding id_token_hint as optionnal parameter

Hello,
Following openID documentation http://openid.net/specs/openid-connect-session-1_0.html#RPLogout, id_token_hint prevent some denial of service attack and is considered as a best practice. Could you help me to implement it ?
I just wanted to concatenate $url from get_end_session_logout_redirect_url( $redirect_url ) function in \plugins\openid-connect-generic-dev\includes\openid-connect-generic-client-wrapper.php like this :
$url .= '&id_token_hint=' . $id_token_hint;
but I don't know how to get back this token properly...

Thanks very much for your work !

information profile

It's possible to have te access token request in the headers rather than the url ?
because I can not retrieve profile information, any ideas ?
thanks a lot

Override WP user registration form

When using SSO, user registration needs to happen on my IDPs pages, not within WP. For user registration, I expect the sequence to be:

/wp-register.php redirects to
/wp-login?action=register redirects to
my application's custom registration URL, of the form:
https://idp.example.com/auth/realms/myrealm/protocol/openid-connect/registrations?client_id=myclient&redirect_uri=https%3A%2F%2Fmyapp.example.com%2F&state=ee4fd4a4-1031-4757-bd78-aeb8a9071cb9&nonce=e24858d3-d194-455d-8c8c-95d51083265e&response_mode=fragment&response_type=code&scope=openid

which shows MY registration page, and returns back to the wordpress app.

I have not found a hook with which a plugin can provide its own registration URL rather than hit the wp-signup form.

Per spec, `refresh_token` is optional, but plugin fails without it

This line of code prevents login without refresh_token:
https://github.com/daggerhart/openid-connect-generic/blob/b64fab27be1a66d065a060703173a540c4b4b845/includes/openid-connect-generic-client-wrapper.php#L138

Here's the line from the OAuth spec regarding refresh_token: https://tools.ietf.org/html/rfc6749

   refresh_token
         OPTIONAL.  The refresh token, which can be used to obtain new
         access tokens using the same authorization grant as described
         in Section 6.

The OpenID-Connect spec does not redefine this.

4.x Branch Planning

Some notes for next major version of the plugin.

  • leave you logged in without much fuss most of the time, but force you to have authenticated within some time window to do higher-privilege operations
  • could have sessions that don't bother with the refresh tokens or possibly even access tokens
  • support backchannel logout and revocation
  • API for controlling the flow

    There's no way for an arbitrary piece of code in another plugin to say, "give me a login URL with these parameters", for example, let alone, "check if the user authenticated recently enough and if not force re-login", or "try and see if this anon user has logged on into the IdP via another app in this browser, and log them in here if so".

  • backward compatibility
  • Arbitrary headers/.parameters in the auth code request
  • wp-json endpoints for authentication

Structure

Lazy load various services into a simple plugin. The main file registers hooks that either point to the other classes by name, or small wrapper functions that decide whether to invoke the other classes.

Plenty of WP Hooks that allow for in-code alterations for data and services.

Features

Reatures requested in other issues or comments.

API

  • ServiceProviderFactory - singleton/static, loads IdP-specific config, and returns a ServiceProvider
  • ServiceProvider - handles remote calls to the IdP, mapping user claims, and logout redirection via the IdP (Ideally, this would be the only class that directly works with the WP settings, though it might create other objects with some of the settings.)
  • AuthorizationNegotiatorFactory - singleton/static, loads and IdP-specific and Endpoint-specific configs and returns an AuthoriationNegotiator
  • AuthorizationNegotiator - interacts with the IdP to obtain a User (that knows about identity stuff, handles userinfo fetching/mapping) and starts an IdpSession
  • IdpUser - internal object that contains methods and data related to an IDP & a WP_User (such as token responses and scope data).
  • IdpSession - handle an IdpUser's session between WP & the IDP
  • EndpointController - manage routes (admin-ajax, rest api, custom url), manages an AuthorizationNegotiator, and returns the appropriate response.
    based on settings for an endpoint.

Each of these objects should be lazy-loaded, they can be overwritten with WP hooks so other plugin developers can completely replace them if desired.

Data Structures

  • IDP - various settings for connecting to a single IDP
    • (most existing settings the plugin provides... i'll provide these shortly)
    • Associated endpoints.
  • Endpoints - various settings for accepting responses as the SP.
    • URL
    • Headers
    • Additional parameters

UI

  • Manage IDP connections. Could be a private post type (easily to dev the UI), but also fine as a option sub-pages.
  • Manage Endpoints
  • Import & export IDP connections & endpoints

Encode Redirect URL in State to Prevent Issues with Missing Cookies

If an error occurs during the login process (e.g. too long to login, missing state, etc.), handle_redirect_cookie() resets the redirect cookie while on the login page that displays the error message. It should not change the URL if the cookie is set and there is no redirect_to in the URL.

On a related note, why does the redirect cookie have an expiration time instead of being a session cookie? There is no reason I can think of for it to hang around for 24 hours even if the browser is closed, nor for it to expire after 24 hours if the session is still active. ISTM that it should be a session-duration cookie.

Alternately, the cookie could be done away with altogether, by encoding it as part of the state field in the authorization URL. When the callback happens, the state field could be split back out into the state and the redirect URI. All the cookie-specific code would go away, and the redirect URI calculation/cookie setting wouldn't have to be done on every request any more; the redirect URI would be determined on-demand.

ability to derivate new claims from existing ones

Here are user_claims fetched from GSuite:

  ["sub"]=>  string(21) "1234567890"
  ["name"]=>  string(13) "Firstname Lastname"
  ["given_name"]=>  string(8) "Firstname"
  ["family_name"]=>  string(4) "Lastname"
  ["picture"]=>  string(92) "https://lh3.googleusercontent.com/photo.jpg"
  ["email"]=>  string(27) "[email protected]"
  ["email_verified"]=>  bool(true)
  ["locale"]=>  string(2) "en"
  ["hd"]=>  string(18) "mydomain.org"

I would like my user nick to be "me" (= localpart of the email).
For this I would normally, in a hook, create a new element in the user_claim array, derived from "email" and use it as the "Identity Key" instead of "sub" or "preferred_name".
But the openid-connect-generic-user-login-test does not permit user_claim variable modification.
Could this hook be adapted, or a new one created for such a purpose?

Side note, identity = email will not work because if specified it will not strip the @domain-part of the email: It only does if field is left unspecified AND claim "name" is not provided (what is unlikely)

Feature proposal: setting and/or filter to limit refresh token lifetime

I'd like to be able to be able to set a long timeout for refresh tokens on my Keycloak instance, but have some of my sites use a shorter idle timeout (notably, ones that control more sensitive data).

Since we now track a refresh_expires value, there could be a setting and/or filter to put a cap on the validity duration, and the session would be timed out automatically.

I'd be happy to write a PR for this, implemented as an admin setting. Any thoughts?

Using with Keycloak: Config problems (missing documentation)

This is probably not a bug but a config issue:

I am trying to use Keycloak 3.4.1.Final as the IdP. In order to try it out I fired up a fresh wordpress install in docker and added a realm + client to the Keycloak installation. I used different ressources that I could find on this plugin to configure the client.

In order to reproduce use the provided setup and config. Go to the wordpress installation and create an accound / log in via the Keycloak interfce (redirects work).

Here is a part of the config for the Keycloak realm:

name: wp-test-realm
enabled: on
user registration: on
email as username: on
edit username: off
forgot password: on
remember me: on
verify email: off
login with email: on

Some data for the Keycloak client config:

client id: my-wordpress-client-id
Name: WP Client
Enabled: on
*Consent Required: off
Client Protocol: openid-connect
Client Template: -
Access Type: confidental
Standard Flow Enabled: on
Implicit Flow Enabled: off
Direct Access Grants Enabled: off
Service Accounts Enabled: off
Authorization Enabled: off
Root URL: http.//localhost:8080/
Valid Redirect URIs: http://localhost:8080/*/*, http://localhost:8080/wp-admin/admin-ajax.php?action=openid-connect-authorize
Base URL:
Admin URL:
Web Origins: http://localhost:8080/*
*User Info Signed Response Algorithm: RS256
*Request Object Signature Algorithm: RS256

...
Client Authenticator: Cliend Id and Secret
Secret: ***

...
Mappers:
Client ID
email
username
Client Host
Client IP Address
family name
full name
given name

Scope:
tested with Full Scope Allowed: on/off
for off the roles are (copied from Wordpress):
administrator
author
contributor
editor
subscriber 

  • here I tested the different possible values to no avail

This is the plugin config:

Login Type: OpenID Connect Button 
Client ID: my-wordpress-client-id
Client Secret Key: ***
OpenID Scope: email preferred_username family_name given_name (had the scopes here too... no avail)
Login Endpoint URL: http://localhost:8089/auth/realms/wp-test-realm/protocol/openid-connect/auth
Userinfo Endpoint URL: http://localhost:8089/auth/realms/wp-test-realm/protocol/openid-connect/userinfo
Token Validation Endpoint URL: http://localhost:8089/auth/realms/wp-test-realm/protocol/openid-connect/token
End Session Endpoint URL: http://localhost:8089/auth/realms/wp-test-realm/protocol/openid-connect/logout
Identity Key: preferred_username (tried "sub" too)
Disable SSL Verify: yes
Nickname Key: preferred_username (tried "sub" too)
Email Formatting: {email}
Display Name Formatting:{preferred_username}
Identify with User Name: no
Link Existing Users: no
Redirect Back to Origin Page: yes
Redirect to the login screen session is expired: yes
Enforce Privacy: yes (easier for testing)
Alternate Redirect URI: no
Enable Logging: yes

The values for the endpoints can be found in the .well-known openid configuration of Keycloak, e.g.:
http://localhost:8089/auth/realms/wp-test-realm/.well-known/openid-configuration

This is the error I keep getting:

object(WP_Error)#7608 (2) {
  ["errors"]=>
  array(2) {
    ["http_request_failed"]=>
    array(1) {
      [0]=>
      string(74) "cURL error 7: Failed to connect to localhost port 8089: Connection refused"
    }
    ["request_authentication_token"]=>
    array(1) {
      [0]=>
      string(40) "Request for authentication token failed."
    }
  }
  ["error_data"]=>
  array(0) {
  }
}
Type: http_request_failed
User: 0
URI: /wp-admin/admin-ajax.php?action=openid-connect-authorize&state=cdc3ca663b15e5838de9de0fdf415c5f&code=eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0..-ME_w8mcBwpNSRDGY7e-5A.dmPn8pzuUJ5udHXZUfGJITpPv3K9uotf1Ti38W7UZMMIu26aRJT7FLtgK6zvRFhhC-lNl52a02OYnmYLnmCDZJBl8xaH884eiJUzogHPPt_oWNwa4YRGPQrwnrNeBBly0xwAk7MKU0lMim-9lLCTE9sA8H_jdcikcQR46FX9-SfHnZD_hHIYuLuH110te3JH1NZxi_6Dlv-kVYdtowd1KPSd69BkHxanrV_BF5MK-cVN5C60p3T6y3zEU_y7BYLq.EFmOpr5-9Taq5oI4N4NdOA

Are there experiences in setting up Keycloak with this plugin? Can anyone point to the (maybe even obvious) config problems? Will provide short docs, if successful.

Thanks in advance and happy holidays.

Option for changing state time limit

It would sometimes be useful to change the value for state time limit from 3min to something else. For example when IdP requires user to fill some details on first login or when it requires user to read a license agreement, etc.

Hook refreshing into determine_current_user instead of allowing the user to be logged in and then logged out

Taken from this comment

It would be good to hook refreshing into determine_current_user instead of allowing the user to be logged in and then logged out. That way, everything in Wordpress sees an expired SSO session as identical to an expired cookie-based session. (I took a look at doing this with the current code, but ran into the snag that the necessary objects aren't created until init, and the current user is defined before that point.) My plugin does it this way, and other plugins are MUCH happier that way.

End Session Endpoint URL

Filing as seperate issue:

Issue:
In the settings you request the End Session Endpoint URL. The OpenID Connect service I am using does not have sessions and many of the other OpenID Connect Plugins I have seen don't request this setting. Perhaps in future versions of the plugin you can make this optional?

Response from Daggerhart:
Regarding the End Session Endpoint, I think you're right. At a glance, I can't see anything in the Oauth2 spec that requires this, so the setting should be optional. This setting is intended to be the "logout url" that when visited will revoke the current access to the SP.

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.