0
votes

I have an Auth pipeline.

run(navigationInstruction, next) {
    if (navigationInstruction.getAllInstructions().some(i => i.config.auth)) {
        var isLoggedIn = this.auth.isAuthenticated()
        if (!isLoggedIn) {
            return next.cancel(new Redirect('login'));
        }
    }  
    return next();
}

As you can see it checks if an unauthenticated user tries to access an auth page they get redirected to the login page. This works. Now I'm trying to achieve the reverse of that if the user is logged in and tried to access a non authentication page I want to redirect them to the dashboard

run(navigationInstruction, next) {
    var isLoggedIn = this.auth.isAuthenticated()
    if (navigationInstruction.getAllInstructions().some(i => i.config.auth)) {
        if (!isLoggedIn) {
            return next.cancel(new Redirect('login'));
        }
    }  else {
       if (isLoggedIn) {
            return next.cancel(new Redirect('dashboard'));
        } 
    }
    return next();
}

Now this also works however it causes a bug I believe. If I try to access a non authorization page and I am not authorized it redirects to the login page. So a more specific example is I'm on the login page and I am not authenticated and I'm trying to go to the register page I just get redirected to the login page. Now I thought that for some reason i.config.auth was thinking it was true but I did some debugging and I realized the return next() actually gets hit it loads the register template but then it redirects back to the login page.

I've also noticed that just moving is var isLoggedIn function outside of the if statement the same bug occurs:

run(navigationInstruction, next) {
    var isLoggedIn = this.auth.isAuthenticated()
    if (navigationInstruction.getAllInstructions().some(i => i.config.auth)) {
        if (!isLoggedIn) {
            return next.cancel(new Redirect('login'));
        }
    } 
    return next();
}

UPDATE

Here are my routes

config.map([

  { route: '', redirect: 'login' },
  { route: 'login', moduleId: 'components/login/login', title: 'Login', name: 'login' },
  { route: 'register', moduleId: 'components/register/register', title: 'Register', name: 'register' },
  { route: 'dashboard', moduleId: 'components/dashboard/dashboard', title: 'Dashboard', auth: true, name: 'dashboard' },
]);
1
You may have run into a scoping issue here. Have you tried using "let" instead of "var" for the isLoggedIn variable (either within or outside of the if statement)? That could help prevent the current value from leaking into the next call. - Fred Kleuver
@FredKleuver I had tried switching it to let and I don't think it's a scoping issue because isLoggedIn is always what I would expect even inside the if statements - Rodrigo
What you're describing really shouldn't happen if the auth property is indeed false or undefined on the 'register' route. So if I understand your question correctly: you are not logged in and you navigate from 'login' to 'register'. First, run gets hit and return next(); is called. Second, run gets hit again and return next.cancel(new Redirect('login')); is called. Is this correct? - Fred Kleuver
@FredKleuver no both times return next() gets hit but for some reason when going from login page to register page it redirects back to the login page. Maybe it doesn't redirect but I can see on my console that the register template was loaded but the page just flickers and stays on the login page - Rodrigo
That could imply an error during the activation lifecycle of your register page, because in that case the router automatically goes back to the previous route. Do you have development logging on? Are any errors occurring? Can you maybe include the log output in your question? - Fred Kleuver

1 Answers

0
votes

I'd recommend using Additional Route Data (settings) to store custom settings. This additional data will always be available within pipeline functions.

Here's a complete demo: https://gist.run/?id=b70a094db52e0cc34fd7c44de550f046

  • Home Page is public and available to everyone
  • Dashboard requires authentication
  • Login Page and Register Page are available to unauthenticated users only
  • Use Toggle Login button to change authentication state
  • When one navigates to Dashboard without authentication, redirection occurs to Login Page
  • When one navigates to Login or Register with authentication, redirection occurs to Dashboard

Relevant sections of app.js

Routes

config.map([
  {
    "route": ["", "home"],
    "name": "home",
    "moduleId": "home",
    "nav": true,
    "title": "Home"
  },
  {
    "route": "dashboard",
    "name": "private-page",
    "moduleId": "private-page",
    "nav": true,
    "title": "Dashboard Page",
    // this is going to be available within AuthorizeStep
    "settings": {
      "auth": true
    }
  },
  {
    "route": "login",
    "name": "login",
    "moduleId": "login",
    "nav": true,
    "title": "Login Page",
    "settings": {
      "publicOnly": true
    }
  },
  {
    "route": "register",
    "name": "register",
    "moduleId": "register",
    "nav": true,
    "title": "Register Page",
    "settings": {
      "publicOnly": true
    }
  }
]);

Pipeline

// substitute auth magic
static auth = {
    isAuthenticated: false
}

run(navigationInstruction, next) {
    let isLoggedIn = AuthorizeStep.auth.isAuthenticated;

    // currently active route config
    let currentRoute = navigationInstruction.config;

    // settings object will be preserved during navigation
    let loginRequired = currentRoute.settings && currentRoute.settings.auth === true;

    if (isLoggedIn === false && loginRequired === true) {
        return next.cancel(new Redirect('login'));
    }

    let publicOnly = currentRoute.settings && currentRoute.settings.publicOnly === true;
    if (isLoggedIn === true && publicOnly === true) {
        return next.cancel(new Redirect('dashboard'));
    }

    return next();
}