JWT : Multiple public keys to create a token and decode using one private keys - rsa

I have a JWT implementation which accessed by multiple clients. In the sense multiple client are sending me JWT token and they are creating the JWT token using the RSA public key I have shared among them. And I am decoding the JWT token using the RSA private key.
But now due to few security reasons I need to send them different public keys and will get the JWT token and I will decode it using one private key I have.
In short how I will generate multiple public keys and single private keys or any similar approach.

(...) send them different public keys and (...) decode it using one private key I have.
As far as I know a RSA private key can only have one public key.
But now due to few security reasons I need to send them different public keys (...)
Are they still "public" if you have to send different public key to each client ?
If I well understand your issue, I would recommend to switch for a PKI with certificates (like X.509) where you are the authority.
The flow would be:
The client generate a private key
The client create a CSR
The client send you the CSR
You generate a cert with your CA base on the CSR
You send back the CRT
The client use its private key to sign the JWT
The client send you the JWT
You check it with your CA
With this solution, you'll get all benefits of client certificate authentication.
If at some point you're not trusting anymore a client you can use a revocation list.
Btw, I never saw this kind of flow... and since I don't know what's you exactly want to achieve, you should read this as an answer of "How can I implement client certificate authentication with JWT ?"

They should each have their own private signing key. They sign the JWT. They then encrypt the JWT with your public key/cert.
You decrypt the jwt with your private key. You then validate the signature of each party using their public key/cert.
This way the JWT is encrypted and only you can access it. It is signed so you can verify the sender

Related

jwt - Django-rest-framework-jwt authentication in microsevices

I am newbie in JSON web token and micro services. I read in an articles that if i share the private, all services can verify user on their own. Then i tried to implement an application to practice.
Basically, I have two services A and B. A is used for authentication. Then, I tried implement a API that required authentication in service B. But when I used a token generated by authentication A in API, 401 status code and "Invalid signature." were returned.
So anyone can explain to me what I did wrong?
"Invalid signature" implies that the secret key that you used to encode the token doesn't match with the secret key you used for decoding it.
Make sure that the secret you are using for encoding and decoding are same.
For more info visit the JWT's site.
First of all the service to service communication only need public key to be shared in case of an asymmetric key pair such as RSA or ECDSA. The public key shared can be used to verify the signature and each service needs to sign JWT using their private key. You have to take care of securing the private key and make public key accessible to other services.
Verifying the user is a completely different use case. The user existence should be checked in database and a password check can be made which is authentication is all about. The JWT can be used to pass the user information along with access right with a signature done by the application using private key so that no one able to generate the same token. NOTICE : Signature is done using private key. In this way you have both authentication and authorisation using JWT.

Public and private keys governance in JWT

