Best practice for handling secondary page requests - facebook

When building a Facebook tab application the first page receives the signed request, my question is what is the best practice to handle the secondary requests. You could save the related information in a cookie to have it on the secondary requests but that seems a little unsecured to me.
I am just curious what is the recommend way to handle this basic situation.

The signed request is just an intermediate step to getting the access_token and userid.
I put the access token into Session, and I also encrypt it and save it in a cookie. Facebook app development has taught me to go belt-and-suspenders when it comes to authentication.

Related

JWT default GET action limitation?

I've successfully used cookies before and I'd like to begin using JWT. My biggest question is how to pass your token to a website during the initial GET operation, for example when a user types your domain into their address bar or clicks on a link from some other website like google.
When using cookies for example, if you type stackoverflow.com into your web browser, the persistent cookie is sent to the website which seamlessly allows your own stackoverflow session to be automatically authorized.
I am aware that I can programatically pass my JWT token via a javascript GET through the HTTP headers but how do you pass the token when a visitor types in your URL into their web browser?
Possible solution #1
My thoughts have been to have javascript code check if 'authorized'. If not, check for a JWT token in local storage. If found, redirect to the same address. The problem of course would be that there is no way to pass the token during a redirect.
Possible solution #2
Similar to above but not issuing a redirect, I would update the current page to reflect the 'authorized' state.
Possible solution #3
Use a permanent cookie containing the JWT token. I am thinking that this 3rd option would be the best. If I did this, there would be no need to pass the JWT via an HTTP header.
I've thought about this for a few days, read up on JWT and here are my conclusions for avoiding JWT in my particular case:
No easy way to authorize a user who opens their browser and types in your website. With cookies, your server immediately knows how to respond to this headerless GET request.
No way to easily change the JWT token signature. All users are immediately affected by such a change, essentially forcing everyone to authenticate again.
No way to easily invalidate a specific JWT token. The best you can do is to maintain and check a banned signature list on the server. This of course would require a centralized or distributed server method almost identical to a cookie session management system. This would force a coupling between the token and the server, no longer stateless as intended by JWT.
SUMMARY
Cookie management requires more server infrastructure but you have much greater session control. State is seamless (in the case of #1 above). You can instantly invalidate state. For example, the user can log out (deleting the session at the server level) or the session can be instantly banned by an administrator by simply deleting the session.
I also see the benefits to JWS:
no need to hit the db or cache system when authorizing.
simple authorization between multiple servers having the secret key.
simple authorization, no session management programming and no db session state storage required.
...but the drawbacks stated previously are too great for my particular needs.

oAuth Silent authentication vs refresh token and http only cookie

Somehow implementing stateless authentication always brings me headaches.
This time it concerns silent auth vs refresh tokens.
Using refresh tokens seems discouraged, however there are certain arguments I don't really get.
If you use an http only cookie to store your refresh token, what exactly is the danger?
Attackers cannot get access the cookie with Javascript and if you use SSL (which you should), I really don't understand the problem.
The resources I read always say "you should not store sensitive data in the client". Seems like an automatic, but that is implicitly impossible if you want to eliminate the need for server session state. Neither do I really understand why, since no resource ever explains how it would be cracked (and I really wonder if anybody really knows).
The reason why I have this question is because using a refresh token offers me more than just authentication.
If a user for example loses his / her device, removing the refresh token will just invalidate all access tokens over all devices (not only browser), which seems like something a user wants to do.
After all, it makes sense that when you lose a device, you need to take action to protect your data.
So the argument "if the attacker gets access to the refresh token, he can infinitely refresh your token" sounds like another argument I don't get. The attacker should not get the refresh token. How would he ever get it? It's the same as saying "if the attacker gets hold of the code of your bank card, he has infinite access to you money". Well if you lose your bank card, you call card stop; likewise if you lose your refresh token, you would delete it to invalidate all access tokens. So how is this an argument?
Can you clarify why I cannot just store my refresh token in an http-only cookie, and how a silent authentication flow improves on this?
Edit:
Note that I read a few other articles that advise to store jwt in the browser by sending the encrypted jwt signature in an http-only cookie. These articles received a lot of upvotes, so that is suddenly okay. It makes zero sense to me.
Edit on comment:
The architecture is very simple:
React / Redux SPA with REST api in the backend
Need for social login through Google, LinkedIn, Github
Need to refresh the token without needed user interaction
Access my own api resources (preferably with jwt)
Ability to revoke refresh token
I don't know why it seems complex (lol).
Refresh tokens are widely used in:
Server side web apps, where they are stored in an HTTP only cookie, as you suggest
Desktop and mobile apps, where they can also be stored in OS secure storage
Refresh tokens should not be infinitely renewable and often represent the user session time - eg:
Refresh token / User session lifetime = 12 hours
Access token / API message credential lifetime = 60 mins
The concern for SPAs in the above article is that there is no real secure storage in the browser - though you are not intending to use browser storage - so no problems there.
One risk is that users can maybe get the secure cookie and replay it to an API via browser developer tools:
To mitigate this it is of course important to ensure that APIs have well engineered authorization - and that what the user can do with a token matches what they can do in the UI.
Another risk is CSRF where a malicious app in another browser tab sends the same cookie to your back end. So you'll need to protect against this.
Note that SPAs have their own token renewal solution based on Authorization Server cookies - I would prefer that option if using an SPA, rather than issuing your own cookie.

JWT authntication and its alternatives to reach RESTfulness of web application back-end

In my company, we are building a web application and most actual problem is to pick an authentication solution. Im thinking about 3 of most used way to maintain
session with authenticated user: stateless JWT (all session data holds JWT token in its payload), stateful JWT (token is only used to validate requests and in its payload it has session ID to session data record at server) and traditional session ID stored in cookie, which requires additional check for matching id in server.
Because i want to build this app RESTful, only first way seems right to me. This way a server does not need to hold any state.
My first question is: Is it ok, to store all session data in token payload (of course, those data are not that big and they are not supposed to be a secret, hence no security is needed).
Also, im going to implement logout logic as well and i know, that blacklisting tokens, which is in my case, i think, best solution ruines statelessness too.
Do you know of any other way to implement logout logic which IMMEDIATELY invalidates JWT token ?
Thank you for your answers.
EDIT:
In case of invalidation, im thinking about sending an updated token with either a flag which tells "im invalidated token" or with expired expire date. This solution but works only for "good boy" users. Hackers will keep previous and still valid token.
Logout with JWT works by deleting the token client-side. Like this.
function removeToken() {
localStorage.removeItem("jwt-token");
}
Without the token, the user is logged out. So I think it is immediate?

Possible approach to secure a Rest API endpoints using Facebook OAuth

I've been reading a lot about the topic but all I find are obsolete or partial answers, which don't really help me that much and actually just confused me more.
I'm writing a Rest API (Node+Express+MongoDB) that is accessed by a web app (hosted on the same domain than the API) and an Android app.
I want the API to be accessed only by my applications and only by authorized users.
I also want the users to be able to signup and login only using their Facebook account, and I need to be able to access some basic info like name, profile pic and email.
A possible scenario that I have in mind is:
The user logs-in on the web app using Facebook, the app is granted
permission to access the user Facebook information and receives an
access token.
The web app asks the API to confirm that this user
is actually registered on our system, sending the email and the
token received by Facebook.
The API verifies that the user
exists, it stores into the DB (or Redis) the username, the token and
a timestamp and then goes back to the client app.
Each time the
client app hits one of the API endpoint, it will have to provide the
username and the token, other than other info.
The API each time
verifies that the provided pair username/token matches the most
recent pair username/token stored into the DB (using the timestamp
to order), and that no more than 1 hour has passed since we stored
these info (again using the timestamp). If that's the case, the API
will process the request, otherwise will issue a 401 Unauthorized
response.
Does this make sense?
Does this approach have any macroscopic security hole that I'm missing?
One problem I see using MongoDB to store these info is that the collection will quickly become bloated with old tokens.
In this sense I think it would be best to use Redis with an expire policy of 1 hour so that old info will be automatically removed by Redis.
I think the better solution would be this:
Login via Facebook
Pass the Facebook AccessToken to the server (over SSL for the
android app, and for the web app just have it redirect to an API endpoint
after FB login)
Check the fb_access_token given, make sure its valid. Get user_id,email and cross-reference this with existing users to
see if its a new or old one.
Now, create a random, separate api_access_token that you give back to the webapp and android app. If you need Facebook for
anything other than login, store that fb_access_token and in your
DB associate it with the new api_access_token and your user_id.
For every call hereafter, send api_access_token to authenticate it. If you need the fb_access_token for getting more info, you can
do so by retrieving it from the DB.
In summary: Whenever you can, avoid passing the fb_access_token. If the api_access_token is compromised, you have more control to see who the attacker is, what they're doing etc than if they were to get ahold of the fb_access_token. You also have more control over settings an expiration date, extending fb_access_tokens, etc
Just make sure whenever you pass a access_token of any sort via HTTP, use SSL.
I know I'm late to the party, but I'd like to add a visual representation of this process as I'm dealing with this problem right now (specifically in dealing with the communication between the mobile app and the web api by securing it with a 3rd party provider like facebook).
For simplicity, I haven't included error checks, this is mostly just to outline a reasonable approach. Also for simplicity, I haven't included Tommy's suggestion to only pass your own custom api token once the authorization flow is over, although I agree that this is probably a good approach.
Please feel free to criticize this approach though, and I'll update as necessary.
Also, in this scenario, "My App" refers to a mobile application.

Questions regarding authentication workflow with REST, and Backbone

I am currently working on a website built with Backbone.js. The site has a RESTful API built in Symfony with FOSRestBundle. Developing was going fine, until I stumbled in to some user-related tickets.
From what I understand, the best way to handle this type of problem is with a token based system, where the user gets an access token after an approved login. I will describe my current perception of the workflow, and ask questions along the way. More importantly, please correct me if I have misunderstood.
First, the user the accesses the login form, then the user types in credentials, and an AJAX request is send to the server. From what I understand this should all be handled with SSL, but with Backbonejs, you can't simply say that the login page should be accessed with HTTPS, as Backbone is a one-page framework. So will this force me to use HTTPS through out the application?
In the next step, the REST server validates the credentials, and they are approved, then the REST server sends an access token to the client. Is this token saved (on the client-side) in local storage or a cookie?
Also is the login stored at the server, so that the REST server can log the user out after a certain amount of time?
Now, the client sends this access token along with other request, so that the server can identify the client, and approve the request or not. So the access token is also stored on the REST server?
Lastly is this what the smart people call "oauth", or does it relate to it?
Thank you.
Let's take your questions one at a time.
From what I understand this should all be handled with SSL, but with Backbonejs, you can't
simply say that the login page should be accessed with HTTPS, as Backbone is a one-page
framework. So will this force me to use HTTPS through out the application?
Ok, there's a lot to unpack there. Let's start with SSL/HTTPS. HTTPS is a protocol; in other words it defines how you send packets to/from the server. It has nothing whatsoever to do with whether your application is single or multi-page; either type of site can use either HTTP or HTTPS.
Now, that being said, sending login info (or anything else containing passwords) over HTTP is a very bad idea, because it makes it very easy for "bad people" to steal your users' passwords. Thus, whether you're doing a single-page or a multi-page app, you should always use HTTPS when you are sending login info. Since it's a pain to have to support both HTTP and HTTPS, and since other, non-login data can be sensitive too, many people choose to just do all of their requests through HTTPS (but you don't have to).
So, to answer your actual question, Backbone isn't forcing you to use HTTPS for your login at all; protecting your users' passwords is forcing you.
In the next step, the REST server validates the credentials, and they are approved, then
the REST server sends an access token to the client. Is this token saved (on the
client-side) in local storage or a cookie?
While any given framework might do it differently, the vast majority use cookies to save the token locally. For a variety of reasons, they're the best tool for that sort of thing.
Also is the login stored at the server, so that the REST server can log the user out
after a certain amount of time?
You've got the basic right idea, but the server doesn't exactly store the login ... it's more like the server logs the user in and creates a "session". It gives that session an ID, and then whenever the user makes a new request that session ID comes with the request (because that's how cookies work). The server is then able to say "oh this is Bob's session" and serve the appropriate content for Bob.
Now, the client sends this access token along with other request, so that the server can
identify the client, and approve the request or not. So the access token is also stored
on the REST server?
If you're running two separate servers they're not going to magically communicate; you have to make them talk to each other. For this reason your life will be easier if you can just have one (probably REST-ful) server for your whole app. If you can't, then your REST server is going to have to ask your other server "hey tell me about session SESSION ID" every time it gets a request.
Lastly is this what the smart people call "oauth", or does it relate to it?
Kind of, sort of, not really. OAuth is an authorization standard, so it's sort of tangentially related, but unless your login system involves a whole separate server you have no reason to use it. You could use OAuth to solve your "two servers, one REST-ful one not" problem, but that would probably be overkill (and regardless it's outside the scope of what I can explain in this one Stack Overflow post).
Hope that helps.