What if JWT is stolen? - authentication

I am trying to implement stateless authentication with JWT for my RESTful APIs.
AFAIK, JWT is basically an encrypted string passed as HTTP headers during a REST call.
But what if there's an eavesdropper who see the request and steals the token? Then he will be able to fake request with my identity?
Actually, this concern applies to all token-based authentication.
How to prevent that? A secure channel like HTTPS?

I'm the author of a node library that handles authentication in quite some depth, express-stormpath, so I'll chime in with some information here.
First off, JWTs are typically NOT encrypted. While there is a way to encrypt JWTs (see: JWEs), this is not very common in practice for many reasons.
Next up, any form of authentication (using JWTs or not), is subject to MitM attacks (man-in-the-middle) attacks. These attacks happen when an attacker can VIEW YOUR NETWORK traffic as you make requests over the internet. This is what your ISP can see, the NSA, etc.
This is what SSL helps prevent against: by encrypting your NETWORK traffic from your computer -> some server when authenticating, a third party who is monitoring your network traffic can NOT see your tokens, passwords, or anything like that unless they're somehow able to get a copy of the server's private SSL key (unlikely). This is the reason SSL is MANDATORY for all forms of authentication.
Let's say, however, that someone is able to exploit your SSL and is able to view your token: the answer to your question is that YES, the attacker will be able to use that token to impersonate you and make requests to your server.
Now, this is where protocols come in.
JWTs are just one standard for an authentication token. They can be used for pretty much anything. The reason JWTs are sort of cool is that you can embed extra information in them, and you can validate that nobody has messed with it (signing).
HOWEVER, JWTs themselves have nothing to do with 'security'. For all intents and purposes, JWTs are more or less the same thing as API keys: just random strings that you use to authenticate against some server somewhere.
What makes your question more interesting is the protocol being used (most likely OAuth2).
The way OAuth2 works is that it was designed to give clients TEMPORARY tokens (like JWTs!) for authentication for a SHORT PERIOD OF TIME ONLY!
The idea is that if your token gets stolen, the attacker can only use it for a short period of time.
With OAuth2, you have to re-authenticate yourself with the server every so often by supplying your username/password OR API credentials and then getting a token back in exchange.
Because this process happens every now and then, your tokens will frequently change, making it harder for attackers to constantly impersonate you without going through great trouble.
Hopefully this helps ^^

I know this is an old question but I think I can drop my $0.50 here, probably someone can improve or provide an argument to totally decline my approach.
I'm using JWTs in a RESTful API over HTTPS (ofc).
For this to work, you should always issue short-lived tokens (depends on most cases, in my app I'm actually setting the exp claim to 30 minutes, and ttl to 3 days, so you can refresh this token as long as its ttl is still valid and the token has not been blacklisted)
For the authentication service, in order to invalidate tokens, I like to use an in-memory cache layer (redis in my case) as a JWT blacklist/ban-list in front, depending on some criterias:
(I know it breaks the RESTful philosophy, but the stored documents are really short-lived, as I blacklist for their remaining time-to-live -ttl claim-)
Note: blacklisted tokens can't be automatically refreshed
If user.password or user.email has been updated (requires password confirmation), auth service returns a refreshed token and invalidates (blacklist) previous one(s), so if your client detects that user's identity has been compromised somehow, you can ask that user to change its password.
If you don't want to use the blacklist for it, you can (but I don't encourage you to) validate the iat (issued at) claim against user.updated_at field (if jwt.iat < user.updated_at then JWT is not valid).
User deliberately logged out.
Finally you validate the token normally as everybody does.
Note 2: instead of using the token itself (which is really long) as the cache's key, I suggest generating and using a UUID token for the jti claim. Which is good and I think (not sure since it just came up in my mind) you can use this same UUID as the CSRF token as well, by returning a secure / non-http-only cookie with it and properly implementing the X-XSRF-TOKEN header using js. This way you avoid the computing work of creating yet another token for CSRF checks.

Sorry being a little late on this, but had the similar concerns and now want to contribute something on the same.
1) rdegges added an excellent point, that JWT has nothing to do with the "security" and simply validates, if anyone has messed up with the payload or not(signing); ssl helps to prevent against breaches.
2) Now, if ssl is also somehow compromised, any eavesdropper can steal our bearer token (JWT) and impersonate the genuine user, a next level step what can be done is, to seek the "proof of possession" of JWT from the client.
3) Now, with this approach, presenter of the JWT possess a particular Proof-Of-Possession(POP) key, which the recipient can cryptographically confirm whether the request is from the same authentic user or not.
I referred Proof of Possesion article for this and am convinced with the apporach.
I will be delighted, if able to contribute anything.
Cheers (y)

To deal with the problem that tokens are getting stolen, you map each JWT with the list of valid IPs.
For eg, when the user logs in with a particular IP when you can add that IP as valid IP for that JWT, and when you get the request pf this JWT from another IP (either the user changed the internet or JWT is stolen, or any reason) you can do the following depending on you use case:
Map CSRF token with user token and incase it gets stolen then it's CSRF token will not match in that you can invalidate that user token.
You can provide a captcha to the user to validate if he is a valid user or not. If he enters the captcha then add that IP to the valid list of that JWT.
You can log out the user and make a new request to log in again.
You can alert the user that your IP has changed or requested from a different location.
You can also use cache with a small expiry of 5 mins in above use-cases instead of checking each and every time.
Suggest if it can be improved.

Can't we just add the ip of the initial host which has requested to generate this JWT token as part of the claim ? Now when the JWT is stolen and used from a different machine, when the server validates this token, we could verify if the requested machine ip matches with the one set as part of the claim. This would not match and hence the token can be rejected. Also if the user tries manipulate the token by setting his own ip to the token, the token would be rejected as the token is altered.

Once the token gets stolen - it is game over.
However there is a way to make it harder to make use of a stolen token.
Check https://cheatsheetseries.owasp.org/cheatsheets/JSON_Web_Token_for_Java_Cheat_Sheet.html#token-sidejacking for reference.
Basically, you create a x-Byte long fingerprint in hexadezimal, store its raw value in the token - hash the fingerprint using for example SHA-512 and put the hashed fingerprint inside a httponly secure cookie.
Now instead of validating just the signature and expired date of the token you need to also validate the existence of the cookie and be sure that the raw fingerprint values match.

Client should use part of the hash of user password to encrypt the time that the http msg was sent by client to the server. This part of the hash should also be encrypted with some server secret key into the token when it is created.
The server than can decrypt the http request time and verify for short time delay.
The token is going to change every request.

Related

Why JWT is called authentication

I'm learning purpose of JWT tokens in ASP.NET Core, but I don't understand one thing. Why does every blog calling JWT authentication? If we pass a token to an authenticated (logged-in) user. I mean why JWT is not authorization but authentication? Can't understand which point I'm skipping in this topic.
In a typical implementation, the JWT token that you create for a signed in user will be sent with every subsequent request. The purpose is that you want to make sure that the party that sends the request is actually who they are claiming to be - ie. you want to authenticate requests.
Strictly speaking, without this, you could not do authorization, or well, you could, but it wouldn't make much sense if you just beleived who the caller was instead of checking (authenticating).
Edit:
The jwt token will always have a "sub" field, a subject, usually a user identifier, and an expiry, even if there are no further claims. The token is also signed(*) that can and must be verified. So if somebody can present a token with their identifier, signed by your server, with a timetstamp not very long ago, then you can be sure that they recently authenticated, eg. provided their password. In all subsequent requests you don't need to get their password, you only check the token. You know they are who they say to be, because they have a valid token, your server signed their email address, so they are logged in.
An attacker cannot forge such a token, because while they can replace or forge their user identifier (the sub field), the signature on the token will not be valid. Only your server can make a signature that can then be verified (by your server in this case).
So in other words, there is the initial user authentication, when they provide their username and password, but HTTP is basically stateless, the next HTTP query has nothing to do with the first one. You explicitly have to make this connection, ie. create a user session, you have to securely "remember" that when a new request comes in from a user, it's the same user that already provided their password. So when they do provide their password, you make a JWT for them with their email address and a timestamp, sign it, and next time they only send that, and you know it's them, because there's you signatuare on the token.
The reason you don't want them to send their password all the time is that sending passwords around in every request would present a somewhat higher risk, but much more importantly, then the client app (the browser in a webapp) would have to remember a user's password, which is not good, it's by far more secure to erase that from the browser's memory. So you create them a JWT instead.
Also note that in such a usecase, a JWT is unnecessary, maybe that's where your confusion comes from. You could just send the user a plain old random session token, which you also store on the server, and store all state in the server-side session. This is all fine, and actually more secure than a JWT. JWTs should be used for example when the authentication token needs to be sent to different origins (domains), or when secure claims should be shared with another party. Using JWTs for primary authentication with a simple web app with one origin is unnecessary (very fancy today, but not correct).
(*Note that for such a usecase, the signature is usually a message authentication code, a MAC, but I did not want to confuse you further with this word, as message authentication is another authentication. You can just think of this as a signature for now, though signature in cryptography is something different, and even more confusingly, JWTs can use actual signatures too.)

Vue protecting paths from edited localstorage [duplicate]

When building SPA style applications using frameworks like Angular, Ember, React, etc. what do people believe to be some best practices for authentication and session management? I can think of a couple of ways of considering approaching the problem.
Treat it no differently than authentication with a regular web application assuming the API and and UI have the same origin domain.
This would likely involve having a session cookie, server side session storage and probably some session API endpoint that the authenticated web UI can hit to get current user information to help with personalization or possibly even determining roles/abilities on the client side. The server would still enforce rules protecting access to data of course, the UI would just use this information to customize the experience.
Treat it like any third-party client using a public API and authenticate with some sort of token system similar to OAuth. This token mechanism would used by the client UI to authenticate each and every request made to the server API.
I'm not really much of an expert here but #1 seems to be completely sufficient for the vast majority of cases, but I'd really like to hear some more experienced opinions.
This question has been addressed, in a slightly different form, at length, here:
RESTful Authentication
But this addresses it from the server-side. Let's look at this from the client-side. Before we do that, though, there's an important prelude:
Javascript Crypto is Hopeless
Matasano's article on this is famous, but the lessons contained therein are pretty important:
https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/august/javascript-cryptography-considered-harmful/
To summarize:
A man-in-the-middle attack can trivially replace your crypto code with <script> function hash_algorithm(password){ lol_nope_send_it_to_me_instead(password); }</script>
A man-in-the-middle attack is trivial against a page that serves any resource over a non-SSL connection.
Once you have SSL, you're using real crypto anyways.
And to add a corollary of my own:
A successful XSS attack can result in an attacker executing code on your client's browser, even if you're using SSL - so even if you've got every hatch battened down, your browser crypto can still fail if your attacker finds a way to execute any javascript code on someone else's browser.
This renders a lot of RESTful authentication schemes impossible or silly if you're intending to use a JavaScript client. Let's look!
HTTP Basic Auth
First and foremost, HTTP Basic Auth. The simplest of schemes: simply pass a name and password with every request.
This, of course, absolutely requires SSL, because you're passing a Base64 (reversibly) encoded name and password with every request. Anybody listening on the line could extract username and password trivially. Most of the "Basic Auth is insecure" arguments come from a place of "Basic Auth over HTTP" which is an awful idea.
The browser provides baked-in HTTP Basic Auth support, but it is ugly as sin and you probably shouldn't use it for your app. The alternative, though, is to stash username and password in JavaScript.
This is the most RESTful solution. The server requires no knowledge of state whatsoever and authenticates every individual interaction with the user. Some REST enthusiasts (mostly strawmen) insist that maintaining any sort of state is heresy and will froth at the mouth if you think of any other authentication method. There are theoretical benefits to this sort of standards-compliance - it's supported by Apache out of the box - you could store your objects as files in folders protected by .htaccess files if your heart desired!
The problem? You are caching on the client-side a username and password. This gives evil.ru a better crack at it - even the most basic of XSS vulnerabilities could result in the client beaming his username and password to an evil server. You could try to alleviate this risk by hashing and salting the password, but remember: JavaScript Crypto is Hopeless. You could alleviate this risk by leaving it up to the Browser's Basic Auth support, but.. ugly as sin, as mentioned earlier.
HTTP Digest Auth
Is Digest authentication possible with jQuery?
A more "secure" auth, this is a request/response hash challenge. Except JavaScript Crypto is Hopeless, so it only works over SSL and you still have to cache the username and password on the client side, making it more complicated than HTTP Basic Auth but no more secure.
Query Authentication with Additional Signature Parameters.
Another more "secure" auth, where you encrypt your parameters with nonce and timing data (to protect against repeat and timing attacks) and send the. One of the best examples of this is the OAuth 1.0 protocol, which is, as far as I know, a pretty stonking way to implement authentication on a REST server.
https://www.rfc-editor.org/rfc/rfc5849
Oh, but there aren't any OAuth 1.0 clients for JavaScript. Why?
JavaScript Crypto is Hopeless, remember. JavaScript can't participate in OAuth 1.0 without SSL, and you still have to store the client's username and password locally - which puts this in the same category as Digest Auth - it's more complicated than HTTP Basic Auth but it's no more secure.
Token
The user sends a username and password, and in exchange gets a token that can be used to authenticate requests.
This is marginally more secure than HTTP Basic Auth, because as soon as the username/password transaction is complete you can discard the sensitive data. It's also less RESTful, as tokens constitute "state" and make the server implementation more complicated.
SSL Still
The rub though, is that you still have to send that initial username and password to get a token. Sensitive information still touches your compromisable JavaScript.
To protect your user's credentials, you still need to keep attackers out of your JavaScript, and you still need to send a username and password over the wire. SSL Required.
Token Expiry
It's common to enforce token policies like "hey, when this token has been around too long, discard it and make the user authenticate again." or "I'm pretty sure that the only IP address allowed to use this token is XXX.XXX.XXX.XXX". Many of these policies are pretty good ideas.
Firesheeping
However, using a token Without SSL is still vulnerable to an attack called 'sidejacking': http://codebutler.github.io/firesheep/
The attacker doesn't get your user's credentials, but they can still pretend to be your user, which can be pretty bad.
tl;dr: Sending unencrypted tokens over the wire means that attackers can easily nab those tokens and pretend to be your user. FireSheep is a program that makes this very easy.
A Separate, More Secure Zone
The larger the application that you're running, the harder it is to absolutely ensure that they won't be able to inject some code that changes how you process sensitive data. Do you absolutely trust your CDN? Your advertisers? Your own code base?
Common for credit card details and less common for username and password - some implementers keep 'sensitive data entry' on a separate page from the rest of their application, a page that can be tightly controlled and locked down as best as possible, preferably one that is difficult to phish users with.
Cookie (just means Token)
It is possible (and common) to put the authentication token in a cookie. This doesn't change any of the properties of auth with the token, it's more of a convenience thing. All of the previous arguments still apply.
Session (still just means Token)
Session Auth is just Token authentication, but with a few differences that make it seem like a slightly different thing:
Users start with an unauthenticated token.
The backend maintains a 'state' object that is tied to a user's token.
The token is provided in a cookie.
The application environment abstracts the details away from you.
Aside from that, though, it's no different from Token Auth, really.
This wanders even further from a RESTful implementation - with state objects you're going further and further down the path of plain ol' RPC on a stateful server.
OAuth 2.0
OAuth 2.0 looks at the problem of "How does Software A give Software B access to User X's data without Software B having access to User X's login credentials."
The implementation is very much just a standard way for a user to get a token, and then for a third party service to go "yep, this user and this token match, and you can get some of their data from us now."
Fundamentally, though, OAuth 2.0 is just a token protocol. It exhibits the same properties as other token protocols - you still need SSL to protect those tokens - it just changes up how those tokens are generated.
There are two ways that OAuth 2.0 can help you:
Providing Authentication/Information to Others
Getting Authentication/Information from Others
But when it comes down to it, you're just... using tokens.
Back to your question
So, the question that you're asking is "should I store my token in a cookie and have my environment's automatic session management take care of the details, or should I store my token in Javascript and handle those details myself?"
And the answer is: do whatever makes you happy.
The thing about automatic session management, though, is that there's a lot of magic happening behind the scenes for you. Often it's nicer to be in control of those details yourself.
I am 21 so SSL is yes
The other answer is: Use https for everything or brigands will steal your users' passwords and tokens.
You can increase security in authentication process by using JWT (JSON Web Tokens) and SSL/HTTPS.
The Basic Auth / Session ID can be stolen via:
MITM attack (Man-In-The-Middle) - without SSL/HTTPS
An intruder gaining access to a user's computer
XSS
By using JWT you're encrypting the user's authentication details and storing in the client, and sending it along with every request to the API, where the server/API validates the token. It can't be decrypted/read without the private key (which the server/API stores secretly) Read update.
The new (more secure) flow would be:
Login
User logs in and sends login credentials to API (over SSL/HTTPS)
API receives login credentials
If valid:
Register a new session in the database Read update
Encrypt User ID, Session ID, IP address, timestamp, etc. in a JWT with a private key.
API sends the JWT token back to the client (over SSL/HTTPS)
Client receives the JWT token and stores in localStorage/cookie
Every request to API
User sends a HTTP request to API (over SSL/HTTPS) with the stored JWT token in the HTTP header
API reads HTTP header and decrypts JWT token with its private key
API validates the JWT token, matches the IP address from the HTTP request with the one in the JWT token and checks if session has expired
If valid:
Return response with requested content
If invalid:
Throw exception (403 / 401)
Flag intrusion in the system
Send a warning email to the user.
Updated 30.07.15:
JWT payload/claims can actually be read without the private key (secret) and it's not secure to store it in localStorage. I'm sorry about these false statements. However they seem to be working on a JWE standard (JSON Web Encryption).
I implemented this by storing claims (userID, exp) in a JWT, signed it with a private key (secret) the API/backend only knows about and stored it as a secure HttpOnly cookie on the client. That way it cannot be read via XSS and cannot be manipulated, otherwise the JWT fails signature verification. Also by using a secure HttpOnly cookie, you're making sure that the cookie is sent only via HTTP requests (not accessible to script) and only sent via secure connection (HTTPS).
Updated 17.07.16:
JWTs are by nature stateless. That means they invalidate/expire themselves. By adding the SessionID in the token's claims you're making it stateful, because its validity doesn't now only depend on signature verification and expiry date, it also depends on the session state on the server. However the upside is you can invalidate tokens/sessions easily, which you couldn't before with stateless JWTs.
I would go for the second, the token system.
Did you know about ember-auth or ember-simple-auth? They both use the token based system, like ember-simple-auth states:
A lightweight and unobtrusive library for implementing token based
authentication in Ember.js applications.
http://ember-simple-auth.simplabs.com
They have session management, and are easy to plug into existing projects too.
There is also an Ember App Kit example version of ember-simple-auth: Working example of ember-app-kit using ember-simple-auth for OAuth2 authentication.

