0

I would like to discuss a paradigm that I am following for the authentication flow in a React Web App and need your advice / suggestions on the same.

The app has a button in the top right corner which is rendered conditionally based on user’s auth status. If a user is signed in, the button says Hi, first name on click of which the user can access protected routes else it’s just a Login button.

Current flow:

Every time user access the app, a spinner displays before rendering the actual route till user’s auth status is being detected by Firebase’s onAuthChanged() which takes a few seconds. Once onAuthChanged() conveys the auth status, app renders the route with the button in top right corner based on auth status.

Issue with the current flow:

Above mentioned flow doesn’t feel like a seemless experience for the user. Because every time user is accessing the app again or even refreshes its browser, it has to wait for that annoying spinner to go away. This is a pretty bad user experience.

Most of the app can be interacted irrespective of auth status, so it doesn't make sense to display a spinner across entire app even if it’s a public route just because auth status needs to be known in order to conditionally render that button. This flow makes the app completely unusable until the auth status is not detected by Firebase. Plus, as all the routes are lazy loaded, it adds up time for user to access app for first time with the 1st spinner being displayed as a fallback for lazy loading the route and the second one for the auth status.

Solution to current flow:

I have thought of a solution which can help me with above. What I am thinking now is to shimmer that button till the auth status is being detected by Firebase. And this seems like a pretty neat solution because now use can interact and browse the app while the button is being shimmered.

Drawbacks of the solution:

But this button is actually not alone in upper right corner and is accompanied by three other buttons as well which link to some other public routes. So, it’ll make UI quite inconsistent by shimmering only that one button, so I’m thinking that I can shimmer all four of them. But this even might seem annoying to user that the entire app loads quickly on refresh, but the upper 4 buttons still shimmer for few seconds and it cannot access any of those to access other public routes.

Alternate solution:

There’s a third and last iteration to the solution, in which I’m thinking to cache the auth status as a boolean check in local storage whether it’s logged in or not along with it’s first name. Now, the app will be totally seemless on browser refresh and repetitive app access.

Caveats:

But, let’s suppose the user has changed his first name on other device and user accesses the app on this browser, the button will show it’s old name cached in the local storage. To sync the name, I’ll have to store the updated name from onAuthChanged() in local storage, update in redux from local storage and then display it on the button. Now, this will seem like a bug to user and might report as well because the old name will flash for a few seconds till the updated name doesn't come from the onAuthChanged()

CONCLUSION: I’d be like to know your views or if you have a better flow than these above. Thanks! :)

Vinay Sharma
  • 3,291
  • 4
  • 30
  • 66
  • Calling a firebase api every time your page loads is really a bad idea ,go for local storage thing store the token ,check its expiry its much quicker . – Shubham Dixit Jul 18 '20 at 10:11
  • `onAuthChanged()` isn't an API as such and more like an auth listener, which is a prerequisite in any Firebase based auth. If don't use it, the user's meta data will never be synced across all the devices due to the stale data kept in local storage. – Vinay Sharma Jul 18 '20 at 11:20

1 Answers1

1

Your Alternate Solution is the best bet according to me.

Even if your user changes name on some other device, once the user logs in on web it will first fetch from localStorage and then due to onAuthChanged() it would give the user old name only for a few second and then display the new name.

Its not like user is going to change the name often, it will be only once in a while and few seconds to update the name once in a while would not be a big issue.

  • 1
    Totally agreeing with the above answer. A small addition to it. @Vinay, you can use [localStorage or sessionStorage](https://stackoverflow.com/a/5523174/13907595) depends on your requirement. Instead having `username -> boolean` mapping, use `userId -> boolean`(or any unique field per say) if possible to avoid `username` change issues. – Prathap Reddy Jul 18 '20 at 11:19
  • great point by @PrathapReddy this would help you avoid some potential pitfalls – Shaurya Vardhan Singh Jul 18 '20 at 11:34
  • 1
    @PrathapReddy I didn’t mean to set a **boolean** check for username. I meant to cache 1st, The `auth status` which will be a boolean check if a user is signed in or not and 2nd, the `name` of user. Caching the `user id` won't make any sense. Because I want to display the user's name in that button, not its `id`. Let me know, if I interpreted your comment wrongly. – Vinay Sharma Jul 18 '20 at 14:43
  • @Vinay, my bad. You are right. Discard the second point suggested on mapping. The first point on `localStorage` vs `sessionStorage` still holds good. – Prathap Reddy Jul 18 '20 at 16:26