1

I have an ember application that uses the Auth0 Ember Simple Auth addon to use the Ember-Simple-Auth functionality with Auth0's Lock.js. Recently I have been trying to implement single-sign-onfunctionality, such that if a user logs into a login portal application, their session will be preserved for other applications on the same domain, and they will not need to log in repeatedly. However my implementation of SSO is resulting in an infinite redirect loop between my login logic and Auth0's endpoint.

I have enabled SSO in the Auth0 application settings. My login is implemented in a few blocks.

My route.js contains a beforeModel() method which contains:

if (!get(session, 'isAuthenticated')){
    // Forward to the login action
}

My login action:

login() {
    var session = get(this, 'session');
    session.authenticate('authenticator:myauthenticator', { authParams: { scope: 'openid' } });
}

This grabs the session object, and calls my custom authenticator. So far, this is basically just ember-simple-auth boilerplate, and complies with the examples supplied in the Auth0 Ember-Simple-Auth documentation.

Where I run into trouble is my custom authenticator. The base authenticator is here. You can see that it handles basic login logic easily, including showing the Auth0 lock when a user isn't authenticated. However it has no logic for handling the kind of SSO-session checking that I want to implement. So I implemented a custom authenticator as below, using examples provided by Auth0 for (basically) this exact scenario (you can see their examples [here], I'm using a slightly altered version)3:

authenticate(options) {
 return new Ember.RSVP.Promise((res) => {

    // the callback that will be executed upon authentication
    var authCb = (err, profile, jwt, accessToken, state, refreshToken) => {
        if (err) {
            this.onAuthError(err);
        } else {
            var sessionData = { profile, jwt, accessToken, refreshToken };
            this.afterAuth(sessionData).then(response => res(this._setupFutureEvents(response)));
        }
    };

    var lock = this.get('lock');
    // see if there's a SSO session available
    lock.$auth0.getSSOData(function(err, data) {
        if (!err && data.sso) {
            // there is! redirect to Auth0 for SSO
            options.authParams.callbackOnLocationHash = true;
            lock.$auth0.signin(options.authParams, authCb);
        } else {
            // regular login
            lock.show(options, authCb);
        }
    });
});

}

This behaves mostly as I would expect it to. When I log in with an existing session from another SSO-enabled app on the same domain, if (!err && data.sso) resolves to true, and lock.$auth0.signin(options.authParams, authCb) is called. However, this signin logic is not working as intended. Auth0.signin calls the Auth0.authorize method, which generates a target URL that looks something like:

https://mydomain.auth0.com/authorize?scope=openid&response_type=token&callbackOnLocationHash=true&sso=true&client_id=(MyClientIdHash)&redirect_uri=localhost%23access_token%3(MyAccessToken)%26id_token%3(MyIdToken1).(MyIdToken2).(MyIdToken3)token_type%3DBearer&auth0Client=(MyAuth0Client)

My application is then redirected to this URL for authorization. I get a 302 and am redirected back to the callback URL (my root page). Because there is a new page transition, if (!get(session, 'isAuthenticated')) is hit again. It returns false, and so the same logic repeats itself, looping indefinitely.

Does anyone have any insight on what I might be doing incorrectly here? The authorize endpoint seems to behave as if I were being authenticated, but then the authentication is never actually triggered. I've debugged through this code fairly extensively but seen no obvious red flags, and I've followed provided examples closely enough that I'm not sure what I would change. I'm not entirely sure where the failure to authenticate is happening such that get(session, 'isAuthenticated') is false.

UpQuark
  • 791
  • 1
  • 11
  • 35
  • Are you checking for whether the session is authenticated in the route that actually handles the authentication? That would explain the redirect loop. – marcoow Jun 22 '16 at 09:07
  • Did you ever find a solution to this? – Andrew Backes Jan 20 '17 at 14:33
  • @AndrewBackes Very belatedly- I no longer work on this codebase, but if I remember correctly the fix was just to save the authenticated session in local storage, which was not previously being done correctly. I wouldn't recommend this implementation of Auth0 anyway (unless you have to); we did it this way as a workaround to a bug with older versions of IE that as far as I know Auth0 has since fixed. I think just using their Lock.js samples as a model definitely leads to the cleanest implementations. – UpQuark Jul 08 '17 at 17:33

0 Answers0