Why should I leave JSON Web Token payload nonencrypted? - json

I'm reading on JWT, there are so many tutorials and so many approaches, it's confusing.
I have couple of questions regarding proper usage of JWTs:
1) I keep seeing inconsistent means of transporting JWTs to and from the server. For example, here: one transport method for retrieving the token (via JSON-encoded object in POST body), another method for submitting it (via HTTP header). Why such inconsistency? Of course, it's up to the implementer to choose the methods, but wouldn't it be good practice at least to be consistent and use either only header or only body?
2) The JWT payload contains the information of state because the server is not maintaining it. It is obvious one should keep the size of the payload as small as possible, because the size of JWT is added to every request and response. Perhaps just a user id and cached permissions. When the client needs any information, it can receive it via (typically JSON-encoded) HTTP body and store it in the local storage, there seems to be no need to access the read-only JWT payload for the same purpose. So, why should one keep the JWT payload nonencrypted? Why mix the two ways of getting application data to the client and use both JWT payload and normal data-in-response-body? Shouldn't the best practice be to keep JWT always encrypted? It can be updated only on the server side anyway.

1) I keep seeing inconsistent means of transporting JWTs to and from the server. [...] wouldn't it be good practice at least to be consistent and use either only header or only body?
This may depend on the Client. While a web app can get a higher degree of security by storing the JWT in cookie storage, native apps may prefere local storage in order to access the JWT information. [1]
2) The JWT payload contains the information of state because the server is not maintaining it. It is obvious one should keep the size of the payload as small as possible, because the size of JWT is added to every request and response. Perhaps just a user id and cached permissions. When the client needs any information, it can receive it via (typically JSON-encoded) HTTP body and store it in the local storage, there seems to be no need to access the read-only JWT payload for the same purpose.
The JWT keeps the Backend state, not the client state. The Backend state may be that User 128 is logged in as administrator. This is (in my example) stored in the JWT in the fields Subject and Scopes. Instead of the client sending an ID of a Backend session that contains this information, the info is in the JWT directly. The backend does thus not have to keep a session that stores the logged in state of user 128. If the Client requests information of User 2, the BE may decide that this info is forbidden if the JWT tells that the logged in user has ID 1.
So, why should one keep the JWT payload nonencrypted?
The state is normally not secret to the client. the client cannot trust the information in the JWT since it does not have access to the secret key that is used to validate the JWT, but it can still adjust the GUI etc from the information in the JWT. (Like showing a button for the admin GUI or not.)
Why mix the two ways of getting application data to the client and use both JWT payload and normal data-in-response-body?
See above, the main purpose of the JWT is to keep information the the Backend, not the Client. Once the user loggs in, the Backend ask "Hey, can you hold this info for me and attach it to every request so that I can forget about you in the meantime?" Like if your manager asks you to wear a name sticker on your skirt so that he/she don't have to remember your name. :-) (And he/she signs it so that you cannot alter it without him/her noticing.
Shouldn't the best practice be to keep JWT always encrypted? It can be updated only on the server side anyway.
It doesn't really bring any security unless you store secret information in the JWT, and that bay be better to do server side. The decryption is a bit more cumbersome to decrypt compared to just verifying a signature.
[1] Local Storage vs Cookies

Related

Clarification on API RESTful request

Im trying to create an applet in IFTTT however i need to obtain an auth token to allow the lights to call the service each time.
Im trying to obtain an auth token via the below:
Account information
GET Request auth token
https://environexus-us-oem-autha1.mios.com/autha/auth/username/{{user}}?SHA1Password={{sha1-password}}&PK_Oem=6&TokenVersion=2
The Nero API is RESTful and stateless and therefore requires authentication tokens to accompany every request. Once these tokens are requested they can be stored in a database for quick reuse.
This is the intial request to the API servers that collects the tokens and various IDs required for all subsequent calls. Tokens are valid 24 hours but should always be checked against the response in case this changes.
Request
{{user}} is the portal login
{{sha1-password}} is the hash of:
sha1(lowercase({username}).{password}.oZ7QE6LcLJp6fiWzdqZc)
(concatenated together - no additional characters should be inserted,
salt at end is static for all accounts)
PK_Oem and TokenVersion are static and provided above.
However im not sure what to put in for the "sha1-password"section.
Any help would be appreciated?
You need to calculate the SHA1 hash for the information above, which is the username, password and 'static salt' concatenated together with each value separated by a period.
Don't know what language you are using but most languages have libraries that will do this for you (e.g. Apache Commons library for Java)
This API is not particularly well designed in this respect, as client side hashing does not bring any benefits (when transmitting over HTTPS) and the 'static salt' as they call it is utterly pointless, as it's public.

