JWT Token Invalid Signature [duplicate] - jwt

This question already has an answer here:
PHP JWT Token Invalid Signature
(1 answer)
Closed 5 years ago.
I am using JWT in my application for login authentication process.
To generate the token I am using:
Jwts.builder().setSubject(username).signWith(SignatureAlgorithm.HS512, MacProvider.generateKey()).compact();
Generated Token:
eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJlaG91c2VAZGV2ZXJldXgub3JnIn0.5SX-aU-p_RlfC3CZa-YXnQu_YR7RsG2Xfim3LOmlqxjAZrIyZiz0fYZwViHr113ms8TNvngcJcV07U4hK-RBZQ
When I decode this token in jwt.io debugger it tells me an invalid Signature. I am not able to find the reason of this failure as I can see the username in the payload which i am using to authenticate. Could anybody point me the issue? Do I need to change anything in the code?

MacProvider.generateKey() is generating a new random signing you key each time you use it. You need to generate it once and store it. The key is used to sign and verify the token.
If you do not store the key you wil not be able to verify the token, which is exactly the problem with jwt.io. You must provide the signing key. In your case, using a random key that can contain non representble characters (it is possible to use a passphrase too, but not recommended), encode it to base64. Then mark the check in jwt.io to verify the token
Key key =MacProvider.generateKey();
String keyB64 = javax.xml.DataTypeConverter.printBase64Binary(key.getEncoded());

Related

Jwt.io self populating the signature

I am very new to jwt and signature validation. I had a very basic query.
I am generating a token from MSAL(AAD).
When I use the token in jwt.io, I can see that it automatically populates the secret key and marks the signature as verified. How does jwt.io know about this?
From generating token point of view, I didn't mention anywhere explicitly to generate the token with any secret.
You don't show the details of your token here (which is ok), but I assume the token has a kid and maybe also a jku in the header.
The kidis the Key Id, and the jku the JSON Web Key Set URL.
Under that URL (you can paste it to your browser to see) you can find a set of JWKs (JSON Web Keys), basically a collection of public keys in a special format. In case of tokens issued by AAD you the JWKS_URI can be found on https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration.
JWT.io can read this information and find the key with the given kid and verify the token based on that.
This Q/A explains the verification of JWTs issued by AAD in more detail.

What is a secret key in JWT

