Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problems with implicit login in > 3.6 #536

Closed
renrizzolo opened this issue Sep 13, 2018 · 7 comments
Closed

Problems with implicit login in > 3.6 #536

renrizzolo opened this issue Sep 13, 2018 · 7 comments
Milestone

Comments

@renrizzolo
Copy link

Hi guys,
I've upgraded the plugin form 3.5.2 to 3.7, and the implicit login flow I had set up no longer works.
Previously, auth0-login-form.php checked for implicit, then posted the state and token (if it was in the hash) to index.php?auth0=implicit, which parsed the info and logged the user in, and redirected to state.redirect_to.

It looks like in 3.6.0 the login form templates were changed and cookie based state / nonce validation was added.

My question is how can I implicitly log in a user with a url like wp-login.php#id_token=${id_token}&state=${state} in the current version?

I can't get the state to validate and my token doesn't have a nonce (it's generated by a react-native-auth0 webAuth login if that helps; I build the state object in my app)

Is it just not intended to be used like this?

Thanks!

@joshcanhelp
Copy link
Contributor

@renrizzolo - Apologies for the delay here, I don't recall getting a notification for this.

Are you using the built-in implicit flow or something custom? We always test that flow along with the regular redirect flow before releases so I'm not aware of any problems with the existing flow. If you're not doing anything custom, can you provide repro steps?

TL;DR on state and nonce verification ... State needs to be generated, sent in a state URL param, and stored in a cookie which is verified here for both login flows:

https://github.com/auth0/wp-auth0/blob/master/lib/WP_Auth0_LoginManager.php#L155

Default cookie name is auth0_state so if you're not using the core plugin process to generate, you'll need to store what you send in that cookie.

The nonce value is similar, validated here from a value in the ID token:

https://github.com/auth0/wp-auth0/blob/master/lib/WP_Auth0_LoginManager.php#L352

That value needs to be generated and sent to Auth0 in a nonce URL parameter. Default cookie name for that one is auth0_nonce.

Let me know if that's unclear or you still need guidance. I'll leave this issue open for now 👍

@renrizzolo
Copy link
Author

Thanks for your reply @joshcanhelp,

So the gist of what I'm doing is:

Authenticate user in react native app via react-native-auth0 webAuth

auth0
      .webAuth
      .authorize({
          initialScreen: 'signUp', 
          scope: 'openid email offline_access', 
          audience: 'https://mydomain.auth0.com/userinfo' 
      })
...

Now I have a token, which I can use for getting/posting as the wp user via wp REST API (with wp-jwt-auth plugin).

The part my question relates to:

a particular process can't be done in-app, so I have a web login function that redirects to the right page.
The user is logged in to the app so they shouldn't have to log in again when redirected to the web.
If the user was already logged in on the web, I just show a 'continue' button that links to the decoded state's redirect_to in place of the login form (small addition to if ( is_user_logged_in() ) in the login-form.php template).
If the user wasn't already logged in to the website, this logs them in and redirects to the correct url.

    static handleWebLogin(id_token, redirect_to) {
        const interim_login = false;
        const uuid = (new Date().getTime()).toString(16);
        const stateObj = {
            'interim': interim_login,
            'uuid': uuid,
            redirect_to,
        };
        const JsonState = JSON.stringify(stateObj);
        const state = base64.encode(JsonState);
       handleWebLink(`${endpoints.base}wp-login.php#id_token=${id_token}&state=${state}`);
    }

This was working previously.
As you can see, I have no way to set the nonce cookie coming from the app / outside of WordPress.

@joshcanhelp
Copy link
Contributor

Just for context around this change ... the nonce check in the ID token and the state validation are both recommended security precautions that were not built into the plugin until v3.6.0.

For your specific case, I see what you're trying to do here and it's clear why it's not working with your current implementation. But we might be able to work around what's there.

Starting with state ... the login process verifies that the state parameter that's passed (for implicit, that comes in as a POST to the callback from the wp-login.php page) matches what's in a cookie (again, default name for that is auth0_state). I don't see why you couldn't set that cookie in JS and pass it along with the request:

// Using the js-cookie library for simplicity's sake ...

    static handleWebLogin(id_token, redirect_to) {
        // ...
        const state = base64.encode(JsonState);
        Cookies.set( 'auth0_state', state );
        handleWebLink(`${endpoints.base}wp-login.php#id_token=${id_token}&state=${state}`);
    }

But the nonce value isn't possible as you can't decode the token, add a nonce, and encode it again (unless your ID token algorithm is set to HS256, which we don't recommend). So I think your best bet is to generate a new ID token with that nonce using silent auth. Your redirect should be something like:

// Using the js-cookie library for simplicity's sake ...

    static handleWebLogin(id_token, redirect_to) {
        // ...
        const state = base64.encode(JsonState);
        Cookies.set( 'auth0_state', state );
        const nonce = base64.encode(AnotherGeneratedValue);
        Cookies.set( 'auth0_nonce', nonce );
        const authorizeUrl = 'https://' + auth0Domain + '/authorize?scope=openid&prompt=none&response_type=id_token&client_id=' + auth0ClientId + '&redirect_uri=' + endpoints.base + 'wp-login.php%3Fauth0%3D1&state=' + state + '&nonce=' + nonce;
        handleWebLink(authorizeUrl);
    }

As long as someone is already logged into Auth0, this will generate a new ID token with the nonce value in the payload. I can't guarantee this will work as-is but it's a starting point at least.

@renrizzolo
Copy link
Author

This is great, thanks so much!
I totally forgot I could be setting cookies from js - I'll give it a go on Monday.

@joshcanhelp
Copy link
Contributor

Happy to help! I tried it out and it worked as expected. The one thing to keep in mind with silent auth is you'll get redirected back with an error URL param if you're not logged in. You'll want to check that case and make sure it does what you're expecting.

I'll close this for now, let us know if you have any issues here!

@joshcanhelp
Copy link
Contributor

@renrizzolo - I wanted to give you a heads up on this solution ... I'm releasing 3.8.0 today which changes how the implicit flow works a bit. Going forward, you don't want to use the /wp-login.php as a callback for an authentication request. That was just rePOSTing authentication data to the main callback URL, /index.php?auth0=implicit. The change needed in the code snippet above is to change:

... '&redirect_uri=' + endpoints.base + 'wp-login.php%3Fauth0%3D1' ...

... to:

... '&redirect_uri=' + endpoints.base + 'index.php.php%3Fauth0%3Dimplicit&response_mode=form_post' ...

Please let me know if you have any questions about that.

@renrizzolo
Copy link
Author

Thanks for the heads up @joshcanhelp.

following up with the above solution, I actually ended up having to make my own callback url in wp that sets the state and nonce cookie then redirects to the silent auth.
It doesn't appear to work on iOS but I haven't had a chance to investigate that (the error is login_required).

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 19, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants