Decoding JWT tokens without the secret - jwt

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/

Related

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

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

Is payload tampering possible when making request to resource server with JWT?

As we know the JWT is signed with secret key so the token itself can not be tampered but the payload we send to resource server with JWT can be plain text/json/xml/query string so how can we protect payload from tampering?
The signature is exactly what prevents the payload from being tampered. The payload cannot be modified without invalidating the signature.
Let me also clarify that JSON Web Token (JWT) is an open standard that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. JWT is a generic name for the following types of token:
JSON Web Signature (JWS): The payload is encoded and signed so the integrity of the claims can be verified.
JSON Web Encryption (JWE): They payload is encrypted so the claims are hidden from other parties.
If you intend to prevent the payload from being tampered, then use JWS. If you want to hide the payload from other parties, then use JWE.
tl;dr To keep your payload (and token in general) safe all you need to do is use a strong secret and signing algorithm and verify the signature before trusting the contents.
JWT is signed with secret key, but the payload can be plain text/json/xml/query
You seem to be confused on what a JWT is. There is no separate JWT and payload, one is part of the other. JWT consists of Header, Payload and Signature. Signature is created over both - the header and payload parts and additionally your secret key. This means that if either piece is tampered with the signature can not be verified.
From JWT introduction:
Do note that for signed tokens this information [header and payload], though protected against tampering, is readable by anyone. Do not put secret information in the payload or header elements of a JWT unless it is encrypted.
To see for yourself you can use JWT debugger. When you change the decoded header or payload their base64 values change and therefore the signature changes with them. If you were to copy-paste the old signature value into new JWT it will show invalid signature error.
Unfortunately, there is no standard way to ensure that the request body has not been tampered during the transport using http headers.
AFAIK and among all the authentication schemes listed by the IANA, none of them have such feature.
However if your project is limited to a few number of clients or if you provide a detailed documentation, you can implement your own request signature mechanism.
I recommend you to read more about the following initiatives. Theses ones could help you in that implementation:
AWS Signature Version 4: certainly the most interesting resource. It also allows POST (maybe PUT and PATCH) requests to be signed
Hawk: same as above. Not widely used though.
OAuth 2.0 Message Authentication Code (MAC) Tokens. This one is abandonned and do not ensure the body has not been modified.
JWT by itself is not tamper proof. To make it secure, it must be transformed with these 2 steps:
Sign with Sender's private key
Encrypt with Receiver's public key
Signing with sender's private key ensures that any unauthorized modification of token can be detected.
Encrypting with Receiver's public key will ensure that the token achieves secrecy and only the intended receiver can see the token content.
JWT signed by Sender is called JWS.
Encrypted JWS is called JWE.
More information:
https://dzone.com/articles/securing-spring-boot-microservices-with-json-web-t

PayPal id_token verification

I'm implementing "Log In with PayPal" functionality. Should be fairly simple, but unfortunately PayPal lacks documentation (only some basic things are described).
I get authorization_code using "Log In with PayPal" widget. Than I make a request to https://api.sandbox.paypal.com/v1/identity/openidconnect/tokenservice and get JSON with access_token, refresh_token and id_token. I want to get unique user identifier, so I decode id_token, but I'm not able to verify signature of my id_token. Id_token header contains {"alg": "HS256", "typ": "JWT"}.
What secret should I use? Tried my app's secret (same that I use to access tokenservice), but it didn't work (using https://jwt.io/ debugger).
PayPal is not OpenID connect compliant. This answer explains the reasons.
PayPal expose a configuration endpoint - https://www.paypalobjects.com/.well-known/openid-configuration.It only support HS256 and does not support or mention about RS256. This could be due to a proprietary validation for ID token. For example a id token used as a bearer token.
Alternative solution would be to invoke userinfo endpoint as described by document. This endpoint can be invoked using access token and document says it would return the user_id
user_id - identifier for the end-user at the issuer.
Although it seems that user_id found in the userinfo is different from sub that could be extracted from id_token.
How to find public keys if signing algorithm is RS256
ID token is a JWT. As you have found out, it contains a JWS signature which acts as a MAC.
This signature is a signed using a private key. The receiver of the id token can validate the token using the public key. To find the public key, openid conenct specify a discovery document. You can read more about this from the specification
In the discovery document, you get a special endpoint to infer the configuration .well-known/openid-configuration. And one of the must have metadata of the configuration response is jwk_url
jwks_uri
REQUIRED. URL of the OP's JSON Web Key Set [JWK] document. This
contains the signing key(s) the RP uses to validate signatures from
the OP. The JWK Set MAY also contain the Server's encryption key(s),
which are used by RPs to encrypt requests to the Server. When both
signing and encryption keys are made available, a use (Key Use)
parameter value is REQUIRED for all keys in the referenced JWK Set to
indicate each key's intended usage. Although some algorithms allow the
same key to be used for both signatures and encryption, doing so is
NOT RECOMMENDED, as it is less secure. The JWK x5c parameter MAY be
used to provide X.509 representations of keys provided. When used, the
bare key values MUST still be present and MUST match those in the
certificate.

How can JWT be verified outside the authorization server

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).

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.