How to handle authentication flow in a React Web App? - javascript

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! :)

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.

Related

Allowing specific actions for non signed-up users in firebase

I am starting a little learning project that would involve the following scenario:
User enters the page, there is a counter on the page which is connected to real-time database on firebase he/she presses the button, counter goes up, database is updated, but this user is not allowed to increase the counter anymore. Even when the app is closed and he/she opens it in couple of days.
The question is: is it possible to achieve something like this without explicitly login user in? So that on subsequent sessions the prohibition persists based on IP address or something. Maybe it could be achieved with local storage?
Thanks for any responses and ideas!
What you're describing requires that you can identify the app instance: the specific installation of your app on a certain device. For Firebase the easiest way to do this is using Firebase's anonymous authentication. This creates a unique identifier for the app instance, without requiring the user to enter any credentials.

What should happen when clicking the back button in an angular2 routing app?

I have implemented the angular2 routing concept with modules in my web application. Everything works fine.
The problem is I'm not sure what should happen upon clicking the browser back button which sends to the previous page normally. In my situation I see that by default the browser back button sends my app to the previous routing path and so on until it reaches the initial-home page.
Should the back button behave in such way on SPA applications or should it send the user to the home page directly?
Should the back button behave in such way on SPA applications or should it send the user to the home page directly?
The fact that your application is a SPA should be transparent to the user. This is the whole purpose of using a router: that the current state of the SPA can at least partially be read from the route. It also enables sharing the links or saving them as bookmarks. For more advanced usages, it also enables server-side rendering, which then leads to possibility for search engine optimizations.
That said, this is what it should be like and what the users probably expect. Your application can do whatever it likes. If you want back button to go to the home page instead of to the previously visited page, make sure that you do not push anything to the browser's history, and instead just replace it.
Note, however, that you cannot imitate this if the user has never landed on the home page. If she comes from a Google search result, or from a link that friend has sent via e-mail, for example, website.example/foo, and she navigates to website.example/bar from there, you have no way to imitate that the back button should take her to website.example. This would be a security issue.

How can I 'lock' a page behind a log-in screen in jQuery/Bootstrap/JS?

I've been building a web app using Google's Firebase as a backend (for those who don't know, it's a Realtime database; any changes in data are reflected instantly and updated), there's other people working on the Android app with it so there's no other option (plus it's kinda cool). I was surprised that I have yet to write a single line of php or any server-side code. Anyway, jQuery is working perfectly fine for login and stuff.
Now I'm going to be making an admin page (with a separate login from the main users login). It'll be accessed in a completely separate way (by opening something like /admin.html). So the login can't be put on a separate page so people don't 'accidentally' access the admin panel by writing /admin.html in the address bar.
So I want to stop the admin page from completely loading until I've received confirmation from Firebase that the credentials are correct. So how can I achieve this knowing that both the login and the whole admin page needs to be in the same file. I'm positive this can be achieved with simple jQuery + Bootstrap but I'm not really sure how. Can anyone please point me in the right direction. Thanks in advance!
I have googled it of course but maybe my wording is off? :P
If I'm understanding your question correctly, your problem is that you need to create two separate views in a single file, and redirect to one or to another depending on your user "session", however, as all your code is in client, you don't have a "session" system operative.
Ok, there are several options you can take. I like the idea of using LocalStorage to store the user session.
When /admin.html is requested, your code checks for a valid session object (keep in mind that you'll need to define that session object) in the LocalStorage. If there is a valid object, you render the admin area, if there isn't any, you render the login area.
When someone sends username/pass to the database and you receive a valid response, you create a session object, store it in the LocalStorage and reload the page.
Keep in mind that you'll need to create a mechanism to make sessions die and a log off view.
For the dying sessions, as an idea, you can store the creation time and a expiration time in the session object. Each time a "session protected" page is served, when you check that the session object exist, you update it's expiration date a fixed amount (20 minutes plus current time, for example).
So, when you check if exists a valid session, you also check that it's expiration date has not due, and if it's, you delete the object.

Javascript Best Practise: Syncing Browser Windows

I have an html5/javascript application in which multiple users can be viewing the same set of data of any given time. For the sake of a real world example, lets say its a calendar type page.
So user1 is looking has the browser open and looking at the calendar page and user2 is also on the calendar page. User2 makes a change to the calendar and i'd like (as quickly as possible) for those changes the be recognized and refreshed on user1's screen. What is the best way to do this?
I'm thinking about have a mysql table for active users that stores the page they are currently on and a timestamp for its last update, then use ajax calls to ping the server every few seconds and check for an updated timestamp, if its newer than what they have client side, the new data gets sent and the page "reloaded." I am putting reloaded in quotes because the actual browser window will not be refreshed, but a function will be called via javascript that will reload the page. Sort of the way stack overflow performs its update checks, but instead of telling the user the page has changed and providing a button for reload, it should happen automatically. If user1 is working away on the calendar, it seems it might be quite annoying for user2's screen to constantly be refreshing...
Is this a horrible idea? Is pinging the server with an ajax request every few seconds going to cause major slow downs? Is there a better way to do this? I would like the views on either users side to be real time because its important that user1 not be able to update an element on the calendar page that user2 has already changed.
Update: based on some web sockets research it doesnt seem like a proper solution. First its not compatible with older browsers and i support ie8+ and second i dont need real time updstes for all users on the site. The site is an account based applicatiin and an account can have multiple users. The data needs to sync between those users only. Any other recommendations would be great.
You need realtime app for this. You should have a look at socketio. Everytime a user log in, you make him listen for changes on the server. Then when something changed on the server, every users listening are notified.
you can find examples on the official website : http://socket.io/

How to detect moving to different domain page?

I have a ruby on rails app and I want to detect user moving to different domain page
while in model creating wizard.
I stored model-data to DB at first-step of wizard and redirect_to second-step of wizard.
And I want to destroy it if user moving to different domain page while in second-step.
I already find a way to hook onbeforeload event to show warning to user.
But I want to warn it only if user moving to different domain page but not to third-step.
And if user want to moving different domain page then I want to destroy stored data.
What is a best solution to do this? Is there any way to detect where user want to go?
EDIT:
In second-step I want to create model from user upload file(ajax upload with jQuery File Uploader) and associate with first-step's model. So if I can get which id will assign to first-step's model then I can easily associate with it. This is why I want to store data in first-step.
And I don't want to expire unfineshed model until user explicitly leaving wizard.
Then can I detect whether user still opening wizard and just stopping very long time or
already leaving wizard page?
(I want to build app just like a desktop application so user can have unsaved file until explicity leaving wizard on multiple browser window)
That's is not possible. Once your page is unloaded you cannot do anything else. If the user is loading another domain page then that domain has control over the page, not you.
What you should do is store the data of the wizard pages not in db but on session state or even in a cookie, this is the good practice. Then, when user reach the final step of the wizard you read the data from cookie/session and write to db at once.
You cannot determine the user's intended destination within the onbeforeunload event, or any other. You also can't stop a user's request to load another page and instead redirect them to some destroy action before sending them off on their way.
If you are content with storing data into the database on each step as the user progresses through your wizard, you can look into setting up a cron job to run a rake task you create which can go through and delete incomplete wizards that are older than a certain age.
The cron (or equivalent) actually is something I'd consider doing even if you could detect a user leaving your site.

Categories

Resources