Why should I store JWT token in cookie?
I understand that this approach prevent Cross-Site Scripting (XSS) attacks and it is more secure than local storage. But what if user can simply look at JWT in dev tools and see the token, is that a real problem?
Fundamentally, if you want to store data on the client-side somewhere, the client will be able to see it themselves if they're determined enough. There's no way to store data on a client's machine without the client being able to use their machine to find and look at it.
If you store the JWT in an HttpOnly cookie, it'll be more secure than other methods because then it won't be possible for malicious scripts to scrape the credentials. Like you've noticed, the client will still be able to read it manually - but that's usually considered OK. The alternative, if no data can be stored on the client, is to require that the client supply their credentials with every request - but without storage, that'd be cumbersome to the point of making a system unusable. It's also a odd attack vector for someone to manually take a JWT from a browser that isn't theirs, though it's not impossible.
So - it's a potential small problem in unusual circumstances (which can be mitigated to some extent by performing more verification methods on the server, like checking the originating network and fingerprinting the browser), but the alternative of not being able to store anything on the client at all may be worse.
Depending on what you're storing on the JWT, you're free to encrypt it so that only your server can decode it. That way, even if someone with access to the client machine tries to mess with it, all they'll be able to do is to copy it verbatim or delete it; they won't be able to modify it.
Related
I have looked through quite a few tutorials (e.g. this, this, and this) on user authentication in a full-stack Django + React web app. All of them simply send username and password received from the user to the backend using a POST request. It seems to me that, if the user leaves the computer unattended for a minute, anyone can grab his password from the request headers in network tools in the browser. Is this a valid concern that must be taken care of? If so, how should these examples be modified? A tutorial / example of the correct approach would be appreciated.
It seems to me that, if the user leaves the computer unattended for a minute, anyone can grab his password from the request headers in network tools in the browser
If the user leaves the computer unattended then what you are describing will probably be the least of his/her worries.
Authentication is a complex topic, if you really do not want to use existing libraries that handle this for you then you will need to spend quite some time to get things right (knowing that even then, risk 0 does not exist), the most basic thing being to never store plain text credentials on your DB and using https to transmit them over an encrypted connection. You can then start thinking about JWTs, avoiding local storage, CSRF and securing cookies, refresh tokens, etc.
You cannot do much however about cases like the one you describe of people giving away access to their computers or sharing their passwords with others except reminding them they should never do such a thing.
On a side note, if the user didn't have the network monitoring tool open when making the request to your website, opening it afterwards will not show the previously submitted plain text credentials (there are workarounds to this however)
My Setup
I am using React and Django as frontend & backend. For authorization purposes I chose Django-rest-knox, which works via tokens stored in a database.
My Problem
Now if an attacker gets a hold of the token (stored in local storage on the client side after a login), he can do anything that the user is able to. There is some expiration on the token and the ability to destroy all tokens of the user by the user himself. But I'd like to be on the safer side.
My Solution
My idea is to map all tokens to the IP address (of the user) that was used to login. That way the token would only be usable on the machine that was used to login. That token-to-IP-address relation would be checked on the backend.
My Questions
Is the idea feasible at all or is there anything in the nature of those IP addresses that breaks my intent?
What is the best way to get the client IP-address?
Do you think that is a secure approach?
Thanks for the help!
The idea is feasible but not efficient. The main problem is, not everyone using static ip address and this will cause you a big feedback by your users because everytime some user's ip address change(via modem reset, power cut, provider problems etc.) he/she/it will have to be authenticated again.
You use 'HTTP_X_FORWARDED_FOR' meta for almost all backend framework as well as django. you can check this link. How do I get user IP address in django?
This idea may come with security but i ll give you a better one that i am currently using on my own application.
My solution: Refresh tokens. With refresh tokens, every time an access token expire(avarage 15 min ideal) user will request a new access token via his/her/its refresh token. With this way even an attacker get user's access token, he/she/it will be only available for 15 minutes(you can make 5-10-15-... mins as well)
We have a system that connects our user to 2-3 third party applications. So, we usually store the tokens to be used for these applications for the user in the client side. When we make an API call to our server (our server is maintained by us), we also send the tokens to the backend, where it will be used to make API calls to these applications. Now, We're not using a Database, so We cannot store these tokens on the server side and hold a session token.
What are the best possible ways to hold the token on the client side? Is it safe to hold them as they are in the Cookies?
Keeping them open did not look fairly safe to us, so we're planing to add AES encryption to them, and whenever they are sent to the server, they are decrypted and used for API calls.
Is this the best approach we can continue while keeping our tokens secure? Or is there another better way to approach this issue?
If the client does not need to use that token and is only expected to forward it to the server for authentication with the 3rd party I think it is definitely a good idea to encrypt it. This way, an eventually compromised encrypted token cannot be used to make requests to the 3rd party.
Cookies should be a safe place to store these tokens as long as you make sure you enable the Secure and HttpOnly attributes on them (more about restricting access to cookies). In a nutshell, you prevent cookies from traveling through unencrypted channels (reducing the risk to suffer man-in-the-middle attacks) and from being accessed from the Javascript (which prevents your cookie from being accessible by an XSS attack on your client).
Background
I am looking at the OAuth 2.0 Implicit Grant flow where a user is redirected to an authentication service and a JWT token is sent back a Single Page Application(SPA). The token is stored in a cookie or in local storage and, in the examples i have seen, the application will hide/show certain pages based on whether it can find the token in storage.
Issue
The problem is that in all the examples (official from service providers), i was able to manually add any random but properly formed token to the browser's local storage and got access to the 'secured' pages.
It was explained to me that you cannot validate the token in the SPA because that would require exposing the client secret and that you should validate the token on the API server. This means that you can 'hide' the pages but it is really easy to see them if someone wants to. Having said that you are unlikely to cause any real damage because any data retrieval or actions would need to go through the API server and the token should be validated there.
This is not really a vulnerability but the documentation and examples I have seen do not explicitly cover this nuance and i think that it could lead naive programmers (like myself) to think that some pages are completely secure when it is not strictly the case.
Question
It would be really appreciated if, someone who is better informed than i am, confirm that this is indeed how SPA authentication supposed to work?
I am far from an expert, but I have played a bit in this space. My impression is that you are correct, any showing/hiding of functionality based solely on the presence of a token is easily spoofed. Your SPA could, of course, get into verifying an access token.
But that may just make it a little more challenging to spoof. If someone wants to fake the client into thinking it has a valid token, they can likely manipulate the client-side JS to do that. Unfortunately that's the nature of client-side JS. Much of the code can be manipulated in the browser.
Thus far this is speaking to protecting the user from seeing a UI/UX. Most applications are only beneficial when they have data to populate their UI. That's where the API access token strategy is still sound. The server will verify the token and not give the client any data without it.
So while it's unfortunate that JS can be easily spoofed and manipulated to show things the developer would rather not make visible, this isn't typically a deal-breaker. If you have some awesome UI feature that doesn't need data, and you need to secure access to that UI itself, this model may not be the greatest.
I have an angularjs app that is on a separate domain than my backend, and the users from my backend all have roles and permissions that allow them access to various areas and elements of my frontend.
Before, I was just storing to a cookie and checking as I needed through the use of angular services and whatnot, cool.
Now the permissions datum have reached the point where they are too big to store in a cookie in the browser. And I'm avoiding Localstorage for fear of user tampering.
The Question:
How do I store the users sensitive data (or anything sensitive, really) that are too big for cookies on the client side in a manner that is safe and doesn't require API calls all the time to get?
I don't want to have to phone home every page change to get this data direct from the server when I need it, because I feel this would be really detrimental to the speed and flow of the site, not to mention the frequency at which this would need to happen would be ridiculous for my app.
Keep in mind that I do proper permission checking on the backend before carrying out any actions, but I'm more concerned about users tampering with their permissions to show certain elements that were removed on the frontside before.
What would be your solution or your advice on this?
If it ends up on the user's computer, regardless of whether it's in a cookie, in local storage, in the URL, in the browser's cache, or anywhere else on the user's computer, assume that the user can see it and mess with it. (You could encrypt it, but if your client-side logic knows how to decrypt it, you're back to step one.)
The best that you can do is exactly what you've described - be sure that the server only carries out authorized actions, and never trusts what the user tells it.