How does the server validate the JWT token?
Where is it stored?
How does the token expire after specific days?
On the client side, I store the token and send it to each query. But what's happening on the server side?
It could do with some entry that works
I'm not a JWT expert, so if some of what I write is wrong, I'm very happy to be corrected.
1) When distributing the JWT, the server will sign it using a private key. The private key is top secret, and must be stored securely on the server. This signature can then be verified using a public key, which confirms that this token was indeed signed by the server (using the top secret private key). The public key is not necessarily secret and can be widely distributed to anyone who needs to verify that the token was signed by that server.
2) The JWT does not really need to be stored anywhere on the server, as the server can verify that it's a valid token whenever it receives it. As the server is also likely to generate JWT, some servers will use a cache to store generated and valid JWT to increase performance. So in short, the JWT does not need to be stored by the server.
3) The JWT contains lots of data, including an expiration time (or time when it was created, and duration for how long it's valid). In addition to verifying the token using the public key, the server will discard valid tokens that have expired.
4) Before processing your request, the server will at minimum use the public key to verify that the token is genuine and check the expiration time. If it passes those tests, the server might also do additional checks with the data stored in the JWT before processing your request. These checks might include checking if your user ID has permission to access the data you are trying to access, check if you're located in a country to has access to the data, and so on. It can change wildly from a case to case basis.
It's a little bit of a broad question. I'll try to answer some specific points though.
How does the server validate the JWT token?
JWTs are typically digitally signed.
The token server signs the token using either symmetric or asymmetric cryptography.
The resource server validates the token by checking the signature against the symmetric key or public key.
Where is it stored?
This is up to the client.
In the case of a single page application, the client can store the token in local or session storage.
How does the token expire after specific days?
A JWT always has an expiry time, set in the token when it is created.
And since the token is signed, this time cannot be changed by someone without the key.
The resource server must check the expiry time after validating the signature.
Trying to understand the 2-legged client credentials scheme in OAuth2. Some people state that JWT is great format for Access Token because it is self-contained and resource server doesn't need to verify the token from the authorization server (STS). But how is this done? The only way I see the resource server could itself validate the JWT is by storing a public key on the server, which is used to verify the signature.
When using a JWT as an access token, the Resource Server doesn't need to call out to the Authorization Server to verify it. Indeed the Resource Server will need to store the public key of the Authorization Server to do so. Obtaining that public key is an out-of-band process.
Verification of a JWT consists of checking the signature plus some additional checks on claims embedded in the token e.g. timestamps (iat, exp, nbf) and identifiers (aud).
The advantage of JWT over other forms of signed data/tokens is that JWTS are standardized and flexible wrt. cryptography used by them which makes it possible to use standard libraries to create/verify them instead of having to write custom code.
Looks like jwt token really contains necessary info inside itself and the correctness of this data ensured via cryptographic signatures. Is there any reasons to persist this token somewhere on the server or "issue and forget" policy should be fine?
No, there is no reason to store JWT tokens on the server side. You can validate the token by checking signature. No need to talk to any server.
If the tokens have a short time to live, there's no need to revoke the access token itself.
Refresh tokens on the other hand are stored on the authorization server, have a long time to live and can be revoked.
When token based authantication is compared to traditional server authantication, it is said that: traditional method keeps login info in memory on server side, but in token based authantication server keeps nothing. Information about logged in user is stored in token itself.
However, I didn't get one point here. If server doesn't store anything, how does server validate the token? I think it should store the secret key to decrypt the token and then validate.
If so, where is it stored? If not what poin did I miss?
The server issuing the token, digitally signs the token with a private key.
The service consuming the token only needs the public key to validate the token. It can download the public key from the issuing server on startup or first use. After that, it does not need to communicate with the issuing server to validate tokens. If the signature is valid, the service trusts the contents of the token.
For example, look at the "jwt", it uses "ssh" keys
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.