I'm looking into JWT as an alternative to traditional sessions with cookies but I fail to see how they differ fundamentally from signed cookies that for example Express is offering through middleware like cookie-parser.
In both of them, the last part is the signature of the payload which guarantees the payload hasn't been tampered with.
Signed cookie:
user=tobi.CP7AWaXDfAKIRfH49dQzKJx7sKzzSoPq7/AcBBRVwlI3
Equivalent JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjoiVG9iaSJ9.kCTlR_Igb4H5cqBEDedShM2ivSQijPQkWqN4pZAXb2g
Besides the facts that:
(1) JWT doesn't come with origin restrictions and that
(2) the cookie content is immediately human-readable, whereas the JWT content (header + payload) are base64 encoded
is there anything that gives JWT a clear advantage over signed cookies?
Beware of mixing the concerns: cookies are primarily a mechanism for storing data on the client, they aren't inherently an authentication mechanism - but we use them that way :)
The primary benefit of JWTs are the declared structure (JSON, with common fields) and the declared mechanism for signing them. This is all just specification, there is nothing special about it. But it is nice to have a common way of persisting identity assertions.
You still need to store your JWT in a secure fashion, and cookies with HttpOnly; Secure are the best option. This prevents the cookie from being read by the JavaScript environment, which prevents XSS attacks.
I've written some blog posts about JWTs, they contain more information that will help to answer your question:
Build Secure User Interfaces Using JSON Web Tokens (JWTs)
Token Based Authentication for Single Page Apps (SPAs)
Disclaimer: I do work at Stormpath. We sponsor open-source JWT libraries for Node.js and Java, which can be found here:
https://github.com/jwtk
If you are using AngularJS, we also implement JWT best practices out of the box with our Stormpath Angular SDK
Cookies are typically used to protect web applications. The browser will add them automatically to every request. This makes the requests vulnerable to CSRF attacks.
JWT tokens are typically used to protect Web APIs. The token is attached to the AJAX request in JavaScript. Since the token is not attached to the request automatically, the request is not vulnerable to CSRF attacks. JWT tokens can also be used cross-origin in case the API you're talking to is on another domain.
JWT tokens are also used in native clients to talk to web APIs.
Related
I use ajax to store, update and delete resources associated with authenticated user. Routes for these actions use web middleware so cookies, session etc are available. Project is based on Laravel framework.
Is it necessary to protect those routes from unauthorized access in any additional way? I've read about API tokens that one could use, but I am not sure if it is necessary.
I will be grateful for any insights on ajax security or how ajax requests work in general, as it is a little over my head at this moment.
I would say no additional work is necessary assuming you have appropriate checks in place such as a user can't delete another user's entities, etc...
AJAX requests are really just like the user browsing to different pages except it's javascript making requests on their behalf. Since everything is already behind the web middleware, there should be no need for additional authentication since your users have technically already logged in.
Look for JSON Web Tokens
What is JSON Web Token?
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a
compact and self-contained way for securely transmitting information
between parties as a JSON object. This information can be verified and
trusted because it is digitally signed. JWTs can be signed using a
secret (with the HMAC algorithm) or a public/private key pair using
RSA.
and this article:
Authenticate users in Node using JWT and Laravel
I have a client-side application on domain client-domain.example and a server-side application on domain server-domain.example. There is an API on the server-side. The client-side application sends AJAX requests to the server-side application. I use token-based authentication, so the client-side application sends token in headers with each AJAX request, for example: "Authorization: Bearer {some token}". It works fine with AJAX requests, when I need to get or post some data.
But the server-side API also keeps files. For example images. The files are private, only authenticated users can get them. And I need to show this images on the client-side in <img> tag. I can't get them using <img src="http://server-domain.example/path/to/image"> because in this case browser will not send Authorization header to the server-side.
What is the adopted solution? How client applications load images from server-side API?
There are three methods to solve it, the best approach to solve it is using the signed URLs
1. signed URL (can be insecure)
The first method simply creates a route without authentication (anonymous access) with a signature hash parameter that indicates if the resource can be loaded or not.
<img src="http://server-domain.example/path/to/image?guid=f6fc84c9f21c24907d6bee6eec38cabab5fa9a7be8c4a7827fe9e56f2">
When the server receives the request it must validate the guid if the expiration time has not been reached and, of course, check if the guid has a valid signature.
This approach is used by several files/documents servers like Dropbox, S3, CDN providers, etc.
See the technique in some companies.
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-urls.html#private-content-overview-choosing-duration
https://client.cdn77.example/support/knowledgebase/cdn-resource/how-do-i-set-up-signed-urls
SECURITY:
the guid can not be just UUID of the image/user, because this doesn't provide any protection.
the guid can not be the same token you use for authentication (for example, you can't use auth-JWT tokens), because the user can share the link - and the user will share his tokens (see also (2)).
as mentioned above: guid should have a server-side mechanism of validation (date/signature/...) and should not provide more permissions than "access to the requested file"
2 Query String with JWT (most probably a security breach)
The second method is to pass the token by querystring with the image URL.
This method is not recommendable because it exposes clearly the URL and many servers sometimes write and expose public logs of URL accessed. The bad notice is that the JWT exposed normally the user can get control a lot of features further the image load.
<img src="http://server-domain.example/path/to/image?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c">
When the server receives the request you must validate the token by querystring and response with the content.
SECURITY NOTES: worse than (1) - because now authentication info (JWT auth) is exposed in the URL and can be cached/logged by servers OR accessed by any server in the middle OR the user can simply share the "image link" with their colleagues.
But if JWT is NOT an access token, but a one-time token generated specifically for accessing that particular file in a form of JWT then it provides the same level of security as (1).
3. cookies
The third method creates an authenticated cookie to validate the access of the image.
This method is not recommendable because is out of API pattern (webapi/token based authentication in general).
When the server receives the request you need to validate if the validate cookie is valid.
SECURITY NOTES: if you can provide security for your cookies and XSS and CSRF — are not just letters for you then it is a solution. But keep in mind: cookies are sent by the browser automatically with each request. Much more information about possible threats and solutions: Where to store JWT in browser? How to protect against CSRF?
My solution to basically this exact same problem, based on Jeferson Tenorio's answer below (option 1), was to sign the URL to my API call with an encryption of the image and the user's JWT token, e.g. path/to/image?token=xxxx. In laravel this is easily accomplished with encrypt($your_object) and decrypt($token) (https://laravel.com/docs/5.7/encryption), and then I used the extracted token to verify the user had access to the file in question. But there are probably many other libraries capable of handling this.
I would be curious if there are any security concerns, but from my perspective the JWT is never exposed via plain text and the encryption relies on a secret key that malicious actors shouldn't have access to, so it seems like it should be fairly secure. My only real complaint is that the token is quite long using this method which does not make for presentable URLs.
I understand that JWT are stateless tokens that store signed information about the client's claim and are passed to a server via the Authorization HTTP header.
My question is, why do we need JWT when we already have client sessions (https://github.com/mozilla/node-client-sessions)? Client sessions are conceptually the same. They're cookies that contained signed information which when verified means the cookie hasn't been tempered with. Also, client sessions are stored in a cookie and passed via the Cookie HTTP header. It's the same thing only using different words. Am I wrong?
So, why is JWT even around? I could understand that maybe the point is to standardize the way authentication tokens work, but we got along fine without a session ID based standard (each implementation did things their own way). Also, why would the JWT not use cookies as a means of transfer. With cookies, you wouldn't need explicitly send the correct header for every request (simplifying Ajax requests).
Am I missing something?
JWT tokens are signed JSON formatted documents that assert claims about a user (or any principal). If you trust the issuer of the token, you trust the claims in the token and can make authorization decisions based on this.
JWT tokens are often used for calling external Web APIs. These APIs do not necessarily live on the same domain as your website and therefore cannot use the same cookies as your site. JWT tokens are used in REST services as they do not need any session info stored on the server. Using JWT tokens is also not vulnarable to CSRF attacks.
I still cannot understand what is the main purpose of JWT. As for me the only purposes are:
to overcome CSRF
and to ensure better mobile support (because mobile apps in some cases don t support cookies).
Also there is a claim that with JWT you don't have to worry about session storage on the server side. This is not clear to me. How could JWT completely replace session storage on the server side? Does this mean that we put all session data into the JWT, encrypt it and send it to client on every response? But if so, does that mean the token that is issued by server will change depending on the data which we used to store in session? And as i understand the only thing that prevent us from using cookie this way(without session storage on the server side) is the size limit on cookie files - only 4kb.
Also do we still need to use SSL to prevent session hijacking?
Please tell me if my understanding is right or there is some other aspects.
I think there're too many legends about JWT. To understand its essence, we should get back to its original definition.
According to its official site:
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a
compact and self-contained way for securely transmitting information
between parties as a JSON object. This information can be verified and
trusted because it is digitally signed.
So essentially, what JWT offers is just a way to transmit data. No more, no less. And because multi parties are involved, the format MUST be standardized. And once the format is standardized, libraries can be made to facilitate its adoption.
Again from the official site:
When should you use JSON Web Tokens?
There are some scenarios where JSON Web Tokens are useful:
Authentication:
This is the typical scenario for using JWT, once the user is logged in, each subsequent request will include the JWT,
allowing the user to access routes, services, and resources that are
permitted with that token. Single Sign On is a feature that widely
uses JWT nowadays, because of its small overhead and its ability to be
easily used among systems of different domains.
Information Exchange:
JSON Web Tokens are a good way of securely transmitting information between parties, because as they can be
signed, for example using public/private key pairs, you can be sure
that the senders are who they say they are. Additionally, as the
signature is calculated using the header and the payload, you can also
verify that the content hasn't changed.
So, Authentication is merely one of the possible use cases of JWT. Though it is indeed a typical usage of JWT.
As far as authentication is concerned, JWT can be used to replace session+cookie approach because it can save server's memory for storing sessions. But how big the benefit is depends on the user amount and your specific scenario. If there's only a few clients and no cross-domain authentication requirements, I don't think you need to give up the good old session+cookie approach.
Last but not the least, Session is not JUST meant for authentication. It is actually meant to place HTTP requests and responses within a larger context. I am not sure if JWT can replace session for that purpose given JWT's size limit. And IMHO, authentication just happened to be one of the use cases of session since such info must be user-specific. There are many other good scenarios to justify session, such as Shopping Cart.
JWTs in itself are just self-contained tokens and don't provide CSRF protection. The protocol used to deliver the JWT may (or should) provide means to prevent CSRF.
One area where JWTs are notably "better" than cookies is their cross-domain capability. You can read more on the comparison between tokens and cookies here: https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/
JWTs can be self-contained so they have all the information that you need in a verifiable container that would enable you to use them without storing them (or a reference to them). But there may be more data that you need in a session so avoiding session storage in general is not a reason in itself for moving to JWTs.
SSL is required for sure to prevent token leakage and session hijacking.
We're currently developing an entirely AJAX based app that will interact with the server via a RESTful API. I've considered potential schemes to protect against XSRF attacks against the API.
User authenticates and receives a
session cookie, which is also
double-submitted with each request.
We implement an OAuth consumer in
Javascript, retrieve a token when
the user logs in, and sign all
requests with that token.
I'm leaning toward the OAuth approach, mainly because I'd like to provide 3rd party access to our API and I'd rather not have to implement two authentication schemes.
Is there any reason why an OAuth consumer would not work in this situation?
Most AJAX libraries will set an additional header "X-Requested-With: XMLHttpRequest", which is difficult to fake in a basic XSRF attack (though possible if combined with XSS). Verifying that this header exists is a good defense-in-depth strategy if you expect all your requests to be AJAX.
Use a two-step request, the first asking for the server an unpredictible token, the second asking for the real action with the token.
As the attacker can't predict the token, and can't read it (same origin policy) he can't give a valid token in the second query.
But be careful to not leak tokens (learn about capturing json using when they affect value to a global variable and so on) and read :
http://www.google.com/search?q=xsrf+defence
The easiest way to prevent XSRF it to check the referer of every RESTful request to make sure the request is coming from the same domain. The session cookie is important for keeping state, but it will not defend against XSRF becuase it will also be sent with a forged request. Its common to see referer based XSRF protection system on embedded network hardware with limited memory requirements, Motorola uses this method on most of their hardware. This isn't the most secure XSRF protection, token based protection is better but both systems can still be bypassed with XSS. The biggest problem with token based XSRF protection is that it takes alot of time to go back and fix every request and you will probably miss a few requests.
Make sure to read up on the same origin policy and to scan your site for xss. You should also read the OWASP Top 10 for 2010 A3-Broken Authentication and Session Management.