Currently my application is making use of the authorization state change callbacks to indicate moving between the authorization and the main page sections in my app. (Note: I am not using AngularFire)
In Firebase 3 there is firebase.auth().currentUser however the currentUser is set to null if firebase hasn't finished pulling the data from the server. This value may be null at startup but be set 2 seconds later without the user doing anything with the application.
In my app, the users authorization state should be the determining factor of the first screen that they see, because this is asynchrnous in nature, they're seeing the Authorization page, then after the currentUser updates it's moving them to the home page, which displays a very tacky page switch.
Splash Screen -> Login -> Home
The amount of time on the Login page depends on the internet connection, however on mobile data it is extremely noticable.
Is there any way to force a check to see if the user is logged in that will return true or false? I can make an asynchronous method into a promise, the issue is that the onAuthStateChanged callback isn't called on startup if the user is logged out already.
No. Use .onAuthStateChanged to determine the users Auth state.
In terms of the login showing / blinking prior to currentUser that is an issue fixed by modifying your HTML/CSS. The default view should not display the login elements. Only display that after .onAuthStateChanged tells you the user is not logged in.
Related
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.
I have a problem with Facebook authentication logic:
On home page load, I call getLoginStatus() and if I get "connected", I redirect the user to his account page. If not, the user can click the login button that calls FB.login().
If the user is logged in and then navigates back to home page (full page load), getLoginStatus() there returns "connected" as expected and user gets bounced back to account page.
However, when the logged in user calls FB.logout() and repeats steps 1-2, the 2nd step will always yield "unknown" login status. So, FB.logout() basically breaks my bouncing logic.
I checked the mechanics of login/logout calls and it appears FB.logout() creates a fblo_<appId> cookie with 1 year expiration that blocks getLoginStatus() from returning the proper status. This seems to be the actual mechanism for keeping people logged out, which I can understand. What I can't understand, though, is: why this cookie is not deleted on a successful FB.login() call?
I fixed it myself by programatically deleting the cookie fblo_<appid> in callback functions of both FB.login() and FB.logout()
I was experiencing this a few days ago but I'm not seeing the issue any more.
In either case make sure you consider these different scenarios when testing:
A person logs into Facebook, then logs into your app. Upon logging out from your app, the person is still logged into Facebook.
A person logs into your app and into Facebook as part of your app's login flow. Upon logging out from your app, the user is also logged out of Facebook.
A person logs into another app and into Facebook as part of the other app's login flow, then logs into your app. Upon logging out from either app, the user is logged out of Facebook.
https://developers.facebook.com/docs/reference/javascript/FB.logout/
Debugging tip:
In the Application tab in Chrome you can select Cookies in the left panel and then type fblo into the search box to filter by that name. When I call FB.login and successfully authenticate I see that the fblo cookie disappears - so I believe this issue fixed.
I have a angular application with api calls being made to back end for logging and and so forth. What i need is to be able to tell when the session expires and logged the user out.
I know on every route change i can check if the user is logged in or not which i do right now but how can i handle it when they are idle. So i have instances where the user is on a specific page and remains inactive and although they are logged out in the back end i do not know on the front end and need some where to constantly be checking. Any solutions for the best method.
A client-side solution without polling:
(re)start a timer at each route change to show a message after 15(this number should coincide with the amount of time the user is logged out in the back-end) minutes.
The only downside to this is that if your app sends data outside of route changes the user could receive of notification of being logged out while the user is still logged in.
It would also require that your route changes actually send a request to the back-end.
I am developing ios and android application using java script. How to set my app always logged in state. For example,when i login in my app and then i just shutdown my device and then restart, then i click my app again,but it asks for log in. How to make my application always logged in as in Facebook app.Help me
Use Shared Preference for that. When user logged into your application store login status into sharedPreference and clear sharedPreference when user click on logged Out.
Check every time when user enter into application if user status from shared Preference is true then no need to login otherwise move to login page.
First create class in that class write all the functions set and get shared preference information or in javascript use localStorage to set and get values probably first time login to set userinfo using:
localStorage.setItem("name","vale");
after switch off you try to open your app, at the time use
localStorage.getItem("name") based on that you can load your values.
My project uses Node.js and Express, but the question is about generic approach.
Our users are all from FB and we don't have any auth other than FB. We need to associate some actions with specific FB users and also need their tokens to communicate with FB.
Currently we do it like that:
user comes to the page
there are invisible blocks: one with placeholders for user's avatar and name ('logged-in'), the other with button triggering FB login ('logged-out')
using FB JS SDK we check user's login status. If connected (which actually means: logged into FB, authenticated our app and provided all the permissions we need), we get user's name and FB ID and show the 'logged-in' block. Otherwise the 'logged-out' block is shown
for logged-in user on some actions user's access_token is passed to the server via AJAX (no worries, HTTPS here) and used by the server code for actions like posting to user's wall or whatever
the FB login button is handled by JS and calls for FB.login()
on JS authResponseChanged event obvious actions are taken (show/hide logged in/out blocks)
What's good: we always know that user's status is effective (token's TTL is more than normal page's lifetime, so we are good here).
What we don't like much:
* client-side tokens are short-lived (yes, we can exchange them, but don't want to if we can find any alternative)
* it normally takes several requests to FB (1 - load JS SDK, 2 - get login status) until we can show something. Till that the 'login' block of our site is empty.
What's the question?
We are looking for an optimal way to use some server-side code here and at least render user's name and avatar when we're sure the user is logged in.
I can imagine some scheme like this:
use server-side auth (with redirects) to get the long-living token and persist it on the server
save user's status (logged in / out, FB ID, name) in session
if session has the logged in state, render name and avatar when processing templates on the server
Concerns:
if the user logged our from FB or revoked App permission, how should we know it and when should we check for it (check every N requests? every X hours? check only when token is going to expire in Y hours?)
if we alternatively check for user's status from the server before rendering any template (which is the case in an official example) this will slow things down, right? Cause I think FB API calls can be rather slow in hot hours.
Using the JS SDK is the only feasible way to know a user’s status in “real-time”. (“real time” in quotes, because the result of FB.getLoginStatus gets cached as well – if one wants it to be accurate at all times, one must use the second parameter set to true.)
If you have the JS SDK set up to set cookies under your domain, then the PHP SDK is able to determine the login status of the user without any API lookups over HTTP – it just reads the user ID from cookie, so Facebook::getUser() will get you the user ID. That would be enough to display the picture – but for the user name, that’ll still require an API request.
Here you could opt for requesting the name once – and then saving it into your session. If, on the next request, the JS SDK indicates that the user is not connected any more, you could erase the login info from the page and/or force a reload (and on that, clear the session), to return to the not logged in state.
Actually it's totally incorrect to say that "in order to be real-time, you need to use JS SDK"!
Facebook has "Realtime Updates Graph API" and every time some data gets updated, your local db gets updated automatically, then you don't need to use JS SDK