How can JWT be verified outside the authorization server - jwt

Recently, I'm trying to implement an OAuth2.0 server using JSON Web Token (JWT) as access token. I'm very confused about the self-contained feature of JWT. I notice that JWT can be verified anywhere, not mandatorily in authorization server because it is self-contained. How does this feature work? What claims should be included in JWT in order to realize self-contained feature?
Another question is that, if JWT is stateless, it means the server should not store the JWT. Then how is the JWT verified? Can't it be easily forged?
I'm the rookie in this field, I wish someone could help me out:)

JWT contains claims that can be signed, encrypted or both.
These operations are performed using cryptographic keys. Keys can be symmetric (e.g. octet keys) are Asymmetric (e.g. private/public key pairs such as RSA or EC keys).
When you want to verify a JWT (i.e. a JWS), you have to perform the following steps:
Check the header (algorithm is supported, critical claims are in the payload and their value are understood).
Check the claims (especially exp, iat, nbf, aud).
Check the signature.
To check the signature, you need the key and, depending on the algorithm, this key can be
The symmetric key
The public key if asymmetric
When you want to allow third party applications to verify your JWT, you will use asymmetric keys and share the public key with the third parties.
As public keys cannot be used to sign, third parties cannot forge a valid token with custom claims.
The way you share the keys is up to you. The common way is to provide an URL where applications will retrieve them (e.g. Google keys at https://www.googleapis.com/oauth2/v3/certs).

Related

What advantage does signing a JWT with RSA have over SHA in the contect of a RESTful API?

I have a backend which exposes a RESTful API which is currently 'free for all' (but uses https).
I now want to add RBAC (role-based access control) and JWT seems the way to go and I read a lot about JWT, but don't see the advantage of using RSA over SHA to sign the token.
Assumption is that the user has authenticated and obtained a key, be it shared or public/private.
Now, it seems to me that in both cases - SHA or RSA HMAC - both parties (client and server) must have the shared key, or their half of the private/public key in the case of RSA. And the server must find that key (in a table or database) based on a claim in the JWT in order to verify the token's signature. Once it has confirmed the purported user in the JWT it will then authorise the request using the configured roles.
So what are the advantages of RSA in that scenario ?
I assume you're talking about RSxxx (e.g. RSA256) and HSxxx (e.g. HS256 (HMAC-SHA256)) algorithms here. The main difference is that HS256 is an symmetric algorithm while RS256 is an asymmetric algorithm. Symmetric algorithms just use one key (or secret) for signing and verifying, whereas asymmetric algorithms use the private key to sign and the public key to verify the token.
If you share the secret used for HS256, everyone knowing the secret could issue or modify and re-sign a token. That would defeat the purpose of the signature if you share the secret with the client. In case of RS256 or any other asymmetric algorithm, only the authentication server knows the private key and anyone who need to verify the token can use the public key to do so. The matching key is usually identified by the KID (Key Id) claim in the header of the token.
But usually, signing and verifying is only done on server side, the client does not need to verify the token and thus does not need to know the key or secret at all. Therefore you can in case of a simple service, when authentication and resource server are the same, still rely on a symmetric algorithms. But once you have one separate authentication server for several resource servers, asymmetric algotrithms should be used.
Thanks for the response, that does help make it clearer.
So basically, for a simple RESTful API, there is no real advantage using RSA over HSA.
Some points that may help others about token-based authentication:
Preamble: the following are all in the context of using SSL.
Firstly, a token is a substitute for username/password credentials: if a client has a token, it is equivalent to having username/password. It took me a while to figure that out. A bit like using a badge at a corporate printer: instead of entering username and password you just place your badge (the token) on the printer and it knows who you are and prints your document.
However, tokens make using an API much simpler because
the client simply adds its token to the http header,
the server only verifies the token,
neither have to deal with authentication flows involving username/pw and managing session cookies.
But the downsides are that
losing the token is like losing the username/password, and
in a complex system involving many components, tokens would have to be shared across all involved backend servers.
Secondly, the client doesn't strictly need to verify the token - it only needs the token - if someone gives you a key to their house or car, you don't typically check the key, you trust the person (maybe sometimes foolishly so) and use it. So a simple random string can serve as a token; the server maintains a simple table correlating tokens to users, no keys involved at all. If a client sends a token that the server doesn't have --> access denied. If it has a matching token --> look up the user that correlates to the token (typically followed by authorisation).
Thirdly, the server typically generates a token either based on trusting the client, or after the client has somehow authenticated, e.g . oauth. Afterwards, the client just sends the token with every request and the server looks it up in its table. However, such server-side tables for random-string tokens may become large and have to be persistent, so either a database or a file is required, and they are typically comparably slow, require maintenance etc, so enter using cryptographic signatures and jwt:
Fourthly, tokens with signature:
the server signs the token and sends it to the client - but the server does not have to store it, also no session cookies as described above
the client stores the token securely and sends it with every subsequent request (just like with a random string token)
the server receives the request, calculates the signature of the jwt, and compares it with the signature of the token sent by the client. Note that there is no file or DB lookup, only computing the signature again and comparing it with the signature sent by the client. If the signatures match then the token must be the same as the one the server issued and hence the jwt header and payload are also the same as issued by the server
the server now interprets the payload, esp. the user (and typically performs authorisation)
So, using jwt means the server does NOT need
a database or file with user names and tokens
to save tokens
to maintain session cookies
It only needs to create and compare a signature. And for that it needs a cryptographic key. This can be a symmetric key for a simple API or an asymmetric key for more complex systems where public keys must be shared.
Hope this helps some other tortured souls who grappled with this topic.

How can I configure Keycloak to use HMAC algorithm as default instead of RSA?

I have created a new realm in Keycloak and in the admin tab Keys -> Active I can see three entries: RSA, HMAC, AES.
Whenever a JWT token is generated the signature algorithm used is RSA. How can I use HMAC instead?
I had the same question and found the following answers:
The latest documentation says that only rsa is supported for access tokens.
(http://www.keycloak.org/docs/3.3/server_admin/topics/realms/keys.html)
There is the plan to sign refresh tokens with hmac. Look at this user mailing list entry for more details:
"It is not great to sign accessTokens and idTokens by HMAC anyway since the
applications will need to have access to realm signing key. As it is
symmetric stuff. This can be security hole as then the application can
generate and sign tokens by itself. Hence we rather rely on the
asymetric cryptography - Keycloak signs tokens with private key and
application has just public key to verify signatures."
http://lists.jboss.org/pipermail/keycloak-user/2017-May/010809.html
Here is the JIRA for it:
https://issues.jboss.org/browse/KEYCLOAK-4623 and internally
https://issues.jboss.org/browse/KEYCLOAK-4622
In Keycloak 20.0.3 you need to go to "Tokens" tab and choose HS256 algorithm:

Create JWT on implementation A and verify on implementation B - is that possible?

more specific: can I use jwt .net implementation to create a token and use jwt node.js implementation to verify the token?
The implementation details does not affect to the format or content of JWT, so you can perfectly use .net (A) to generate and node.js (B)to verify.
For B to be able to verify the token, use a RSA asymmetric key pair, public and private. A signs with the private key and B verifiew with the public.
It would be possible to share a HMAC symmetric key between A and B. But then it is needed to consider the security issues of having the key in both systems and how to synchronize them.

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?

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.