JSON Web Tokens (JWT) - Validate Client - javascript

I've been investigating JWT and I'm very interested in using it. I like that it doesn't require state checks on the server, due to the digital signature and payload contents.
The thing I'm having a hard time is validating the client. I understand that the signature allows the server to say "yes I issued this token, it is valid", but I don't totally understand how the server can verify the client is who it says it is.
Digital signature makes sense from the server side, but the client can't sign anything to verify who it is because browsers can't keep secrets. This is the one part I haven't been able to wrap my head around. If the browser can't keep the secret, how can it add data to the token (like a nonce, or information about the resource it's requesting) to be included in the signature, similar to how oAuth 1.0 works.
Is this not supported? Are there other way to validate the browser is who it says it is? What if my client has a security hole that leaks tokens? If the client isn't validated, couldn't anyone use those tokens? I don't think "short expiration times" is a good solution to that problem.
Can someone help me wrap my head around this part of JWT?

To add on to what Tim B said, I have used tokens where the secret key has the browser AND ip appended to it like so: (PHP Example)
$secret_key = 'kajsdfkljk' . $_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT'];
That does seem to work, however, if you're bouncing around from network to network, then you would have to login each time, in which case you could just use the user agent and not the ip.
Another thing to note here is that if there was a leak of some sort, you could always change the secret key, in which all tokens issued from your server would no longer be valid.
Also, without using https connections, tokens can be very dangerous to use for authentication.

Verifying the client isn't compromised isn't really possible, as it could definitely leak a token. Token expiration helps mitigate a leaked token being dangerous for too long, but as you mentioned isn't a fool proof solution. You could do something use the requesting user's current IP address as part of the signing key to help mitigate against a leaked token being used elsewhere. It could still be used via XSS locally, but not as easily used by phishers.
My understanding is that the client wouldn't add information to the token, it would simply pass it beside the additional info. Separate POST vars -- a token to "verify" identity, the other vars to define additional parameters.

Related

How to handle the JWT on the client layer?

This is a subjective question, although I believe this is not opinion based. The only reason of asking it here is that I could not find satisfying answer even after reading multiple articles on JWT Authentication.
I recently started learning JWT and found that it is a 3 part token issued by server to client for authenticity along with passing data like user-scope/roles/permission etc in forms of claims.
My question however are:
The claim part of token still is base64 encoded string which can easily be parsed using atob/btoa. So is the transmission really secure ? What is the real gain here ?
There are multiple articles on generating and sending token to UI. However, almost no good articles on what UI does exactly with it. Is it a common practice to decode the token using atob and use the content within it ? Or is there a different way of validating and retrieving data from it.
Is it really secure to transmit data via headers. I mean is it safe against things like MITM, XSS etc.
I would really appreciate some efforts from the expert in resolving these queries ?
For question #1, the gain is not on the client side. If you can't trust what you received from the server, you can't trust it no matter how it's obfuscated/encoded/encrypted/. The point is that you send this token back to the server. On the server, a quick check will tell that this token is legitimate. Imagine a complex login scenario, where MegaCorp looks up permissions for the user across 739 subsystems, combines them into a single payload, and then doesn't have to do that again on further requests. When the client sends the token back, it validates that you are properly logged in and uses the permissions to do further processing.
For #2, you can put whatever you like into this payload, so long as it isn't meant to be too secure. I mostly use it for basic user info and for application permissions. So I can paint the user's name and offer a link to the specific user settings page. I can check whether the user has access to an administrative page or whatever permissions I need to check. While a malicious user can fool the system by manipulating that data client-side, and can therefore, say, see the admin page, when the call goes back to the server to get the data for that page, the token is either illegitimate and the request will be rejected, or it won't contain the proper permissions and, again, it will be rejected.
I don't really know enough about security to attempt an answer to #3.
Some people use JWT only for isLoggedIn, which is fine, but I think misses some useful possibilities. Used properly, this can be the single mechanism to capture user information for both the client and the server. But the important side to my mind is the server. This can be done in many ways on the client. But it's hard to find something better for the server.
The claim part of token still is base64 encoded string which can
easily be parsed using atob/btoa. So is the transmission really secure
? What is the real gain here ?
The transmission is secure (cannot be read/modified by others) if you send the token via https. JWT contains 2 important parts: a payload and a verify signature.
The signature can be produced and verified only by one person and prove that the payload is legit for that person.
Here is a simple use case:
Client send is credential to the Auth server to receive the right to publish something
The server receives the credential and valid them through a complex process then send back to the client a JWT saying: {I give Client the right to publish signed the Auths erver}
The Client store locally the token
When the client needs to publish something he sends the JWT and is work to server B which share the signing key with Auth server.
Server B verify easily the token and publish the work of the client
Another example of usage is authentication via mail only.
There are multiple articles on generating and sending token to UI.
However, almost no good articles on what UI does exactly with it. Is
it a common practice to decode the token using atob and use the
content within it ? Or is there a different way of validating and
retrieving data from it.
In general, the client wants to obtain a token from some server to send it back later. The client cannot verify the signature because he does not share the private key with the server, he is not a source of trust.
Is it really secure to transmit data via headers. I mean is it safe
against things like MITM, XSS etc.
Using https it is safe: Are HTTPS headers encrypted?

JWT token signature validation javascript

I was making a javascript client that connects to an Api using JWT tokens. On the server side there are no problems, I can create the token sign it and later verify the signature en thus ensure that nobody tampered with the token.
But how do I do this on the client side. I can just decode the JWT token and see the header, payload and signature. But how do i verify the signature at the client site? Are there libraries for this, how do I transfer the public key to the client?
If I do not verify the signature how can I know the token is not tampered with?
if I do not validate the signature at the client side how can I ensure that the token is indeed from the server.? Maybe there is somebody in the middle who is changing the token
Signature validation does not avoid a Man In The Middle attack. An attacker could sniff the channel to capture credential or alter messages even using valid tokens
Use a SSL/TLS channel (https)
If I do not verify the signature how can I know the token is not tampered with?
A token provided by a TLS trusted server is probably valid.(it could has been altered in local storage). You can validate the signature. This operation is usually done in server side( see #sakuto answer), but you can do it in the browser perfectly
But how do i verify the signature at the client site?
These are the steps
Download the public key from a trusted server
extract the signature from JWT and decode it( base64url)
verify the digital signature using a cryptographic library
I suggest to use the Webcrypto. See an example of RSA import key an validation here: https://github.com/diafygi/webcrypto-examples/blob/master/README.md#rsassa-pkcs1-v1_5
You are usually not doing verification on client-side, nor storing important data on the token. Every control and permission are checked on the back-end. Meaning that even if the user tamper its token, he won't able to pass the back-end control, only possibly seeing one more option on the front.
This type of work-around comments are the reason why I don't trust "libraries" written by others.
JWT.io has reported that many of the libraries that are widely available have security vulnerabilities.
RFC 7519 clearly states that the application MUST validate the token signature and if its signature is not valid, you MUST discard it.

How to keep the shared secret secret when using JWT, for example?

There is something very basic I do not understand. In order for JWT to be secure both the client and the server must share a secret.
However, the client is typically a JavaScript application running in a browser on some remote completely unknown client machine.
Suppose I am the author of both the server and the client code, how am I supposed to ensure the safety of the shared secret on the client side?
You assume the secret is shared. It doesn't have to be. (And it only ever should be shared between systems trusting each other. You usually cannot trust the client that executes your JavaScript.)
A typical use for JWT is for the Server to produce signed data using the secret and sending the signed data (without the secret) somewhere (e.g. a client) without persisting it. When it gets the data back, it can verify (using the secret rather than a persisted copy of the data) that the data hasn't been tampered with since is has been signed.
What application does that use pattern have? You can e.g. implement token-based permissions that way and thus have authentication without identification:
Let's assume you provide a cloud storage service. A user can upload a file, to which you assign some identifier, let's say 5. You generate a shareable URL that has the JWT-signed data "may access file #5" as one of its parameters and display that URL to the user. The user and everyone they share this link with can then access that file through that URL. You just have to verify that the signature is a valid signature created by you and that the signed data indicates the correct file. Of course, if someone with whom the user has shared the URL distributes it further, other people may get access that way, too. But without knowledge of the URL, the file isn't accessible.
It is the same as sending cookie to client on auth and then relying to it for other actions.
Yep, you can't ensure safety of client's cookies, they can be stolen. Same as jwt token can be stolen.
Good part about jwt is that token itself is not being the part of comminication as cookie, so you can use it even in http communications - even if somebody gets the payload or header of user's request he wont be able to create new request with other data, which is possible in case of cookies usage.

Authentication with JWT

I've been following this blog post (https://auth0.com/blog/2015/04/09/adding-authentication-to-your-react-flux-app/), and am confused on an aspect of JWTs.
The post above seems to test if the user is already logged in by checking to see if there is a JWT stored as a cookie, and if so, it simply decodes it to find the username and other information, and redirects the user to the authenticated page.
I'm wondering what is stopping someone from adding a fake JWT cookie to gain access to an authenticated portion of the app? I must be missing something obvious. In other words, when maintaining a session, how does the frontend ensure that the JWT is one that was "signed by the server" or something, and not one that was fraudulently created to try to gain access?
In many apps, someone can add a fake JWT to gain access to parts of the front end that you only want them to see if they are logged in. But then, they also have the front end running on their own computer and can change the code to do the same thing.
The back end server encoded the JWT using a key that should not exist on the front end, and when you pass the JWT back to the server the server will decode it BEFORE processing your request. So it knows that someone used your login credentials earlier, that it sent out the JWT in response, and that someone is sending it the JWT again. This blocks attacks on your API from people without the (real) JWT.
It also has advantages over session cookies in that it is stateless on the server side and it makes certain cross-site request forgery attacks harder in traditional browsers because an attacker can't embed a request to your site and trust the browser to add your session cookie.
But it's only one part of a larger security solution.
The key here to JWT's security is the "secret"-- a key that should only be on trusted servers (or with your authentication provider, if using a third party). JWTs are encrypted using this secret. It can be a passphrase, but JWT also supports public/private key encryption, so the secret can also be a private key.
So, in your case, what's preventing the user from creating new JWTs on their end is, unless they know the secret, the encryption they use to create their own JWT will not work on the server, which, if coded correctly, will prevent the user from authenticating the way they wish to.

How to Secure ASP.NET Web API with Cross Domain AJAX Calls?

I want to create an API at www.MyDomain.com that is accessible from public websites www.Customer1.com and www.Customer2.com. These public websites display each customers inventory and do not have any login features. They will use AJAX calls to read data from my API.
How can I secure the API so that it can be accessed via AJAX from different domains but no one can access the API to be able to scrape all of my customers data and all of their inventory?
I have tried thinking of different solutions on my own but they would all either require people to login to the public websites (which isn't an option) or it would require some secret "key" to be displayed publicly in the browser source code which could then be easily stolen.
Any ideas would be greatly appreciated.
Thanks!
P.S. Are their any obstacles that I am going to run into using Javascript & CORS that I need to look into now?
Anything that is accessible without authentication from a browser is by definition insecure, so you can't stop that. Your best bet is to have to have a relationship with the owner of customer1.com and customer2.com - the server apps for those two websites would make an HTTP call to you and authenticate with your service. Going this way also avoids the CORS issues you're talking about.
If you've already designed the client functionality, you can still probably do it without much change to the javascript - have it point to customer1.com for its AJAX call instead of your API, and customer1.com would accept this request and just act as a proxy to your API. Aside from the authentication, the rest of the request and response could just be pass-throughs to your API.
You can use Microsoft.AspNet.WebApi.Cors.
It's just need add ONE line at webapi config to use CORS in ASP.NET WEB API:
config.EnableCors("*","*","*");
View this for detail.
The simplest way to provide a minimum security here is to provide some kind of token system. Each app has its own token, or combination of tokens which it must pass to the server to be verified. How you generate this tokens is up to you and other than being linked to app's access, doesn't have to mean anything.
Provide a way for each API implementer to open an account with you. This way you will know who is accessing what and in some cases you can block/stop service.
For instance, a token can just be an MD5 hash:
7f138a09169b250e9dcb378140907378
In the database, this hash is linked to their account. On each request, they send this token with what they want. It is verified first to be valid, then the request is fore filled. If the token is invalid, then you can decide how to deal with it. Either don't return anything or return an "access denied" (or anything you want).
One thing to avoid is having a single token for everyone, though this can be a starting point. The reason for this is if some unauthorized app gets a hold of this token and exploits it, you have to change the token for everyone, not just the app that somehow leaked the token. You also can't control if someone has access to something or not.
Since you listed ASP.NET, I can also point you to WCF, which is fairly complex but has all the tools that you need to setup a comprehensive web service to service both you and your clients.
I hope this gives you a starting point!
EDIT:
There are security concerns here in the case that someone leaks their token key somehow. Make sure that you setup a way in which the app/your service do not expose the the token in anyway. Also have a flexible way of blocking a token, both by your clients in you, if it so happens that a token is exploited.

Categories