A proper approach to FB auth - javascript

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

Related

How to secure web pages with token based authentication?

I'm building a website using ruby on rails which is hosted separately which makes requests to another backend api rails app which is again hosted separately. Obviously i've setup the backend api with token based oauth authentication.
Now since im not dealing with sessions, and it being stateless n all, How can I stop users from accessing certain view pages in my front end web app? For example, I have a consumer/booking page. I don't want the user to access this page without being logged in. But anyone can just enter the url and open any page they want right now.
On user login (ajax call from .js.erb files), im getting the token and storing it in localStorage variable for every future request to the api. I know I should use this token somehow to stop users from access restricted pages. But I just dont know how.
Now as you have stored the token in the localStorage, you will need to pass this token with the request to the page where you want to restrict access and check if the user is authorized to access the page or not.
TL;DR: there is no standard method or library for this; you must implement such functionality as you see fit.
I'm assuming you're using some sort of front end framework like react; if so, then any request to change the current view should be terminated if there is no valid token in localStorage. Check out this post regarding conditional rendering in React; if you're using something else, the methodology is still pretty much the same.
Otherwise, I would build a small script to include in the beginning of every page that checks whether or not there is a valid token and if there isn't, calls window.history.back() to return the user to the previous page.
(Another way of doing it is to intercept every call to a static HTML file on the server, check if there's a token, and send the file if there is. Otherwise, you can send a custom error page or whatever).

How to log in remotely with AJAX?

I'm making a google-chrome-extension for a certain website, and want the browser_action to display the number of notifications a user has received on said website.
Currently, I am using an ajax request to retrieve the HTML from the website/messages page, and then I am using jQuery to count the number of "#unread > li" elements in that HTML (each one representing a new message.)
Now, I take this number and display it on the browser_action icon.
All works perfectly, the correct amount of messages are notified, BUT the user must be logged in on the site (not my site) for it to work properly, otherwise they will think that they have no messages.
I was thinking that I could detect if the user is logged in, and if not display a red ! exclamation mark on the icon. Then, when the user clicks to show the pop-up, it asks them to log in.
However, I have no idea how to actually log the user in to the website using this method: how do I send the credentials across? Or does the website have to support a request like this?
TL;DR
How can I log a user into a website I don't own remotely?
Disclaimer: I've never done a google chrome extension, but based on the rest of your question, it sounds like it's just working with JavaScript like any other web page, so I'll go ahead and answer it.
In any case, working with cookies in JavaScript can be somewhat of a pain:
https://developer.mozilla.org/en-US/docs/Web/API/document.cookie
http://www.perlscriptsjavascripts.com/js/cookies.html
I'm assuming that your server side already works with and expects cookies, so I won't try to suggest any alternatives. That being the case, your server is what needs to validate the cookie, so, IMHO, might as well set the cookie on the server side. If the server handles it, on the JS side, you simply post the username/password to a server-side page, e.g.
$.post("/user/login",{"Username":"foo","Password":"bar"},callback);
That server-side page validates the username/password and then, if successful, generates the cookie and sends a response back to the JavaScript (e.g. {"IsSuccess":true}). Upon receiving a successful response rather than an error, you just start calling the other web services to retrieve your data assuming you are logged in and build out the page.
Assuming that your web services will return HTTP error codes that help you determine a problem with the session, if you get a 401 error code, you take the user back to the login page. If you get a 403 error code, you let the user know they can't access that data...etc., all depending on your app.
Ultimately, JavaScript doesn't know whether a user is actually logged in, so you have to rely on the server to send you information in a way that is understandable so that you can direct/prompt the user as necessary.
[Edit: 2014-11-21]
You didn't answer my other question: what do you get back? If they don't set the cookie themselves at the login, then you need to get back the session token from the response they send...if they don't send you a session ID, you're SOL. If they do send you an session token/session ID, then you need to know what to name it (e.g. PHP uses something like PHPSESSID as the cookie name, but it can be whatever the coders of that domain decided on). Beyond that, you have to be able to set the cookie for THAT domain name (3rd party cookie). This may have mixed results depending on the user's settings--if they block 3rd party cookies--however, since this is a google extension and not a website, maybe it's able to bypass that kind of restriction. I know that FireFox's developer toolbar is able to manipulate cookies for all domains, so it would be a reasonable assumption you would be able to as well.

Maintaining client side page state on page refresh in angular.js applications

I am building an Single Page app using angular.js and I am facing this issue for which I am not able to find the right answer.
When we do a full page refresh in an angular app, how should we check if the user still has a valid session ?? State Provider or UI router merely routes the url to the requested page, but what if the session of the user has expired ?
One thing that comes to my mind is to use a service and store a Boolean value there once the user logs in and on every page refresh or state change, we check this Boolean and redirect the user to login page, if this value is false. But, if we do a refresh, this Boolean value is reset.
Thought of storing this key value in a cookie or html local storage, but how safe are these values getting stored here. Some one can reset the value of this Boolean to gain access to a page.
Please let me know.
To make a client-side app secure you will need to involve a server of some sort. Storing values in cookies or local storage will not do any good as these can be manipulated by a user (as can everything else on the browser).
Not sure what options you have available to you but I would recommend looking into Nodejs/Expressjs/Passportjs - this is a pretty awesome combo and very good support here on SO.
Once you make progress in this area you will then be in a position to ask a more focused question.
I think you're conflating a few concepts here.
One - is the user authentication to the server. It must be the server, otherwise the concept of a user session in a client-side-only app is useless. This is facilitated (typically) by an authentication cookie. The cookie is a security token given to the user and signed by something secret on the server. The cookie contains things like login name and expiration. The cookie is validated by the server on every request the browser makes.
Two - is the nice user experience maintained in the client-side app. What I mean by that, is that if you didn't check whether the cookie has expired, your ajax calls to the server would (and should) fail with HTTP 401 - Unauthorized. You likely would want to prevent that, and have your app preemptively redirect to a login page, or if applicable, request to refresh the security token.
So what does all of that mean?
Enforce authentication on the server
Create a loginService that checks session expiration from a cookie, or whatever else you use fo your user authentication.
Use resolve parameter of $routeProvider or $stateProvider to have the loginInfo available to controllers. Here's my answer on SO to a question you might find useful.

How to manage server user session within client side single page app

I've been fumbling around with different client side technologies, like AngularJS, EmberJS, even trying to use straight JQuery and figure out how to use ReactJS with it. That aside, my goal is to build a single page app using json in between the client and a Java Jersey 2 jax-rs back end api.
I have two stumbling blocks right now. Some info though..I am deploying my app as a WAR file in Jetty. My back end is java based. I am using only jquery in the client side as of now.
My main stumbling block is how to handle login, logout and session management. With an rest API and using ajax, I have login working, including it setting a cookie. My concern however is with a single page app, there is just the one index page, and if the user closes the browser, then reopens it to the index page while the cookie/session is still good, the user should be logged in, not see the outside (not logged in) page. I am unsure how to handle this, whether it be a jsp page, index.html with some templating library, etc. With JSP I can insert some scriplet code (against my better judgment). In the old days I'd include a header that would check for request.getSession().getAttribute("user") and if it was there..the user was logged in and using scriplet if() code I'd display a logged in header, instead of the non-logged in header. But I am in the belief there has got to be a better way to do this with todays client side JS frameworks.
The other stumbling block is the navigation and dynamic aspects. For example, when I was messing around with angular js, it was easy enough to use Welcome {{name}} and within the scope replace name with a json response value for the logged in user. In my current situation, I am not exactly sure how to best go about displaying dynamic bits like this with pure jquery other than using some sort of $("#elem-id").innerHtml="..." code within the response success method of an ajax call. As well, I am not quite sure how to handle navigation to different pages. My logged in site will have some drop down menus or links that will replace the content area with different varying amounts of content.
So first, what are some ways in a SPA to handle user sessions, in the case of a page reload, or close/crash browser restart.. to ensure the user is still logged in and direct them to the right page? Second, what sort of templating and routing/navigation options exist that don't require me to put a huge ton of code in my one index.jsp page?
Thank you.
If you're having a REST API as the back end, then you must have implemented oAuth as an authentication mechanism. That is, when your user logs in, using a username and a password, you exchange that data with an authentication token. This authentication token is sent your server with each and every API call and your backend validates this token before servicing the request. Clear so far?
What you could do is, when you obtain the access token, you can also obtain the access token expiration time from the server and store that data in your client side app. In localStorage maybe? And when your user closes the browser and reopens again, you can first check whether such access token is available (and not expired) before asking the user to log in. This should solve your first problem.
Secondly, if you're looking for a lightweight routing option, I recommend director.
I am building a similar application. OAuth is not mandatory. You can have normal sessions etc by hitting the jersey login endpoint and setting a session and a cookie "keepme" with the session if user wants to be persistently logged in. You can then have a jersey AuthFilter for example check if either there is a cookie with a valid session or an active session and keep the user logged in.
Your frontend application should have no say over this, just communicate with the server and if it doesn't get unauthorized access (from the AuthFilter) then continues otherwise it displays the login page.

Chrome extension / web app session control

I am creating a chrome extension, rather a chrome webapp. This application just contains the html, js, image and css files. The application connects to a server to fetch data. I chose to do this as it would reduce the amount of files downloaded by the user. Using Backbone.js I have an MVC architecture in my application. Thus the application just sends json.
Now having said this, I need a session management. I plan to use Google authentication as the organization has Google Apps. I need a method that once the user has logged in using google auth the server get the user name every time the application makes a request.
Is it a good idea to add the user name in request header, if possible. Or should I use cookies? Can any one tell me how I could go about using cookies in this case?
This might be a late response but I want to present a more elegant solution to you given that the user has cookies enabled in their browser.
First read my answer on another question.
Now that you can send cross origin xhr from your content scripts all you need to do is store all your authentication and session management at server only. That is right, you just need to display whether the user is logged in or not and a logout button at client based on server response.
Just follow these steps.
At client Whenever user accesses your chrome web app, blindly make XmlHttpRequests to your server without worrying about authentication, just keep a tab on response from server which I describe below.
At server whenever you receive a request check for valid sessions or session cookie. If session is valid send proper response, if not send error, 401 or any other response to communicate to your client that session is not valid. It is better if you send an error code like 401 since then you can put a generic script at client to inform them that they are not logged in.
At Client If response from server is proper, display it, else display login link to your website.
IMPORTANT: Display logout button if user is logged in.
Check out my implementation of this in my extension
For help using Google authentication in your app take a look at Google's OAuth tutorial which comes with all you need (took me no time to set it up using this).
As for session management. The implementation of OAuth used by Google stores the tokens in localStorage. Also, as briefly mentioned in the extensions overview we are expected to use localStorage to store data. Thus, I suggest you store the users name here as it will be accessible throughout the app's lifetime (until it is uninstalled). However, you may need to manage the name stored here and consider what should happen when users log in and out. That said; I'm not sure if sessionStorage would be a better option as I've never used it before, let alone in an extension.
Note
localStorage and its counterparts only store strings so I suggest using a wrapper which uses JSON to parse and stringify to get and set your values respectively.

Categories

Resources