I'm trying to better understand JWT and how to properly use it.
In common JWT use cases (like JWT-based authentication or JWT access token in oauth), does it make sense to verify a JWT token client-side? In particular, I'm asking this to better understand the requirements on the public and private keys that are involved in the JWT signing and encryption. If the clients never need to verify the JWT signature than the server does not need to make its public key available. If this is true, I don't even need a full blown X.509 certificate: a bare public/private key pair or a self signed cert would suffice, right?
So all this boils down to the question: what is the right way to deal with asymmetric keys used in JWT? Do I need a public key infrastructure or is a simple private/public key pair enough?
I understand that JWT specs do not cover this: yet I'm curious to know what the common practices are in real JWT usage.
Of course this question has nothing to do with the certs involved in https: I'm just talking about the keys used in JWT signature and encryption.
does it make sense to verify a JWT token client-side?
It makes sense if you use the token payload data to perform an operation in client side, and you need to trust the token. If you use the token for authenticate in a server, then let the server verify the signature.
if this is true, I don't even need a full blown X.509 certificate: a bare public/private key pair or a self signed cert would suffice, right?
Do I need a public key infrastructure or is a simple private/public key pair enough?
You can use either a trusted certificate, a self-signed certificate or simply a RSA keypair. Usually is used an autogenerated keypair. But if you do not plan to verify the signature on client, you can just use a HMAC symmetric key (not assymetric

Understanding RSA signing for JWT

I'm implementing a sign in system with the help of the JWT (JSON Web Token) scheme. Basically, after a user sign in / login, the server signs a JWT and passes it to the client.
The client then returns the token with each request and the server verifies the token before sending back a response.
This is pretty much how you would expect it, but I'm having some problems with the logic of the process. From all the mathematical articles I've read, it seems that RSA signing uses asymmetric keys for signing. As the public key, as its name suggests, is exposed to the client and the private key is kept on the server, it makes sense to sign the JWT with the public key which is sent to the client and verify it on the server side using the private key.
However, on every example and library I see it seems to be the other way around. Any idea as to why it is so? If a JWT is signed with the private key and verified with the public one than whats the point?
First off, apologies, this answer got rather long.
If you use RSA to sign your tokens, and a connecting client is a web browser, the client will never see the RSA keys (public or private). This is because the client presumably doesn't need to verify that the JWT is valid, only the server needs to do that. The client just holds onto the JWT and shows it to the server when asked. Then the server checks to make sure its valid when it see's the token.
So why might you need a public / private key combo for JWT's? Well first off, you don't need to use a public / private key algorithm.
You can sign JWT's with a number of different algorithms, RSA being one of them. Other popular choices for signing your JWT's are ECDSA or HMAC algorithms (the JWT standard supports others as well). HMAC, specifically, is not a public / private key scheme. There's just one key, the key, which is used to both sign and validate the tokens. You can think of this as using the private key for both signing and validating the JWT's. I'm not an expert on this by any means, but here's the conclusions I came to from doing my own research recently:
Using HMAC is nice because it's the fastest option. However, in order to validate the JWT's, you need to give someone the one key that does everything, Sharing this key with someone else means that that person could now also sign tokens and pretend like they're you. If you're building multiple server applications that all need to be able to validate your JWT's, you might not want every application to have the ability to sign tokens as well (different programmers might be maintaining the different applications, sharing the signing ability with more people is a security risk, etc). In this case, it's better to have one, tightly controlled private key (and one app that does the signing) and then share the public key around with other people to give them the ability to validate the tokens. Here, the private key is used for signing the tokens, and the public key is used for validating them. In this case you'd want to choose RSA or ECDSA.
As an example, you might have an ecosystem of apps that all connect to
the same database. To log users in, each app sends folks to one,
dedicated, 'logging in' app. This app has the private key. The other
apps can verify that the person is logged in using the public key (but
they can't log people in).
The research I've done points to RSA being the better option for most JWT apps in this scenario. This is because your app will be, theoretically, validating tokens frequently. RSA is much faster then ECDSA at verification. ECDSA is primarily nice because the keys are smaller in size. This makes it better for HTTPS certificates because you need to send the public key to the client's browser. In the JWT scenario though, the keys are staying on a server so the storage size is n/a and the verification speed is more important.
Conclusion: if you're building a small app without multiple smaller 'micro-service apps' / you're the only developer, probably choose HMAC to encrypt your keys. Otherwise, probably choose RSA. Again though, I'm not an expert, just someone who recently googled this topic, so take this with a grain of salt.
There is a difference between signing/verifying and encrypting/decrypting data but the semantics can be similar.
You sign data with a private key that only controlled sources have so anyone who receives the information can use your public key to validate this information was indeed sent by you and is the same information you intended to send out.
You encrypt data with a public key and decrypt with a private key. This sounds opposite but really follows the same logical concept as signing. If you want to send data between person A and person B, both people have a public/private key pair and they share their public keys with each other when they meet (handshake). A constructs a message for B and encrypts it using B's public key and sends it to B. Now, no one without B's private key can decrypt that message including A - even though they originally sent it.
In terms of JWT, a JWT payload by itself is just Base64 encoded JSON with some standardized fields. The signature allows someone with the public key to validate the information hasn't been altered by someone in the middle. Similar to a checksum but with some extra security based warm fuzzy feelings. The contents of the signed JWT are easily visible (base64 is encoding like unicode or utf-8, not encryption) to the end user and anyone in the middle which is why it is generally frowned upon to send sensitive data in a JWT like passwords or PII.
As others have mentioned, most JWTs contain information not intended for clients but to help facilitate the stateless part of RESTful services. Commonly, a JWT will contain an accountid, userid and often permissions as "claims". An API endpoint can verify the signature and reasonably trust the claims to not be altered by the client. Having the client send the JWT for each request saves the endpoint having to do a lot of database back and forth just to get where they are by simply verifying a signature with a public key.
Additionally, signed JWTs can be encrypted. According to the JWE spec, the payload is encrypted after signing and then decrypted before verifying. The trade off here is that all endpoints must also have the private key to decrypt the JWT but end users won't be able to see the contents of the JWT. I say trade off because in general private keys are meant to be kept secure and a widely distributed private key is just less secure. Security, risk assessment and cost/benefit of encryption is a whole other beast :)
Your suggestion:
it make sense to sign the JWT with the public key which is sent to the
client and verify it on the server side using the private key.
is not correct. Signing is done with the private key of the sender, encryption is done with the public key of the receiver. That is how PKI works in general.

For signing JSON web token, should I re-use the https domain certificate keys or create a new key pair

I am implementing a REST service which has RESTful authentication using jwt based on suggestions from this and this answers.
In constructing the JWT I have decided to sign it using an rsa public private pair rather than hmac for the obvious benefit of being able to keep my signing key fully private because I don't trust the clients that I will need to share the validation key with.
My question is, since normal https server certificates already use rsa keys, would it be acceptable to use that same key pair to sign a JWT token? One advantage I can see is that I will not have to maintain two certificates and mechanisms for sharing the public key with the client are already well established.
PS In case I sign the JWT with a new specific key pair, what is the best way of sending the public key to the client for use in verifying the token?

Decoding JWT tokens without the secret

I created a token with the private key by JWT, but when I try to decode it on http://kjur.github.io/jsjws/tool_jwt.html, I found that the token can be decoded without any key given. So is it correct that the JWT token is just a signing? How to keep the token from decoded without the key?
There are two ways in which a public/private keys can be used by a JWT: signing and encryption.
If you use a private key for signing, it allows for the recipient to identify the sender of the JWT and the integrity of the message but not to hide its contents from others (confidentiality). Note that it would be the sender's private key that is used to sign the JWT and produce a JSON Web Signature (JWS) object. Apparently that applies to the JWT that you're looking at.
When using a public key for encryption it can be used to hide content from anyone but the intended recipient. The result is a JSON Web Encryption object. Note that it would be the public key of the recipient that is used to encrypt the JWT. Apparently that is what you're looking for.
See: http://jose.readthedocs.org/en/latest/