I have three servers:
- authorization server
- api server
- frontend server
Authorization server returns JWT self-contained access token (+refresh token). JWTs aren't stored anywhere in Authorization Server.
I want to secure JWT with asymmetric encryption and i am not sure if i my idea is correct.
Let me describe flow:
After login from Fronted Server, Authorization server gets user credentials, then generates JWT token and encode it with public key.
Fronted Server receives encrypted JWT token and client (web browser) saves it as HTTP-Only cookie.
Client sends request to secured resource, so FrontEnd based on obtained encoded JWT token, requests for secured data API Server.
API Server based on secured JWT and private key decrypt value and checks if user has enough access to perform operation.
If JWT token expires, front end sends request to Authorization Server with refresh token to get new JWT token.
In this case Authorization Server and API Server would need to store private key for decryption.
Is this solution secure enough? Is it OK to store the same private key in two servers?
Do you know if flow is correct? Or maybe data flow should be different?
I want to secure JWT with asymmetric encryption and i am not sure if i my idea is correct.
In general, data encryption is a good idea. Especially if you transport sensitive data.
Let me describe flow
[…]
In this case Authorization Server and API Server would need to store private key for decryption. Is this solution secure enough? Is it OK to store the same private key in two servers? Do you know if flow is correct? Or maybe data flow should be different?
If I understand correctly your flow, the token is encrypted on AS (Authorization Server) side and decrypted on API server side. Therefore you want to prevent the client from reading its content.
This flow is absolutely fine. Both the AS and the API server will have the shared secret so that they will be able to encrypt or decrypt the token.
I suggest you to read more about JWE (encrypted JWT) and the associated RFC7516. This specification describes a standard way to encrypt tokens.
Depending on the programming language you use, you may found libraries that support JWE. https://jwt.io/ lists lot of libraries and some of these support more than signed tokens (JWS). For example com.nimbusds/nimbus-jose-jwt (Java) or web-token/jwt-framework (PHP).
A possible flow could be as follow. Please not that it will undoubtedly create complexity in your AS and API server code. So before you implement it, you should make sure it is necessary to encrypt your tokens! (e.g. you transport sensitive data)
The AS sign the token with its private key (e.g. algorithm RSxxx, PSxxx or ESxxx) => JWS
The JWS is encrypted as per the RFC7516 with an asymmetric encryption algorithm (e.g. AxxxKW or AxxxGCMKW) and the shared key => Nested token (a JWS in a JWE)
The Nested token is sent to the client
The client cannot read the content, but the token can be sent to the API server as usual
The API server decrypts the JWE with the shared key to get the JWS
The API server verifies the JWS with the AS public key
Related
I am creating a Flutter app which uses Node Js server API. For the authorization I decided to use JWT with private/public keys. Communication between Server and mobile client uses HTTPS. Flutter app stores the token in a keychain (ios) or a keystore (android). My question is related to the need of the additional security measures implementations. I am wondering if the following points are required:
Verification of the server responses with public key by checking the token to identify the server
Verification of the client requests with the private key on the server side (client signs the token with public key)
Are these really needed in order to avoid man in the middle attacs? My objection is related to the performance related to signing/verifying tokens for each communication.
Thank you
I've used JWT our mobile apps for security and these apps had taken the security test(3.party company). The company says: secret your stored token or any keys.
And we know doesn't enough just JWT security. We wrote a custom encrypted algorithm to hide JWT (like sha-1) so we encrypt JWT to this.( you must write encryption code client-side & backend side)
Normal jwt : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
After encriypt: xxs{4=-23dasdxe3 (example)
We passed the security rules with this solution.
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.
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.
I'm reading about JWT and I'm confused about why there's a signature:
JWT site
What is the purpose of the signature if it's just a hashed version of the header and payload?
Also, why not just use oAuth? Or whatever 2 factor auth uses?
The purpose of Oauth2 and JWT is different, so it is not possible to compare them directly
JWT is a compact way of representing claims to be transferred between two parties (JSON with digital signature).
OAuth2 is an authorization framework used by third party applications (websites, mobile apps) to access on resources on a resource server, without exposing user password. OAuth2 can use JWT as the exchanged token
JWT is self contained and does not need server sessions . The digital signature is performed with server private key and protects the content. Any alteration of the header, the payload or the signature will be detected by the server and reject the token.
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.