Arguments against creating JWT on client side - json

A partner company is creating an RESTful Endpoint which we want to consume.
Instead some proper way of authentication they want to give use the JWT signature key so that we can create a JWT clientside and send the JWT as JSON body to the API endpoint. They could then check if the signature is valid as they also own the signature key.
While this actually seems to get the job done it feels like abusing JWT's.
Is this a valid workflow for JWT's?
if not what are argruments against it?
I can't think of any valid argument against it (beside that it feels wrong).

The biggest problem I see with this workflow is that the server has to trust the information that the client includes in the JWT payload. Additionally, if the server sends the same signature key to all users, the server will have a lot of trouble confirming if a user is who they say they are. Now, if the server is sending a different signature key to each user, the best the server can do is to store records in a database to control the expiration of the signature keys, but this makes JWTs no longer stateless (since they depend on "states" stored in the server), and the advantages of this feature are lost.

By far the best way to do this is to
use asymmetric encryption
generate a private/public key pair
Send the other party a public key
Generate JWTs using our private key.
Every time there's more than 1 party involved with JWT, and they individually generate/validate tokens and asymmetric encryption/signing is not used you should feel this is a red flag.

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.

Best Practice to Store API tokens

I am working with an API for automating tasks in a company I work for.
The software will run from a single server and there will only one instance of the sensitive data.
I have a tool that our team uses at the end of every day.
The token only needs to be requested once since it has a +-30 minute timeout.
Since I work with Salesforce API, the user has to enter his/her password either way since it relates the ticket to their account.
The API oAuth2 tokens and all of its sensitive components need to be secured.
I use PowerShell & a module called FileCryptograhy to produce an AES version of my config.json.
In my config file, I store all the component keys that need to be used to generate the token itself.
Steps
Base64 encode strings
Use FileCyptography module to encrypt the JSON file with a secret key into an AES file.
When API needs to produce a token, it works in reverse to get all the data.
Is this a valid way of securing sensitive API data, or is there a more efficient way?
P.S: I understand that nothing is very secure and can be reverse engineered, I just need something that will keep at least 90% of people away from this data.

Why should I leave JSON Web Token payload nonencrypted?

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

JSON Web Tokens in Node Js Express application

So I have an API using Express in NodeJS and I want to secure it so only I or known clients can use it. I found about JSON Web Tokens but not sure how to keep the key secure if I'm making AJAX requests to the API from a web client using JQuery for example. People will be able to get the key and make request themselves right?
How do I prevent this? Or have I misunderstood the concept of JSON Web Tokens.
Other smaller question, I found the jsonwebtoken npm package which seems popular and you can sign a web token and verify one. How does the verification work? I know you pass a secret but the same secret is used for multiple signed keys right? I originaly thought I store the key in a database or something and verify if the provided key in the request is in my database but that does not seem to be the case as the you do not store the key.

Block unwanted use of json API

I have a website where you can request data using ajax from our servers as json (only to be used on our site). Now i found that people start using our requests to get data from our system. Is there a way to block users from using our public json API. Ideas that i have been thinking about is:
Some kind of checksum.
A session unique javascript value on the page that have to match server-side
Some kind of rolling password with 1000 different valid values.
All these are not 100% safe but makes it harder to use our data. Any other ideas or solutions would be great.
(The requests that you can do is lookup and translations of zip codes, phone numbers, ssn and so on)
You could use the same API-key authentication method Google uses to limit access to its APIs.
Make it compulsory for every user to have a valid API key, to request data.
Generate API key and store it in your database, when a user requests one.
Link: Relevant Question
This way, you can monitor usage of your API, and impose usage limits on it.
As #c69 pointed out, you could also bind the API keys you generate to the API-user's domain . You can then check the Referer URL ($_SERVER['HTTP_REFERER'] in PHP), and reject request, if it is not being made from the API-user's domain.