Search code examples
ember.jsmixinsember-simple-auth

Ember simple-auth AuthenticatedRouteMixin or UnauthenticatedRouteMixin on route depending on condition


I have a route that should be AuthenticatedRouteMixin or UnauthenticatedRouteMixin depending on the response coming back from the server. How do I implement this?

Presently, I have a route with AuthenticatedRouteMixin and I am forcing the route to be authenticated and de-authenticated by overriding my beforeModel and implementing the willTransition action as follows.

beforeModel() {
  this.set('session.isAuthenticated', true);
  return this._super(...arguments);
}

And

  actions: {
    willTransition: function(){
      if (Ember.isEmpty(_this.get('session.data.authenticated.token')))
      {
        this.set('session.isAuthenticated', false);
      }
    }
  }

However, there are two issues with this.

  1. It looks and feels wrong. There is probably a better way to do this.
  2. There are some unintended consequences to this. If not logged in and then try to login, a user needs to refresh the page before it redirects to the appropriate page. I looked into the simple-auth code and a transitionTo function is not acting as expected.

    sessionAuthenticated() {
      const attemptedTransition = this.get('session.attemptedTransition');
    
      if (attemptedTransition) {
        attemptedTransition.retry();
        this.set('session.attemptedTransition', null);
      } else {
        this.transitionTo(Configuration.routeAfterAuthentication);
      }
    }
    

this.transitionTo(Configuration.routeAfterAuthentication); is the line that is not transitioning. I have verified that Configuration.routeAfterAuthentication is set correctly.

I may force a reload at the login route or where ever route a user navigates to, but (I think) because of issue 2 above, I am running into infinite redirects.

I would love to do something like the following:

import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';
import UnauthenticatedRouteMixin from 'ember-simple-auth/mixins/unauthenticated-route-mixin';

const { service } = Ember.inject;

var mixin;
if (service('session').isAuthenticated){
  mixin = AuthenticatedRouteMixin;
}
else{
  mixin = UnauthenticatedRouteMixin;
}

export default Ember.Route.extend(mixin, { ... })

However, I am not getting info from the session. I am not sure but maybe the specific Ember.Route needs to be loaded to get that info.

Any help would greatly be appreciated.

Update

I may force a reload at the login route or where ever route a user navigates to, but (I think) because of issue 2 above, I am running into infinite redirects.

I figured this part out. I just set a key/value in the session. If it is true, reload and remove the key or set it to false, so the reload only happens once.


Solution

  • Well, the right way to do this is to do what the mixing is doing manually in your route. Check out the source code.

    Its not that hard right? The interesting thing is: Why would you want to have the AuthenticatedRouteMixin when the session is authenticated and the UnauthenticatedRouteMixin when the session isn't? Thats basically the same behavior as when you wouldn't include any of the mixing.

    Because the AuthenticatedRouteMixin only changes the behavior when the session is not authenticated, and UnauthenticatedRouteMixin only changes the behavior when the route is authenticated.

    But something like that in your route is what you asked for:

    beforeModel(transition) {
      if(...) {
        if (!this.get('session.isAuthenticated')) {
          transition.abort();
          this.set('session.attemptedTransition', transition);
          this.transitionTo(Configuration.authenticationRoute);
          return;
        }
      } else {
        if (this.get('session').get('isAuthenticated')) {
          transition.abort();
          this.transitionTo(Configuration.routeIfAlreadyAuthenticated);
          return;
        }
      }
      return this._super(...arguments);
    },