I am unable to clearly grasp how JWT works, esp. the signature part.
Once a client submits correct username and password, the authentication server creates a JWT token consisting of header, payload/claims and signature.
Question 1 - Is signature some secret key (not the user's password) which only the authentication server knows (sort of a private key of the server)?
Question 2 - Say I am using a separate application server and authentication server, on receiving JWT from client, would the application server send the JWT to authentication server to get it validated? I suppose the application server cannot validate a JWT token as it doesn't know the secret key used to sign the header and payload.
Question 3 - I took the following JWT and pasted it on jwt.io. I see the message Signature Verified. How does jwt.io know that the signature is correct as it doesn't know the secret key.
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxLS9tSjVsVTNYc09QWCt2VitpaGZRMWlCUDVjUTROQm1hNDluOE9rS1FFSnEzTDFNOTl2VW9iQ1ZLUHVYMmdlWWhYaHJQM0t3bHY4SE1RaHNGdnFjbllIeGxGSHM9IiwiaXNzIjoicGxheS1zaWxob3VldHRlIiwiZXhwIjoxNTI2MjgxMDU1LCJpYXQiOjE1MjYyMzc4NTUsImp0aSI6IjhmOGM3YTVmYWRkNTE5MjUxNzQ5NGE4N2Q1ODcxZjJjZGUxZDkzMDdkOTY1MThjNjg2NzExOTc1YjU3M2I5NDBlZWU2NGY0NDUwYzcxODI3NGZmNzU1MmE2Y2JlNTVmZmZhMWI1ZjA3ZWZlOWVkNTE0Y2Y4YTViOTZlM2ExYjI0ODRmYTI5NjZiYjA0ODlmODIwZjMyMzM5YWVhNjM3NWRkZmU4ZDE4N2E2NzBjMzg0ODgwZGIyMzQ1ZTFkMzRkYWNjZmY2MTdkMDY1NzU3YmEwZTQzNDg4YWFhZmZmNDNjYWZlZGY0OTFlODU1YTA0NWM0NmJjNDY4NGYzODlmY2YifQ.GwN6TSNd426xpc3Y02eRXHbrmSr_61MMBqrmx66Ofqs
Question 1 - Is signature some secret key (not the user's password) which only the authentication server knows (sort of a private key of the server)?
No, the electronic signature is a mathematical computation applied to the payload of the JWT using a secret key. The purpose is to ensure that the message has not been altered and to recognize the signer to validate the JWT
Question 2 - Say I am using a separate application server and authentication server, on receiving JWT from client, would the application server send the JWT to authentication server to get it validated? I suppose the application server cannot validate a JWT token as it doesn't know the secret key used to sign the header and payload.
Not necessarily. If a symmetric key (HMAC) is used, the signature and verification key is the same. In that case the Authorization server must know the secret key or send the token to verify. However, if an asymmetric key (RSA, ECDSA) is used, the signature key is different from the verification key. The authorization server can have a copy of the public key safely
Question 3 - I took the following JWT and pasted it on jwt.io. I see the message Signature Verified. How does jwt.io know that the signature is correct as it doesn't know the secret key.
jwt.io or anyone who wants to verify the token needs the secret key. Note that if you copy-and-paste the token in jwt.io, the signature is not verified, but if you change the secret key, the editor changes automatically the signature creating a new token at the time
Signature is just hashing using secret key generated by authentication server, using algorithm specified in header, a combination of your header, payload, and secret
Only the authentication and/or application server knows that secret. JWT is encoded and signed, but not encrypted. to understand difference between Sign/Hash and Encryption, check this
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
Signature just verifies or validates whether the message was already hashed before using the same kind of algorithm specified in the header with the secret that is known only by server.
To understand how it works in authenitcation, here is a flow:
User sign in, you send user/pass to server in an encrypted way over https
Server validates username/pass from your db
Server generates a JWT and send it back to you, The signature is used here to verify the message wasn't changed along the way.
Server saves the JWT somewhere in a session store.
Later, user requests a server (send JWT everytime it needs something from the server)
Server validates it using same type of hash algorithm that is in the header and secret stored in there.
Server checks whether it is already there in session store.
Servers authorizes and grants you for the request.
I would recommend you read this article that is more descriptive to better understand how it works.

JWT Tokens global + private secret

I'm reading about JWT Tokens recently, and I've got a moment; I've got an idea which seems to be great in my head, but I suspect it's not so great when it comes to the end.
I see people are encrypting tokens with single key for global purpose. What if I'd generate completely new key for every user, join two strings afterwards and use the output for encrypting the token? This would deal with need of creating blacklists for users that shouldn't be having access anymore and so on. What I am missing? Because I'm sure somebody had similar idea to mine, and for some reason it's not widely used. Where am I lost?
JWT are signed (not encrypted) with the private key of the issuer, usually the server. A digital signature identifies the signer and protects the content from alterations.
If you modify the payload of a valid JWT, the signature or create a fake token, the server just will reject it. This is why the server does not need a list of issued tokens, because it can verify cryptographically if a token is trusted
You could create a different key for each user, but is not necessary, because you want to proof that the token has issued by the server to trust in the data contained in payload do just one key is needed

Do we need to validate JSON Web Token at client/consumer?

I am studying a bit about JSON Web Token. I understood that header+claims get signed by a secret key and the encoded result gets concatenated to "header.claims.signature" and finally sent back to client.
I have some basic doubts:
Do we need to validate the token at client/consumer (once it receives from server, for sake of authenticity)? Is it a standard at all or not necessary? Any example for reference on this?
If the client needs to validate the token, I guess it has to know the secret key to decrypt/decode. Is there any other way to ask client validate on its own without sharing server's secret key?
If client knows the secret key, I guess it can create its own token too. If such is the case, do the server need to accept such tokens (or is application/business dependent?)
Do we need to validate the token at client/consumer
On client side you usually don't validate the token. Treat it just as an opaque token. Keep it safe and use it when making requests to the server.
If the client needs to validate the token, I guess it has to know the secret key to decrypt/decode.
As mentioned above, the client doesn't need to validate the token.
In any cases in which the authentication server (the instance that authenticates the user and issues the token) and the resource server (the instance that owns a proteceted resource and requires a token for authorization) are not the same, signing and validation of the token is usually done with asymmetric algorithms like RS256 in which the private key is used to sign the token and only known by the authentication server, and the public key is used to verify the signature.
If client knows the secret key, I guess it can create its own token too. If such is the case, do the server need to accept such tokens (or is application/business dependent?)
That's why a client should not know the secret key.
When symmetric key algorithms (e.g. HS256), in which the same key is used to sign and verify a signature are used, you can't allow the client to know the key, as it could be abused to create a fake token. Then JWT would be pointless. For asymmetric keys, there's no risk if the client knows the public key.

JWT Verification Failing

I am new to JWT tokens. I am able to create and verify JWT in Java (using JJWT) and even online using following link http://kjur.github.io/jsjws/tool_jwt.html.
BUT when I try to create JWT using one source and try to validate using another, it always fail. I couldn't successfully generate and validate JWT using 2 different sources. I even tried using http://jwt.io
Can someone help me understand what might be wrong? I believe it should be possible to create JWT using one library and validate using another library considering you are using correct sign algo and secret key.
The key input at http://kjur.github.io/jsjws/tool_jwt.html accepts hex-encoded values. The default secret 616161 actually decodes to aaa. Verifying the generated token at http://jwt.io/ using aaa as the secret works.
One aspect of JWT that can confuse is that it does not encrypt the data.
It is possible to extract the contents of a JWT including all the fields. The signing of it however allows us to validate that the token was generated/signed with a particular secret and it is this that is used to validate or authenticate.
If that is not the issue then it could well be just the tool/library key encoding as suggested by #frasertweedale - care needs to be taken to encode all the source fields appropriately.