oidc-wp / openid-connect-generic

WordPress plugin to provide an OpenID Connect Generic client
https://wordpress.org/plugins/daggerhart-openid-connect-generic/
259 stars 154 forks source link

Separate Sign In, Sign Up, and Change Password Auth URLs #425

Open backpackingseries opened 2 years ago

backpackingseries commented 2 years ago

Hi,

I am using the shortcode [openid_connect_generic_auth_url] to power a button element redirecting to the Cognito's hosted UI page. Everytime I click it, it opens up the Sign In tab. In other words, a new user needs to click the Sign Up tab to get started.

It would be nice if I could create two separate button / menu elements redirecting the users to the appropriate tabs of Sign In or Sign Up. Thanks

Kind regards,

timnolte commented 2 years ago

This can get complicated pretty quickly, and typically the use case for this plugin is to provide central identity management by IT and there is rarely a concept of user sign-up. Are you allowing users to sign-up without any sort of approval? I ask because if the sign-up flow doesn't end up with a user being automatically logged in then that flow really isn't going to work with the plugin. Not to mention that you are going to run into timeout issues with authentication as the plugin will expire the state that is required to resume a login session on the WordPress site because a sign-up process will take way too long.

To be clear the primary use case of this plugin is for WordPress user management/site login to the Dashboard and not for use as a site membership login.

backpackingseries commented 2 years ago

Apologies if I have misunderstood. I am not an experienced OpenID user at this time. But please allow me to explain what I am after.

When I use the shortcode [openid_connect_generic_auth_url], it redirects to the hosted UI page of Cognito, I see the following screen. This is the default Hosted UI at Cognito:

Signin Cognito Screenshot from 2022-08-15 18-38-51

It offers an option to click the SignUp link shown underneath (Need an account? Sign Up). When I do so, the URL changes to display the following:

SignUp Cognito Screenshot from 2022-08-15 18-39-03

Similarly, there's another click to Change Password:

Screenshot from 2022-08-18 07-07-14

Yes, I am considering typical WordPress workflows for WooCommerce and Membership sites using your plugin with AWS Cognito where customers / subscribers / blog contributors can create their own accounts without approval. However, I do not expect this plugin to handle role allocation, account approval workflows, etc.

Instead, I simply want to provide distinct navigation menu items for Sign In, Sign Up, and Change Password to improve the UX. This is how I have been using Login by Auth0 and now, if possible, looking to migrate few of my projects over to Cognito with your plugin.

Edit: To accomplish this, wonder whether we could have distinct shortcodes like: [openid_connectgenericlogin__auth_url] , [openid_connect_genericregister_auth_url], and [openid_connect_genericchangepassword_auth_url] corresponding to the options on Cognito's hosted UI page.

Kind regards,

zabalajka commented 1 year ago

Yes @backpackingseries, something like this could be achieved by having two additional settings in the plugin (Signup endpoint, Password reset endpoint) and corresponding shortcodes. In my previous project I did exactly this, because we wanted to have separate link for Login and separate one for Signup. [1]

However, I don't think this should be part of the openid-connect-generic plugin, because I feel it goes against the nature of OpenID Connect specification, where you have one /authorize endpoint, and it is up to the IdP how it gets the user (login, 2FA, signup, invite link, ...).

If you still wish to have separate buttons, you have at least these options:

Option 1: Shortcode attribute endpoint_login

Wiki article for Shortcodes mentions endpoint_login attribute which overrides the Login endpoint URL. Usage:

<a href="[openid_connect_generic_auth_url endpoint_login='https://.../authenticate']">Login</a>
<a href="[openid_connect_generic_auth_url endpoint_login='https://.../signup']">Signup</a>
<a href="[openid_connect_generic_auth_url endpoint_login='https://.../reset-password']">Reset password</a>

Option 2: Define your own shortcodes outside of the plugin

add_shortcode( 'openid-connect-generic-login-url', function( $atts ) {
    $url = OpenID_Connect_Generic::instance()->client_wrapper->get_authentication_url( $atts );
    $url = str_replace( '{action}', 'authenticate', $url );
    return $url;
} );

add_shortcode( 'openid-connect-generic-signup-url', function( $atts ) {
    $url = OpenID_Connect_Generic::instance()->client_wrapper->get_authentication_url( $atts );
    $url = str_replace( '{action}', 'signup', $url );
    return $url;
} );
<a href="[openid-connect-generic-login-url]">Login</a>
<a href="[openid-connect-generic-signup-url]">Signup</a>

This still uses OIDC to store the configuration (if you define Login endpoint URL = "https://some.idp.com/openid/{action}") and to generate all the parameters for the URL. This is just an idea, I don't have experience with Cognito's service.

Maybe @timnolte's approach in oidc-keycloak-sso or oidc-generic-button-text-addon could be used here to extend the plugin.

Option 3: Single link

Or, perhaps, you could get away with only one link having both words "Login / Signup".

Edit:

Proposed solution: prompt=create

There is new addition to the specification allowing RP to indicate to the IdP that user creation is desired:

A value of [prompt=]create indicates to the OpenID Provider that the client desires that the user be shown the account creation UX rather than the login flow. -- Initiating User Registration via OpenID Connect

I would like to propose to support passing the (optional) prompt parameter to the [openid_connect_generic_auth_url]. It seems to be a small change, I'd be happy to prepare it. And we should probably check if at least some of the relevant identity providers support the create value since it was finalized in Dec 2022.

-- [1] Later, this approach was discarded, because it was confusing for the users which option should they choose (we had multiple websites connected to the central IdP; if I register on website X.company.com, should I register again on website Y.company.com? and then Z.company.com?). And we ended up designing the IdP exactly like you posted in the screenshots (Forgot password?, Need an account? Signup up).