How the server verifies the JWT client?

We know if the JWT content is modified, the server simply finds it using the signature. But what if the JWT is stolen and used by a hacker without modifying it? How the server verifies the JWT comes from the correct client?
I know the user id is inside the JWT, but still I am not sure how the server can securely makes sure the JWT comes from the client who is having the same user id that is in the JWT.
A hacker can't and won't modify the token. As the token itself is safe and is fully trusted. This is the nature of a JWT. So without additional information you can't tell the difference.
You can however design a strategy to protect your resource.
Most important is to prevent a hacker from 'stealing' the token. It helps when you send the token always over a secured line and store information (like tokens) in a secured place.
Make it not worthwhile to hack the token. Use short-lived tokens, like five minutes or less. When a hacker gets hold of a token it will only give access for a short period. This is the 'acceptable loss'. On the other hand the hacker is discouraged as the effort is not worth the result.
Detect suspicious behaviour. Like hundred hits per second or varying ip addresses with the same token.
When using a refresh token, check the requesting party. Is the Ip address within range? Use one-time only refresh tokens. Only allow refresh tokens when the client can keep a secret. Use expiration on refresh tokens, this will force the user to login every now and then.
And add additional information to the claims in the token. Like the ip address, used agent, etc. These are quick checks.
When the ip address is not the same as in the claim, do not accept the token. The app will need to send a refresh token to obtain a new access token. The hacker can't do this without a refresh token.
Keep track of succesful login ip addresses. For a known ip address the token can be refreshed. For an unkown ip address (a possible hacker, or unknown changed wifi network), invalidate the refresh token. That way the user is forced to login again.
As an additional security measure contact the user (send an e-mail like Google does) when there was something different. In that case the user can revoke the refresh token.