Login Security using jsonwebtoken

I am currently working on a website using React where I want to be able to have user login. Right now my strategy is to send form data to the server (express) on submit, and if the info matches a user in my DB, the server sends back a signed JWT with no sensitive information (just the username).
Once the client receives the JWT, I am adding it to localStorage as well as adding the decoded data of it to my redux store. I plan to have my redux store holding the currently logged in user.
I believe there may be a security issue in my site because currently I have it so when the user first arrives at the site, If there is a JWT, it is added to my axios headers and the decoded JWT is set to be the current user. The code looks like this:
if(localStorage.jwtToken) { // If token present, most likely a user is signed in
setAuthorizationToken(localStorage.jwtToken) // Set that token to head all api calls
store.dispatch(setCurrentUser(jwt.decode(localStorage.jwtToken))) // Set user in redux store
}
Currently I've found that if someone just goes into my localStorage, copies my JWT and adds it to their localStorage then bam, they are me. I'm unsure if this is really a security flaw because the only way I've recreated this myself is by physically copying the token from one browser to another. But in general this seems very unsafe that just taking my token steals my identity.
If anyone knows a way to make this more secure or if there is a better strategy, or at least tell me what I'm doing wrong that would be highly appreciated.
How can another person get your token? Give expire time to token needed. Maybe try different way for securing token, especially give more security in API side. When logging in, store log activity in database and create unique field to identificate it such ip address or user-agent, or maybe detect is that user have been hit login endpoint before or not.

Is it secure to send username and password in a Json object in the body of a post request?

I am building a web application and my web server is secure, meaning that it uses an ssl cert with the front end to encrypt the connection.
When a user logs in, a JSON object which looks like this is created, and sent to the server.
{
username:"the user's username",
password:"the user's password"
}
On the server this is verified with a hashing algorithm that uses a salt. Once it is verified an api token is created which is valid for a certain amount of time, and is passed back and forth in the header in order to verify the user when requests are being made. Is sending the username and password like this best practice/secure, or is it better to send it in the header?
Lets divide it to many points:
1) you use a valid SSL certificate to secure the communication between the user and the server (It must be valid)
2) Sending the username and password in the body of the POST request is the best practice (Never use GET to send sensitive information such as Credentials)
3) Sending the api token in the HTTP request and response headers is the best practice (Again never use GET to send sensitive information such as session tokens)
So based on the points above, it seems that there is no risk in this implementation but you need to take the following points in your consideration:
1) The time out of the API token should be short in case of idle user. (5 ~ 15 mins are the averages based on the criticality of the application)
2) The length of the API token should be long string approx. 30 ~ 40 characters.
3) The API token generation must be randomized and hard to predict to protect from (session prediction attacks.)
Hope this help you.
What you are describing is basically HTTP basic authentication.
Is sending the username and password like this best practice/secure, or is it better to send it in the header?
In security point of view I cannot think of a big difference whether you send the credentials in the body or in the header. Basically whoever manages to read the clear text message, can see the credentials in both components. The common practice when using the basic authentication is to use the HTTP header though:
Authorization: Basic VGVzdFVzZXI6UGFzc3dvcmQxMjM0
where VGVzdFVzZXI6UGFzc3dvcmQxMjM0 is your base64-encoded credentials. The decoded string in this case is: TestUser:Password1234
It is important to realize that in your case the TLS is the only protection for the credentials in transit so you must identify all the nodes in the communication channel that could potentially expose the clear message. For example if you are using proxies that would terminate the TLS, those proxies are potential vectors for MITM attacks.
If you want to increase the security for the credentials in transit, one option could be to implement asymmetric end-to-end encryption so that you would encrypt the credentials with an authenticated public key on the client-side (e.g. certificate signed by a trusted CA) and then decrypt it at the destination with the private key known only for your server. In this case you would not need to worry too much what happens to the message in-transit.

Does JWT share/store the secret for signing on both the client and server?

