How to handle User Login/Out

Hello everyone. Just as the title says I am asking you for the best practice to handle user login/out within your app.

This is what I have done so far:

  1. Split my routes between, LoggedIn Routes and Logged Out.
  2. I am using the App-Root Component with a simple if loggedIn display that view and so on…

I am using pushStates and that on load and here is the catch. navigating through the app normally works. but visiting a specific page will not work. In the page I am doing a simple request to load data but that works only when providing the user information. Since on pageload the userInformation and wether the user is logggedIn or not is still not available, that will not work.

My question here is how to handle that scenario in the best way? I thought about adding events at user login and listening to them and only request data after the user has been loggedIn. But I wanted to ask you guys if you got an idea how to handle it best

@Momo What you have done so far? Any implementation you’ve tried? Are you using F7 login form?

You can use localstorage or root data.

I am using firebase auth. which works fine, and everything when using the pwa/website in the 1 flow

but accessing links afterwards has the problem that, the authentication, and user information is not ready on load.

what i do in App Root is checking wether the user is Authenticated and request addition information about the user from the database and store that in the $root context:

            firebase.auth().onAuthStateChanged(function(user) {
                if (user) {
                    window.user = user;
                    self.$setState({ loggedIn: true }).then(function () {
                        app.preloader.hide();
                        app.views.create('.view-main', {
                            name: 'main',
                            main: true,
                            routes: window.routesMain,
                            url: '/'
                        })
                        app.views.create('.view-left', {
                            name: 'left',
                            pushState: false,
                            routes: window.routesLeft,
                            url: '/'
                        })
                        console.log("go to home")
                        //app.views.main.router.navigate('/home')
                        if(app.width > 960)
                            app.panel.open();
                    });
                    db.collection('Users').doc(user.uid).get().then((doc) => {
                        if(!doc.exists) {
                            self.user.EMAIL = window.user.email;
                            self.$update();
                            app.views.main.router.navigate('/account')
                            return 
                        }
                        //get bussiness information
                        const user = doc.data();
                        self.$setState({ user: user });
                        db.collection('Business').doc(user.BUSINESS).get().then((doc) => {
                            if(!doc.exists) {
                                app.views.main.router.navigate('/account')
                                return 
                            }
                            self.$setState({ business: doc.data() });
                        }).catch(function(error) {
                            app.views.main.router.navigate('/account');
                        });
                    }).catch(function(error) {
                        console.log("Failed to retrieve user document");
                    });
                } else {
                    app.views.create('.view-landing', {
                        name: 'landing',
                        url: '/'
                    })
                }
                app.preloader.hide();
            });

works all fine, but, in the intial page, I need the user information. So, I wait 1st for user to authenticated but the user information from the database is not ready yet. So, either I have to request it again and than work with it but that would mean, on everypage, I request the user information twice, once in app root, and once for the specific page.

My question would be how could I implement it so that I don’t have to request the information twice, and not store ist in localStorage (cause than it will be old information)

What I think about is moving the initiation of view and change of login state to after requesting the user information

Got it! I had the same problem on my Tab View React App. No one responded.

https://forum.framework7.io/t/react-tab-view-firebase-auth-state/

First I did using localStorage

var currentUser = firebase.auth().currentUser;
var user = {
   //assign provided data to user object
}
//store data in LocalStorage
localStorage.setItem('userData', JSON.stringify(user));

Then in any page

componentDidMount() {
    // console.log('Home - componentDidMount :: init');
    const user = JSON.parse(localStorage.getItem('userData'));
  }

Second one is setting user object in root data f7param

// Framework7 Parameters 
const f7params = {
  id: 'unify-travel.web.app',
  version: '1.0.3',
  name: 'uTravel', // App name
  theme: 'auto', // Automatic theme detection
  // App root data
  data: function () {
    return {
      // Demo products for Catalog section
      products: [
        {
          id: '1',
          title: 'Apple iPhone 8',
          description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nisi tempora similique reiciendis, error nesciunt vero, blanditiis pariatur dolor, minima sed sapiente rerum, dolorem corrupti hic modi praesentium unde saepe perspiciatis.'
        },
        {
          id: '2',
          title: 'Apple iPhone 8 Plus',
          description: 'Velit odit autem modi saepe ratione totam minus, aperiam, labore quia provident temporibus quasi est ut aliquid blanditiis beatae suscipit odio vel! Nostrum porro sunt sint eveniet maiores, dolorem itaque!'
        },
        {
          id: '3',
          title: 'Apple iPhone X',
          description: 'Expedita sequi perferendis quod illum pariatur aliquam, alias laboriosam! Vero blanditiis placeat, mollitia necessitatibus reprehenderit. Labore dolores amet quos, accusamus earum asperiores officiis assumenda optio architecto quia neque, quae eum.'
        },
      ],
      user: {},
      isSignedIn: false
    };
  },
  view: {
    pushState: true
  },
  // App routes
  routes: routes,
  // Register service worker
  serviceWorker: {
    path: '/service-worker.js',
  },
};

Update root data user object in firebase.auth().onAuthStateChanged

var that = this;
that.$f7.data.isSignedIn = true;
that.$f7.data.user.displayName = currentUser.displayName;
that.$f7.data.user.photoURL = currentUser.photoURL;
that.$f7.data.user.phoneNumber = currentUser.phoneNumber;
that.$f7.data.user.nicNumber = userData.userNIC;

Then in any componentDidMount

authOnChange() {
    // console.log('Home - authOnChange :: init');
    if (this.$f7.data.isSignedIn == true) {
      this.setState({
        isSignedIn: true
      });
      // this.$f7.preloader.hide();
      if (!this.$f7.data.user.tourGuide) {
        this.setState({
          run: true,
        });
      }
    } else {
      setTimeout(() => this.authOnChange(), 5000);
    }
}

componentDidMount() {
    // console.log('Home - componentDidMount :: init');
    if (this.$f7.data.isSignedIn == false) {
      this.authOnChange();
    }
}

Hope this help!
Let us know if you’ve use any different approach.

Happy Coding!

Thanks for your reply, I don’t want to use localStorage

I have changed my code to only initialize views after the authentication has happend and the user Data was recieved its an intial delay but yeah i guess thats the best way. For all the other data I just request it again on everypage, I know it means 1 query more at loading time but the data is always update

I have a user object in Vuex to handle my user state (and other related data) across the app. That way I can check the logged in value before entering a page and direct accordingly.