How are cookies different from JWT and why are they considered worse than JWT?

I have been reading around using tokens for authentication. I, however, fail to understand how tokens (JWT) are different from cookies. Both will store the user info (as claims in tokens), have persistence defined and will be sent with each client request to the server.
Few questions that come to mind, in addition to the above -
Are JWT tokens not prone to Man in the Middle attack? If someone steals a token (on an unencrypted channel), can't they pose as the original user? (unless we add the user's IP etc in the claims)
I've read a few rants that cookies are not good for new-age mobile apps and tokens are the answer. Why?
Why are tokens considered more secure than cookies? What makes them more invulnerable to attacks?
Does a token needs to be issued by the server only, or one can receive a token from another OAuth provider and customize (add/remove claims) and reuse it?
Performance wise, cookies are 'bad' as they have a size limitation, that is why they just store the session ID (typically) with session data in server. This reduces cookie size. But JWT, the whole token needs to be sent, so if the token contains the session data as claims, then we'll be essentially sending this ever increasing token every time. If am getting that correct, isn't that bad performance of JWT as compared to Cookies?
Thanks
Are JWT tokens not prone to Man in the Middle attack?
Yes, you should use HTTPS to ensure that no one can see the JWT in the HTTP request headers. If someone gets the token, they can pose as the original user. The same thing is possible with cookies.
I've read a few rants that cookies are not good for new-age mobile apps and tokens are the answer. Why?
Most mobile apps don't use browsers to make HTTP requests. Browsers make dealing w/cookies seamless for web developers. For mobile developers, using JWT's can be less cumbersome than dealing w/cookies.
Why are tokens considered more secure than cookies? What makes them more invulnerable to attacks?
Tokens aren't necessarily more secure than cookies (a cookie could be signed, just like a JWT). The security benefits come from not being exposed to exploits which trick the browser into inadvertently using the cookies (CSRF attacks).
Does a token needs to be issued by the server only, or one can receive a token from another OAuth provider and customize (add/remove claims) and reuse it?
A JWT is signed with a secret that only the server/organization that generated it should know. So only servers that know the secret can verify the token is valid. While the server that generates the token doesn't have to be the same one that validates it, it doesn't make sense for you to customize and re-use someone else's token.
Reference

Security of Token Based Authentication

My understanding of token based authentication is that upon authentication (perhaps over ssl), a token is passed to the user for cheap user verification on the fly. One implementation of this would be to generate a cookie that is passed to the user for session management.
But, my understanding is that token based auth (at least through cookies) is susceptible to man in the middle attacks like firesheep.
Are there other methods of implementation that skirt this major security issue, or do I have a fundamental misunderstanding of tba?
Your understanding is good. Fundamentally, in terms of how the application sees it, a token may as well be a username and password. If someone has the token, they can authenticate themselves to your application. The main purpose in the case of a http cookie is to avoid leaking the username and password should someone obtain the cookie by means of a cross-site scripting vulnerability (XSS) or otherwise. Yes, given the right circumstances they can "replay" this token to the application as a "man in the middle" but they shouldn't be able to figure out the username/password pairing from it but again this is not guaranteed if the token generating algorithm is weak, say, like if you decided to BASE64 encode the username and password concatenated together and use that as the value.
Typically you keep the token -> user mapping secure on the server side. So ultimately your security is all based around keeping the token safe and ensuring that its lifetime is controlled (e.g. it expires and/or is only valid when given to you from the same IP as that used by the original provider of the credentials - again, just an example)
Hope this helps,
-Oisin