I am working through some architecture issues in my head related to JWT authentication security and I'm trying to figure out the following:
How does JWT securely pass a secret between server and client?
Take a look at the below excerpt from from https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage/ ....................
CSRF can be prevented by using synchronized token patterns. This sounds complicated, but all modern web frameworks have support for this.
For example, AngularJS has a solution to validate that the cookie is accessible by only your domain. Straight from AngularJS docs:
'When performing XHR requests, the $http service reads a token from a cookie (by default, XSRF-TOKEN) and sets it as an HTTP header (X-XSRF-TOKEN). Since only JavaScript that runs on your domain can read the cookie, your server can be assured that the XHR came from JavaScript running on your domain.
You can make this CSRF protection stateless by including a xsrfToken JWT claim:'
{
"iss": "http://galaxies.com",
"exp": 1300819380,
"scopes": ["explorer", "solar-harvester", "seller"],
"sub": "tom#andromeda.com",
"xsrfToken": "d9b9714c-7ac0-42e0-8696-2dae95dbc33e"
}
How does the client create and send a valid request including the xsrfToken claim unless it can first sign the JWT after including the claim? (This xsrfToken after all is what's supposed to keep EvilBob from forging a request right?)
More details regarding my current understanding of the JWT XSRF process can be found here http://spring.io/blog/2013/08/21/spring-security-3-2-0-rc1-highlights-csrf-protection/.
I can explain how Stormpath does it, there are some other ways as well. Stormpath includes a 'kid' (key id) field in the JWT header, which is the identifier for the API Key ID / Secret pair. The JWT was signed with the Secret, and the ID is stored in key id field. When Stormpath validates the token, it can retrieve the secret. This works across servers and services but is never passed to the client. Using the client to glue separate services together with the secret is extremely insecure.
The client SHOULD NOT generate the JWT, this needs to be done on the server. The server knows the XSRF token and can sign it in the JWT and put it in the cookie.
Hope this information helps!
The article appears to call this the "synchronized token pattern", however the solution described better fits with the Double Submit Cookies method rather than the Synchronizer Token Pattern.
Double submit cookies involves sending the cookie value in a header or body as well as sending it with the browser cookies that are automatically sent. If you are not supporting CORS, then setting a token in a header is secure anyway, as is with any custom header value (e.g. X-Requested-With). This is because a custom header cannot be sent cross-domain in the first place, so verifying that it has transported from the client verifies that it is not from another domain already. As a defence in depth strategy, you can set it to a random value, as explained by this answer.
The random value doesn't need to come from the server, nor be signed. It just needs to be generated by a CSPRNG. If generated client-side, window.crypto should be used for this. All the server does is check that the header and cookie values match.
A third party domain cannot forge a request because even though the cookie value will be sent by the browser automatically from the victim's machine, the attacker cannot include the value in the header or the request body.
With the Synchronizer Token Pattern the CSRF token is generated server-side and stored against the session. This value has to be sent from each form submission and is verified server-side that it matches the stored token.

Secure iOS to online database connection

I have an iPhone application that needs to collect data from an online MySQL database. I've written a PHP web service so I collect the data with JSON. The problem is that everyone can see the data if they go to the URL now. How do i secure the data transfer properly?
Thanks for your suggestions.
Typically, if you are showing data private to a particular user, then each user will generally have an account (user id and password). The app will pass the user's credentials to the server before the server will provide the user's data.
You can also do something similar using SSO integration, or OAuth (ala Facebook).
In some cases, your app may only pass the username/password on the initial call and receive a session ID, which the app passes on remaining calls. This allows the server to store session data.
Even if the data isn't private to a particular user, you can use accounts to restrict access and privileges for a publicly reachable web API.
In all of the above cases encryption such as SSL (HTTPS) must be used to protect the authentication mechanisms and data transfer.
I'm assuming your data is public for all users of your app, in other words, you don't want to implement a login mechanism for your users. If you just want to make sure you return the data only to users of your app and not to anyone who happens to enter the right URL in their browser, you will need to sign your requests, so that only requests from your app are accepted by your server.
I use a secret key that my app uses to create a hash/digest of the request which the server verifies (it knows the secret key as well). Also I make sure requests cannot be replayed if they are intercepted by adding a timestamp and a nonce. The timestamp is checked to be within 10 minutes of the server's timestamp (relaxed sync) and the nonce must be unique (server keeps the last 10 minutes of nonces). This way no-one can copy the same request, the server will just serve an error if they try.
This post explains how to sign your requests in a bit more detail:
http://www.naildrivin5.com/blog/2008/04/21/rest-security-signing-requests-with-secret-key-but-does-it-work.html