How to prevent showing pages when not logged in?

My app requires a login and I want to prevent users from going to any deep link in the app unless they are logged in. I’d like to redirect them to /login instead. I tried to call router.navigate from a global routeChaged but that didn’t do anything. Calling router.navigate from mounted in app.vue does work, but all the controls seem disabled (looks like I get into some kind of infinite initialization loop).

Is the built in LoginScreen part of the solution? I need a custom look for the login screen and it seems to only be a visual component. Maybe I should use an login overlay and always show it on top of any page if the user is not logged in?

What’s the right way to do this?

You need a way to determine if the user is logged in via a persistent value of some sort (securecookie, localstorage, indexDB etc)

Then perform a lookup for isloggedin or whatever you wish to call it. If its there, then let them view the page, otherwise route them to the login screen.

That is the general flow of how you would do it. You would obviously want more security then using say localstorage because that can be changed on the client to be true so a secure cookie might be better or indexedDB because it cant be changed on the user side.

If you wish to validate each time the app is opened and wish to keep users logged in you could also use JWT to renew token at login and store the token in the secure cookie to revalidate. As you can see there are options depending on the data sensitivity here

Thanks M, I was aware of most of what you said. What I’m looking for is a way to reroute to a login page for every page, without adding this logic to every page. I tried to do the rerouting on routeChanged but as I said that didn’t work.

Where should I hook the rerouting? On each pages mount event? Somewhere else?

Thanks!

Hi, you can use a “beforeEnter” guard on the router to protect the pages that requires identification.
And personally, my login page is a popup, so when I detect in app.vue that the user is not identified anymore (with firebase, it’s simply listening to an event) I switch the login popup visibility.

Route.js

function checkAuth(to, from, resolve, reject) {
  const { currentUser } = firebase.auth();

  if (!currentUser) {
    reject();

    // If the forbidden page is not accessed in a visible view, we do not launch the animation
    const router = this;
    const { app } = router;
    const thisView = router.view;
    const isInCurrentView = thisView === app.views.current;
    this.navigate('/auth-required/', {
      animate: isInCurrentView,
      reloadAll: true, // TODO : ideally, the parameters should be the same than those of the navigation that triggered the guard
    });
  } else resolve();
}

const routes = [{
  path: '/',
  component: HomePage,
  beforeEnter: checkAuth,
  alias: ['/home/'],
},
{
  path: '/intro/',
  component: IntroPage,
},
{
  path: '/auth-required/',
  component: AuthRequiredPage,
},
{
  path: '/login-signup/',
  component: LoginSignupPage,
},
{
  path: '/contacts/',
  component: ContactsPage,
  beforeEnter: checkAuth,
},
{
  path: '/contact/:contactId/',
  component: ContactPage,
  beforeEnter: checkAuth,
},
{
  path: '/contact/',
  component: ContactPage,
  beforeEnter: checkAuth,
},
{
  path: '/contact-edit/:contactId/',
  component: ContactEditPage,
  beforeEnter: checkAuth,
},
...

App.vue (inside mounted)

  // We hide/show login form based on user authentication and if he has read the intro or not
  let appLoaded = false; // See below for explanation
  firebase.auth().onAuthStateChanged(() => {
    const user = firebase.auth().currentUser;

    this.showLoginPopup = !user;

    console.log('views', this.$f7.views);
    // We reload all the views if the user has changed
    // When the app load the first time, the routes are already correct, so a reload is not necessary
    // TODO: clearPreviousHistory does not work
    if (appLoaded) {
      const settingsReload = { reloadAll: true };
      this.$f7.panel.close('left', false);
      this.$f7.views.parameters.router.navigate('/parameters/', settingsReload);
      this.$f7.views.home.router.navigate('/home/', settingsReload);
      this.$f7.views.events.router.navigate('/events/', settingsReload);
      this.$f7.views.contacts.router.navigate('/contacts/', settingsReload);
    }
    appLoaded = true;
  });
2 Likes

Thanks, beforeEnter is what I needed.

For anyone else stumbling on this, the docs (that I missed) are here:
https://framework7.io/docs/routes.html