I am currently working on an application (React frontend, node.js server and api) and am using JWT. I am having a hard time wrapping my head around the process of storing and sending the token using HTTP "Authorization" header.
Tutorials online seem to do a great job of showing me how to send this token once it is stored somewhere, but how does it actually get stored there in the first place is where my confusion arises.
I have two ways of thinking of approaching this:
The token is generated on login, then returned to the frontend, then stored in localstorage. Then, when a request is made, the HTTP "Authorization" header is set by pulling the token from local storage.
The token is generated on login, then returned to the frontend. It is somehow stored already in the "Authorization" HTTP header (Does this even make sense?). Then when a request is made, the header is already set.
Do option 1 but use a cookie (or session-cookie?) (don't know how to do this approach).
I would like to know:
A. Which of the 3 (if any) is the right approach
B. If approach 2 is the correct way, how do you actually STORE this header once you get the token?
C. If NOT approach 2, where is the preferred place to store this token (localstorage, cookie, etc.)?
I have tried approach 1, it works but seems unsafe and not best practice.
I have NOT tried approach 2, because I have no idea how to do it, and couldn't find anything online.
I have NOT tried approach 3, but I assume it could work in a similar fashion to 1?
First, your instincts are right; you should not use local storage for a secure token because local storage persists even when the browser is completely closed.
The most straightforward way to store your token is to just keep it in memory. A global variable in Javascript, or even attaching it to window, works fine. Then with every XHR call you insert Bearer [Token] into the Authorization header yourself. There are a bajillion npm packages to help with XHR requests but virtually all of them should let you insert this header. If you haven't already you should write a single wrapper function to encapsulate all your API calls and insert the token at this point.
The drawback with this is that the token won't persist across different pages on the same domain or across browser tabs, nor will it work with non-XHR requests like img src="https://secure_api_route_that_returns_an_image.jpg", as there's no way to programmatically inject custom headers in those cases. I don't know if any of that is a problem for you. Usually with React SPAs you aren't going to be bouncing around truly different "pages" on the same domain, but you may well want to be securely sourcing images with what are technically API routes, or keeping the session alive across browser tabs; I'm not sure what your requirements are.
Anyway if you do need any of that functionality, you have to use a "session cookie". (Technically you could use session storage if you only need to preserve the token across page navigation but it doesn't work across tabs, so I find it to be pretty useless over just storing in-memory). This just means a cookie with no expiration date, which is automatically purged when all browser tabs have been closed. You must enforce earlier expiration on the backend rather than through the cookie header.
I use .NET backends rather than Node, so I can't give you specific code, but basically you need to return this header in a successful login API response:
set-cookie: myCookie={jwt}; Path=/; Secure; HttpOnly; SameSite=Strict;
Don't omit Secure, HttpOnly or SameSite=Strict except possibly in development, as otherwise you'll be open to common vulnerabilities. (This is one of the disadvantages of the cookie approach; it's easier to implement wrongly and open up a vulnerability). This assumes your frontend and backend are hosted on the same domain. It becomes a little more complicated if not (CORS, etc.) but it can be done in that case too with a little more work.
On the authentication side, you will just need to look for this cookie in every API other than login. If everything is working right the browser will automatically send something like this with every request to your domain, on any tab, for as long as any browser tab remains open:
cookie: myCookie={jwt}
Again not a Node.js guy but I'm reasonably sure most any library that can verify a token via the Authorization header will support cookie authentication too; you'll need to check the documentation or please post a new question if you can't figure it out.
On the frontend side, besides the cross-tab support, the browser takes care of saving the cookie and sending it when it should, so it's conceptually close to what you're looking for in option 2.
So as with most things there's no single right way (though there is definitely one wrong way - localstorage). For what it's worth, a few years ago I surveyed several commercial sites to see how they handled this, and I found most used the session cookie. This included U.S. banks and financial institutions, which have to follow some of the strictest security standards that exist. While cookies sometimes get a bad rap, when used correctly they are still industry standard for secure authentication. But storing the token in plain old Javascript memory is fine if you don't want to deal with cookies or need the features cookies give you.
Related
So I have 2 domains: http://domain1.com and http://domain2.com
domain1.com has a bunch of cookies for the user stored on it.
I want to access all of those cookies but from domain2.com (to keep them synchronized).
Is this possible in JQuery? I was thinking of making a Cookie php file and somehow connect to that file from domain2.php to pull all of the data in.
Thanks for any help
NOTE: These are NOT sub-domains but 2 completely different domains I Control
In a strict sense? No. It isn't. In a more loose sense, yes it is.
If you're storing all of your data in cookies, you're actually storing the data in the browser, which means that jQuery, Prototype, Mootools... can't help you because of browser security (unless you can turn their browser into a server (might work with a Firefox extension (I swear, FF could be an OS if needs be...), but that would be gratuitous)).
I said that in a loose sense it is possible because PHP lets you do two very important things. First, it lets you store your session in a database, and second it lets you assign the session ID directly. It is possible, then, to have two servers point to the same DB and then share SESSION data by switching the user's session ID.
no. this would violate the security model on which browser cookies operate.
to work around this you can implement an iframe (perhaps invisible to the user) on domain1.com which is served from domain2.com and pass data between the two sites with JS.
I would look at a server-side solution, creating a common database that all sites can access. When the user logs in, generate a time-sensitive, IP-keyed token that can be passed from site to site either in GET or POST. Then, validate each request on token, IP, and time. The combination of the three will resolve most security concerns.
or you can look at this SO question for ideas its in .Net though Store cookie for other site
The Question(s) =]
Based on my research, it seems like storing web tokens in local storage is the preferred method over using cookies in order to prevent CSRF attacks (I am aware that local storage is susceptible to XSS attacks though these seem easier to prevent than CSRF). This being said, I have been unable to locate any relavant guides on utilizing local storage for this means...
I am looking for some help on understanding how the following works...
What is the preferred method/workflow to pass a server-signed token to the browser's local storage.
Once the browser stores the token, how do I then use that stored token.
Do I need to stop the default submission of things like forms via JS and then send AJAX requests with the authorization: Bearer <token> header with every request?
When a user clicks a link to a resource owned by that user, how do I send that token to server to grant access to the protected resource?
The Tools
Front-end
HTML5 (Compiled from Handlebars)
JS
CSS (Compiled from SASS)
Back-end
nodeJS (using Express)
NOTE: I hope to edit this post with code samples in the future (once I get the hang of it lol), to help other confused people like myself in the future
Preferred method is to return token with successful response from /users/login request (wherever you prefer, header or body). Then you put it into local storage.
Most important thing here, is that JWT can NOT be used without HTTPS. Otherwise you will end up passing credentials unprotected.
After acquiring of token, you should MANUALLY add it as a header to each request. Use some js ajax wrapper to simplify this task.
There is no way as far as I know to send custom headers with <a href=""> elements. So I ended up passing additional token (some hash, not JWT) along with link <a href="/some_protectded_page?token=...">. But this is not optimal. If you render pages on server side, it is better to use sessions.
I am starting to implement a JWT based Single Sign On system (for several single page apps under the same domain, so something like app1.mydomain.com, app2.mydomain.com, auth.mydomain.com) using the mechanisms described in this article from Stormpath.
In order to protect my signed JWT token from XSS attacks, I want to store the token in a secure (HTTPS only) and HTTP-only cookie. The SPA itself will get the user info from the response body.
My main question is how can we implement a "log out" feature in JavaScript, since the cookie is, by design, not accessible from the JS code?
I am guessing that I will have to make a server call that will expire the cookie. Is there a pure-client-side way to do it though?
The best way would be to do the cleanup server-side as user JEY already suggested.
Additionally, I wanted to extend the bit on the possibilities so this did not fit a comment.
When dealing with browser-based applications selecting the token storage is almost a pick your poison game. If you go with a secure HTTP-only cookie you don't have to worry about XSS vulnerabilities leading to token disclosure. However, you'll still have to ensure you're not vulnerable to XSS by an whole set of another reasons.
This means you don't save any actual work, you just get that fuzzy feeling that if you do get compromised by XSS at least the token is safe.
On the other hand, by going with a cookie, CSRF is now something that needs to be on your radar and here is where things may get funny, some trivial methods of preventing CSRF like double-submit cookies can be implemented in such ways that they are virtually useless in the presence of exploitable XSS vulnerabilities in child domains for example.
I'm not saying that storing tokens in cookies is plain wrong, it isn't, likewise storing them in Web storage is also acceptable. In both cases you need to understand the consequences of your choice and the possibilities each one brings.
In this case, Web storage would simplify your logout scenario from a client-side perspective so you need to ask yourself which set of pros and cons are better suited for your scenario.
Given you mentioned multiple applications in child domains one thing to be aware of is the following:
With token-based auth, you are given the choice of where to store the JWT. Commonly, the JWT is placed in the browsers local storage and this works well for most use cases. There are some issues with storing JWTs in local storage to be aware of. Unlike cookies, local storage is sandboxed to a specific domain and its data cannot be accessed by any other domain including sub-domains.
(emphasis is mine, source: Where to Store Tokens? section of Cookies vs Tokens: The Definitive Guide)
(Disclosure: I'm an Auth0 engineer.)
Im developing a web application which requires cookie to be set httpOnly = false.
Since, I find no other way to pass authentication cookies(for checking whether user has logged in successfully) from server side to be accessible via Javascript in my front end. This cookie is then used to send an AJAX request to my server side(added to the header). (Please do correct me if Im wrong and suggest me any other way)
My question:
How insecure is httpOnly = false? Is it safe enough with just forcing it to use cookieSecureOption = true so that it will always be send via HTTPS.
How can I protect it from XSS attack?
A "non-HttpOnly cookie" isn't a vulnerability in itself.
An "HttpOnly cookie" mitigates the risk of an XSS attack. That is, any attacker injected scripts into your website will not be able to grab the value of this cookie, thus protecting the session.
If your application requires the use of the cookie value to add as a header, then you cannot mark this cookie as "HttpOnly". You can change the request handler to look for the value in the cookie rather than in the header (so you can set the flag), however this may put your site at risk of CSRF. The most secure approach is for your handler to check authorisation via a "HttpOnly" cookie, and to use another token value in a header ("non-HttpOnly") to check for CSRF. If these values are different, e.g. in the encrypted token pattern or the synchronizer token pattern, then there isn't much value in attacker in only retrieving the one value via XSS because they can't use it to authorise requests. Note that any XSS vulnerability is usually a bigger problem than a CSRF vulnerability, because the attacker could always use their XSS attack in order to submit requests directly from your site, however it is a much harder attack to accomplish. At least with "HttpOnly" they cannot grab the auth cookies from your site in order to remotely login.
The other cookie flag you mentioned is the secure flag. This will limit the cookie scope to https connections only, and is recommended if you are using https (which is also recommended). This does not affect whether JavaScript can access the value though.
If you do use a "non-HttpOnly cookie" then you can still mitigate the threat of XSS as follows.
Move all script code into external js files and set a Content Security Policy to prevent any inline scripts from executing.
Make sure you are correctly encoding all user input when output (e.g. < becomes < in HTML) and run a web security scanner against your application.
If you do not have HTTPOnly flagged, your users are still more vulnerable to XSS than they otherwise would be, as the cookie can still be accessed from JavaScript. From your description, you should not need access to the variable from JavaScript, simply access the cookie from the server side (which is still possible with HTTPOnly flagged, cookies are sent with every request including AJAX calls) to retrieve authentication information. The Secure flag and HTTPOnly flag defend against completely different attacks.
There is a hybrid way of doing this. I say hybrid because it involves half of what your doing and a mix of what bksi mentioned in a comment.
Since I do not know your full scenario this answer assumes you are just looking for a way to authenticate the user before allowing them to make changes or start a process server side; login, viewing an account page, and so on. You should never rely solely on httpOnly = false I would recommend using it with what is below.
A Solid Solution
Set a normal cookie when a user logs in successfully, this does not need to be sent over HTTPS although it would be nice. This cookie should be a randomly generated token for their session. I usually hash (md5 encrypt in PHP) their user id (assuming you use a database) and a time stamp of when they logged in. This insures the token is unique.
Now that you have a token saved on their local machine as a cookie also make sure to save this token in a PHP session which is server side. Now any time they visit a page or an AJAX request is sent you can compare the local cookie to the PHP session value server side. This is the fastest way you can authenticate a user interacting with your server. If the values match they are legitimate.
Now this is not entirely secure. The local cookie can always be edited which is something we usually don't care to much about because this will only harm the user by invalidating their session. On the flip side a crafty hacker could alter the PHP sessions and that could invalidate other users because their session was erased or hijacked. A hacker would have to get a legitimate session token and make a cookie to match.
The Better Solution(s)
1) On the server side you could use a database instead of PHP sessions. The process remains the same but now you need to do a bit more work of keeping the sessions table in your database up to date. Usually this is done by saving the token with a time stamp and updating this time stamp every time the token is checked. If the token is checked and the last time stamp is really old (you decide how long that is) you can un-authenticate the user by destroying their local cookie and having them sign in again. This is more resource intensive though and can slow down sites with large traffic loads.
2) Use a form of double authentication. This would be using PHP session 90% of the time for simple things but when an extremely important process comes up, say updating personal information or providing credit card information, check with the database as well. This would require two different cookies to be saved on the users machine. One if for checking PHP session for authentication and the second is for checking the database. This scenario would be really hard for a hacker to break through to the more important things because they would need to figure out both tokens and the database one is not easy to steal.
Final Thoughts
This is a fairly secure answer but you should still implement extra security precautions. It seems you are misunderstanding how cookies work in general; your recent comment sounds like your using cookies and ajax backwards but maybe I'm misunderstanding. Here is how I do it:
[User]-> Tries logging in to website with a login form
[Server]-> Checks this information against the database Pass, log 'em in.
[Server]-> Generate and set a random token as a cookie
I use PHP here and usually store this cookie with a name like sessionToken. This cookie immediately exists now on the users computer and we, the server, always have access to it server side; we can call it up any time. This is not really secure though because people could copy the cookie without the person knowing/ steal it as we send it to them. I'll deal with that in a minute.
[Server]-> Create a PHP session (session id: abc123) server side that has this same token.
This is step one in security. PHP sessions are not as easy to steal or hack. So even if someone steals our users token cookie when they try to use it on their computer it will fail. Here is a vaild user:
[User]-> (PHP session id: abc123) Tries to access secured page or content. PHP session is called up and is checked against the cookie token. If they equal each other this attempt passes.
Here the user has a session on the server they don't know about that recognizes who they are and can be accessed only by the server; usually. It is here where your AJAX request come into play. Every time the user tries to do something that you want to see if they are even allowed to do, send a request via AJAX to a PHP script that authenticates the user. All it does is send back PASS or FAIL. Then you can use AJAX or Javascript to do whatever you need. Here is a hacker exmaple:
[Hacker]-> Steals a cookie from a user over a cafe's wifi.
[Hacker]-> Tries to access the website you are on with it.
[Server]-> (PHP session id: ???) Doesn't have one, destroy the cookie and ask this user (the hacker) to login again.
This is as much information and help I can give. Your latest comments are starting to sound like new questions you should post on Stackoverflow.
We're developing a system using AngularJS and PHP. I have some concerns about the security on the matter of authentication. I wrote a basic authentication based upon multiple different examples around the web (I only started learning Angular), which uses a database via REST API calls. On some routes it checks if the user information exists before it creates a promise, but I have a few questions:
Can session information be stored in$window.sessionStorage or $cookieStorage without the client being able to modify these values or should I keep them server-side with PHP $_SESSION and fetch them from there, never storing them anywhere in JS? Session information can contain uid, role, email and name
Can I store a value, like let's say $rootScope.role or $scope.role without the client being able to modify this value? Let's say for example we have multiple levels of user accounts where super-admin is the highest. If I create a route with a resolve which would check the $rootScope.rolelevel, can a novice go change the $rootScope.role value to super-admin gaining access to restricted backend sections?
Will I have to implement a GET /session check on every route to which gets $_SESSION data to actually make sure this data stays untouched?
Or am I just paranoid?
You're not paranoid, any client-side authentication should be questioned. When it comes to security, you can't assume that the client is forbidden or unable to do anything on their own device.
Security related functions must stay on the backend, an environment you set up and control.
can a novice go change the $rootScope.role value to super-admin gaining access to restricted backend sections?
Asking questions like "can a novice..." are futile in my opinion. Do you only want security against novice malicious users? If your "restricted backend sections" can be accessed by modifying the frontend, you're doing something wrong.
Great question! Front end security requires the cooperation of the browser and your server.
Javascript is an untrusted environment, so you can’t reliably enforce any authorization there (i.e. you can’t use properties on $scope to prevent a user from doing something). Your server needs to enforce these rules by ensuring that every API request is properly authenticated and authorized.
API requests are typically authenticated with a cookie. The cookie typically contains a session identifier, which points to a row in your database which contains the authorization information (i.e. what the user is allowed to access). The user can get this cookie by logging in (presenting hard credentials like a username and password).
The cookie may also contain a signed access token, such as a JWT. Depending on your architecture you can remove the session database and rely purely on the signed token for authentication.
In either case you want to set the HttpOnly flag on the cookie when your server is sending the cookie to the browser. This will prevent the JavaScript environment from reading the cookie, this is a good security measure to yourself against XSS attacks.
You also need to protect yourself against CSRF attacks. This is a situation where another website can trigger a GET or POST request to your API, and this will send along the authentication cookies. You can guard against this by creating another cookie that does NOT have the HttpOnly flag, and storing a random value in it. The JS environment must attach this value to any request, typically as a custom HTTP header. Your server then asserts that the value is associated with the session or token.
I’ve tried to cover all the bases in this answer. If you’d like to read more, you can check out these blog posts that I’ve written, they discuss token authentication, but each has sections that cover front-end security issues:
Token Based Authentication for Single Page Apps (SPAs)
https://stormpath.com/blog/build-secure-user-interfaces-using-jwts/
Disclaimer: I work at Stormpath and we provide a secure, hosted user management solution for any application, including Angular! See https://docs.stormpath.com to learn more and find the SDK for your server.