In my project, I'm using the nodeJS and react. For the session on the backend side, I'm using the httpOnly cookie. So when the user login, we're sending the httpOnly cookie with JWT token (httpOnly cookie contains JWT token). Now using this httpOnly cookie, I'm checking the authentication on the backend side.
Now, the problem is how to manage the session (or do authentication check) on react side? because here, we can't access the httpOnly cookie using the javascript.
For example:
/login route --> httpOnly cookie send to the user
/dashboard ----> Suppose, the user wants to open it route without login then we first need to check whether the user is valid or not (If we use local storage then it would be easy because we only need to check the token store in local storage). Now how to check the authenticity of the user in the cookie?
It would be great help if anyone has any idea to resolve this problem.
If you want to use only httOnly cookies then your only option is to implement authentication check on your BE, which will return response based on that cookie (and you use this endpoint for checking authentication).
Other option would be not to use httpOnly cookies. So if you switch to regular cookies you will be able to verify JWT also on the FE like on BE (verifying signature of the JWT before you preform additional actions).
But you should know that normal cookies and also httpOnly cookies can be stolen, so this is the reason that they do not recommend to store JWT tokens in cookies. (but yes httpOnly cookies are a lot safer then regular, but still not 100% safe )
I am using React SPA, Express, Express-session, Passport, and JWT.
I'm confused about some of the different client-side storage options to store tokens: Cookies, Session, and JWT / Passport.
Do tokens have to be stored in cookies, even if I can store them in req.sessionID?
Many websites use cookies to store shopping cart tokens. So far I have stored shopping cart data based on the session ID without adding any cookies.
So when users visit my website, I will match it with their
req.sessionID and then retrieve the data in the database like shopping carts and user session.
Do I need to store cookies? I can access it via req.sessionID to get the data needed.
And the second
I have made authentication using a passport-google-oauth20.After I successfully login, the data is saved into the session. and to send it to the client I have to send it via the URL query ?token='sdsaxas'.
in this case I get a lot of difference of opinion. someone saved it
into local storage and someone saved it into cookies by converting it to a token using JWT.
jwt.sign(
payload,
keys.jwt.secretOrPrivateKey,
{
expiresIn:keys.jwt.expiresIn // < i dont know what is this expired for cookies or localstorage ?
}, (err, token) => {
res.redirect(keys.origin.url + "?token=" + token);
});
Can I indeed store everything related to the session by using sessionID (without cookies or localstorage)?
Only by doing fetch once or every page refresh and retrieving the data and then saved into redux because I use React SPA.
This answer is based on the stateless approach and therefore it doesn't talk about the traditional session management
You have asked two altogether different questions:
Shopping cart - which is more related to business functionality
OAuth 2 & JWT - which is related to security and authentication
As a user of an ecommerce website, I'd expect that any item I add to my shopping cart from my mobile device while commuting to my workplace, should be available in the cart when I login to the website from my PC after reaching home. Therefore, the cart data should be saved in the back-end DB and linked to my user account.
When it comes to authentication using OAuth 2.0, the JWT access token and / or refresh token need to be stored somewhere in the client device, so that once the user authenticates himself by providing login credentials, he doesn't need to provide his credentials again to navigate through the website. In this context, the browser local storage, session storage and cookies are all valid options. However, note that here the cookie is not linked to any session on the server side. In other words, the cookie doesn't store any session id. The cookie is merely used as a storage for access token which is passed to the server with every http request and the server then validates the token using the digital signature to ensure that it is not tampered and it is not expired.
Although all three storage options for access and / or refresh tokens are popular, cookie seems to be the most secured option when used in the correct way.
To understand this better, I recommend you read this and this along with the OAuth 2.0 specification.
Update On 16-Feb-2019
I said earlier that cookie seems to be the most secured options. I'd like to further clarify the point here.
The reason I think browser localStorage and sessionStorage do not provide enough security for storing auth tokens are as follows:
If XSS occurs, the malicious script can easily read the tokens from there and send them to a remote server. There on-wards the remote server or attacker would have no problem in impersonating the victim user.
localStorage and sessionStorage are not shared across sub-domains. So, if we have two SPA running on different sub-domains, we won't get the SSO functionality because the token stored by one app won't be available to the other app within the organization. There are some solutions using iframe, but those look more like workarounds rather than a good solution. And when the response header X-Frame-Options is used to avoid clickjacking attacks with iframe, any solution with iframe is out of question.
These risks can, however, be mitigated by using a fingerprint (as mentioned in OWASP JWT Cheat Sheet) which again in turn requires a cookie.
The idea of fingerprint is, generate a cryptographically strong random string of bytes. The Base64 string of the raw string will then be stored in a HttpOnly, Secure, SameSite cookie with name prefix __Secure-. Proper values for Domain and Path attributes should be used as per business requirement. A SHA256 hash of the string will also be passed in a claim of JWT. Thus even if an XSS attack sends the JWT access token to an attacker controlled remote server, it cannot send the original string in cookie and as a result the server can reject the request based on the absence of the cookie. The cookie being HttpOnly cannot be read by XSS scripts.
Therefore, even when we use localStorage and sessionStorage, we have to use a cookie to make it secured. On top of that, we add the sub-domain restriction as mentioned above.
Now, the only concern about using a cookie to store JWT is, CSRF attack. Since we use SameSite cookie, CSRF is mitigated because cross-site requests (AJAX or just through hyperlinks) are not possible. If the site is used in any old browser or some other not so popular browsers that do not support SameSite cookie, we can still mitigate CSRF by additionally using a CSRF cookie with a cryptographically strong random value such that every AJAX request reads the cookie value and add the cookie value in a custom HTTP header (except GET and HEAD requests which are not supposed to do any state modifications). Since CSRF cannot read anything due to same origin policy and it is based on exploiting the unsafe HTTP methods like POST, PUT and DELETE, this CSRF cookie will mitigate the CSRF risk. This approach of using CSRF cookie is used by all modern SPA frameworks. The Angular approach is mentioned here.
Also, since the cookie is httpOnly and Secured, XSS script cannot read it. Thus XSS is also mitigated.
It may be also worth mentioning that XSS and script injection can be further mitigated by using appropriate content-security-policy response header.
Other CSRF mitigation approaches
State Variable (Auth0 uses it) - The client will generate and pass with every request a cryptographically strong random nonce which the server will echo back along with its response allowing the client to validate the nonce. It's explained in Auth0 doc.
Always check the referer header and accept requests only when referer is a trusted domain. If referer header is absent or a non-whitelisted domain, simply reject the request. When using SSL/TLS referrer is usually present. Landing pages (that is mostly informational and not containing login form or any secured content) may be little relaxed and allow requests with missing referer header.
TRACE HTTP method should be blocked in the server as this can be used to read the httpOnly cookie.
Also, set the header Strict-Transport-Security: max-age=; includeSubDomains to allow only secured connections to prevent any man-in-the-middle overwrite the CSRF cookies from a sub-domain.
LocalStorage/SessionStorage is vulnerable to XXS attacks. Access Token can be read by JavaScript.
Cookies, with httpOnly, secure and SameSite=strict flags, are more secure. Access Token and its payload can not be accessed by JavaScript.
BUT, if there is an XSS vulnerability, the attacker would be able to send requests as the authenticated user anyway because the malicious script does not need to read the cookie value, cookies could be sent by the browser automatically.
This statement is true but the risks are different.
With cookies, the access token is still hidden, attackers could only carry out “onsite” attacks. The malicious scripts injected into the web app could be limited, or it might not be very easy to change/inject more scripts. Users or web apps might need to be targeted first by attackers. These conditions limit the scale of the attack.
With localStorage, attackers can read the access token and carry out attacks remotely. They can even share the token with other attackers and cause more serious damage. If attackers manage to inject malicious scripts in CDNs, let’s say google fonts API, attackers would be able to siphon access token and URLs from all websites that use the comprised CDN, and easily find new targets. Websites that use localStorage are more easily to become targets.
For the sake of arguments
A pen-testing might flag your use of localStorage for sensitive data as a risk.
If it was ok for JavaScript to read access token from localStorage from an XSS attack, why do you think the httpOnly flag is still recommended by everyone.
Recommendation from OWASP
Do not store session identifiers in local storage as the data is always accessible by JavaScript. Cookies can mitigate this risk using the httpOnly flag.
https://medium.com/#coolgk/localstorage-vs-cookie-for-jwt-access-token-war-in-short-943fb23239ca
HTTP is a stateless protocol. Read that answer for more detail, but essentially that means that HTTP servers, such as your web server, do not store any information about clients beyond the lifetime of one request. This is a problem for web apps because it means you can't remember which user is logged in.
Cookies were invented as the solution to this. Cookies are textual data that the client and server send back and forth on every request. They allow you to effectively maintain application state data, by having the client and server agree on what they remember each time they communicate.
This means, fundamentally, you cannot have a session without a cookie. There must be a cookie that stores at least the session ID, so that you can find out which user is currently logged into your app by looking up the session. This is what express-session does: the documentation for the main session method explicitly notes that the session ID is stored in a cookie.
so my question is do I need to store cookies?because I can access it via req.sessionID to get the data needed.
You don't need to store cookies. express-session will do this for you. Your application as a whole does need to store a cookie; without it, you wouldn't have a req.sessionID to look up.
According to my experience, just store token in localStorage.
localStorage:
it can store information up tp 5MB. You do not need to ask user's permission to store token in localStorage.
The only concern is that whether the target device support localStorage api.
Check here: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
It is widely supported. But according to my experience, if you have an ios app, and there is a html page in this app which ask the user to store token (also called webview), the localStorage api cannot be recognized and throw an error.
The solution is simply i just put token in url and transfer it every time. In webview, url is not visible.
Cookie:
It is a very old style to store info locally. Storage in cookie is relatively small and you need to ask user's permission in order to store token in cookie.
Cookies are sent with every request, so they can worsen performance (especially for mobile data connections). Modern APIs for client storage are the Web storage API (localStorage and sessionStorage) and IndexedDB.
(https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies)
Do not store token in sessionStorage or redux.
Data stored in sessionStorage will be lost if the tab is closed. If a user accidentally closed a tab, the token is lost and the server will not be able to identify the current user.
Token stored in redux is not different to be stored in other js files. redux store is just another js file. information stored in redux get lost for every page refresh.
In conclusion,
most of the time, token is stored in localStorage if using a modern style. In certain scenarios, you can store token in cookie and may be put in url sometimes. But never store in session.
Hope it helps.
I'm familiar with Web Storage APIs and cookies but I can't figure what is the most secure way to store an authentication token. I'm wondering if this might break any third-party libraries.
I'd like to have an exhaustive list of available methods to do so, with the pros and cons of each and the best way above all, if any.
Where to Store Your JWTs
With token-based authentication, you are given the choice of where to store the JWT. We strongly recommend that you store your tokens in local storage/session storage or a cookie.
Web Storage (local storage/session storage)
Commonly, the JWT is placed in the browsers local storage and this works well for most use cases.
When logging in a user with a username and password, the response body contains the access_token JWT. Then you need to handle this response in the client side code. This token can then be stored in localStorage or sessionStorage.
Click here for an example using sessionStorage
Both localStorage and sessionStorage both extend Storage. The only difference between them is the persistance of the data:
localStorage - data persists until explicitly deleted. Changes made are saved and available for all current and future visits to the site.
sessionStorage - Changes made are saved and available for the current page, as well as future visits to the site on the same window. Once the window is closed, the storage is deleted.
Web Storage Disadvantages
Unlike cookies, local storage is sandboxed to a specific domain and its data cannot be accessed by any other domain including sub-domains.
Web Storage is accessible through JavaScript on the same domain so any JavaScript running on your site will have access to web storage, and because of this can be vulnerable to cross-site scripting (XSS) attacks.
The developer must ensure that the JWT is always sent over HTTPS and never HTTP.
Using Cookies
You can also use cookies to store the JWT. The exact way to set a cookie depends on the client side language you are using.
There are different options to control the lifetime of a cookie:
Cookies can be destroyed after the browser is closed (session cookies).
Implement a server side check (typically done for you by the web framework in use), and you could implement expiration or sliding window expiration.
Cookies can be persistent (not destroyed after the browser is closed) with an expiration.
Cookies can be read by both the JavaScript and the server side code or only server side if the httpOnly flag is set.
Cookie Disadvantages
The max size of a cookie is only 4kb so that may be problematic if you have many claims attached to the token.
Cookies can be vulnerable cross-site request forgery (CSRF or XSRF) attacks. This type of attack occurs when a malicious web site causes a user’s web browser to perform an unwanted action on a trusted site where the user is currently authenticated. This is an exploit of how the browser handles cookies. Using a web app framework’s CSRF protection makes cookies a secure option for storing a JWT. CSRF can also be partially prevented by checking the HTTP Referer and Origin header.
Can be difficult to implement if the application requires cross-domain access. Cookies have additional properties (Domain/Path) that can be modified to allow you to specify where the cookie is allowed to be sent.
Original article: https://auth0.com/docs/security/store-tokens#how-to-implement
JWTs should never be stored in your localStorage
In fact, they shouldn't even be stored in your cookies, unless you are able to implement very strict CSRF protection
Checkout this for motivation
JWT as an id_token is like your user credentials
JWT as an access_token is like your session token
The most secure option is in-memory. Checkout this for a deep dive
I have an application where I send the auth token to the server with every request as a cookie in the header request. Also, I force the app to run over HTTPS, so cookie headers are encrypted. However, I know that's not enough keep the cookie inaccessible to (XSS) attacks. I thought of the HttpOnly option, but that won't help since it can't be accessible by Javascript.
Is there any other options that I can do to better secure the cookie that I send in the header request?
When using cookie-based authentication, the HttpOnly flag is the one you're looking for: when the user logs in, the server sends the HttpOnly cookie to the browser, which is not accessible by JavaScript and shouldn't be accessible by JavaScript, the only important part is that the browser will automatically send the cookie to the server for every request matching the domain of the cookie.
What you need to keep in mind is that cookie-based authentication needs an additional mechanism to protect against CSRF.
If, on the other hand, you're using OpenID Connect or OAuth2 authentication and want to store the access token in a cookie, then yes, you can't use HttpOnly flag. But it also doesn't make sense to encrypt that cookie with some magic, because if someone can steal the cookie, they'd steal the correctly encrypted cookie which remains valid. The key thing here is, you should protect every input on your website against XSS: if you have text-inputs, you'll have to filter the input against XSS attacks, for PHP you could take a look at the AntiXSS library. Also don't link to client-side libraries, images or other resources from CDN's you don't trust as scripts could be injected from there too.
For access tokens, no matter what method you're using to store or encrypt it, the access token is always prone to XSS, because your own JavaScript application needs access to it. That's the main reason why an access token is, and should always be, short living (max 1 hour f.e.).
I'm exploring JWT and OAuth2 for a Javascript Single-Page-App which will make calls to a backend server-side API. I've come up with a security process that involves using two tokens and gives me the advantage of avoiding the need to have an additional server-side session storage:
The first time the client JS app is loaded up, user sends username/password over SSL to OAuth2 server. The server will set a cookie (normal cookie that is readable by client, without any HttpOnly flag set) that contains a JWT with an OAuth2 access token inside it's claims (along with some other non-confidential data in the JWT claims, ie. user's first/last name, country, role/permission). The server will also set a HttpOnly cookie that will contain the OAuth2 refresh token.
The cookies set by the server will be included on every request from the client automatically (always over SSL), so the server will receive the JWT (see step 3) and both confirm the signature and confirm the OAuth2 access token. The server will also confirm the refresh token. Since the server is checking the access token and refresh token against the OAuth2 database on each request, this gives us the ability to revoke access (which we would not be able to do with the JWT signature alone). We can do a "hard" revoke which revokes both access and refresh token. And we can do a "soft" revoke which just revokes the access token (for instances where perhaps some data that we keep in the JWT claim gets updated, ie. user changes their name or country or role). A soft revoke would be invisible to the client end user (it wouldn't disrupt their logged in status).
In step 2 above, the server will actually look for the JWT in a specific header set by the client (instead of the cookie set by the server). For example, the client JS app will read the JWT from the cookie and then set the JWT in another part of the header. By requring the client to explicitly set a header key/value containing the JWT shows that the client was able to read it's own cookie, thus preventing against XSRF (cross-site request forgery).
The HttpOnly cookie that contains the refresh token ensures we are protected against XSS (ie. some malicious javascript that sneaked its way onto our client). If our JWT was stolen, access still wouldn't be granted because the refresh token was not also seen or stolen by the JS.
With this approach we get all these benefits:
We don't need a server-side session storage. Since we are hitting an OAuth2 server then we can simply just include some extra data in the JWT that we return (non-confidential data). We wouldn't need to re-query/refresh the data in the JWT every time, but perhaps only when the OAuth token is revoked (ie. was revoked when some user data was changed that we include in the JWT's). No need to tackle the storage/scaling requirement that comes with using sessions. The client JS app can use this data like any other app would normally use sessions. For instance I can display a user's name on every "page" in the app. We could also just use websockets, but the JWT is a good backup place for adding some data if we need it.
We are protected against XSRF.
We are protected against XSS.
We can revoke access and also log users out (which is not easily possible with JWT alone).
SSL prevents man-in-the-middle attacks.
The JWT adds a little extra security hurdle for attackers to pass versus just a normal JSON object serialized in the cookie. The attacker would need to get the server-side key for signing JWT's (in addition to OAuth access). The JWT is also a standard, so easier for a trusted developer to work with.
The JWT can be easily passed down to other micro-services sitting behind the OAuth layer to use service-to-service. We can pass it around as "session like" data access to all the services on a request. If a service want's to change something in that data, then they can inform OAuth2 server and it will "soft" revoke the user's current JWT (not really much different from the process with a session storage) and provide a new one.
I haven't exactly seen anyone detail a security process like this yet. Many I see seem to only talk about using JWT with an OAuth2 access token inside and don't elaborate much more. So my question is, does this approach indeed provide the benefits I listed above? If not, what am I missing here and what security hole have I not covered for?