0

So I am not sure if my question fits in really in stackoverflow or not but I would give it a shot and try to see if my knowledge of JWT is actually correct or am I out of the loop totally.

So what I have created is an server API that reads POST requests that is being sent from a client app and that returns Bearer Token which is needed to be able to access rest of the API's that I have created.

So far I have a server api that created Bearer token IF the username and password matches the login.

A simple POST requests would look like

{'username': 'hello', 'password': 'world'}

so what I have done instead is that I created a JWT encoded from JWT.IO site with a secret code which would look like:

{'username': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImJhcnJ5In0.-TCwkrPr8dq4WqsckaWNG7G2ddn7e97hH0jkQ-1j5Bo',
 'password': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXNzd29yZCI6ImF1dG9zbmtyIn0.mWvxW4xga_OQMLKxf5zfSP4bSV0KzLPSRpqapU-RbAw'}

However my main problem is that how should I handle the connection between client app -> first /token request to be able to get bearer token?

It seems like I do need to somehow "hardcode" the username and password inside the client app to be able to access my API but I feel like this is not the correct way because then you would just be able to read the network logs and send the same requests to the server and you would forever get a new Bearer token which you can manipulate my server api.

My question is that what way should I do to not be able to expose my username and password in the client app AND to be able manipulate through my server api? Because what my server does is that it decodes the username and password from JWT with secret and matches if the username and password matches my server api username and password. But it feels like by exposing my username and password with already finished encoded JWT token you would still be able to use those values and do whatever you want?

Example of a client app:

import requests

headers = {
    'accept': 'application/json',
    'Content-Type': 'application/x-www-form-urlencoded',
}

data = {'username': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImJhcnJ5In0.-TCwkrPr8dq4WqsckaWNG7G2ddn7e97hH0jkQ-1j5Bo',
        'password': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXNzd29yZCI6ImF1dG9zbmtyIn0.mWvxW4xga_OQMLKxf5zfSP4bSV0KzLPSRpqapU-RbAw'}


response = requests.post('http://127.0.0.1:8000/token', headers=headers, data=data, verify=False)
Thrillofit86
  • 599
  • 2
  • 7
  • 20
  • 1
    I don't understand why you put the username and password in a token when sending the credentials to the server to get a bearer token. The content of the token is readable for everyone you get's the token, so it adds zeor security. You should genereally use https connections instead. – jps Dec 19 '19 at 10:52
  • @jps I agree. Because I am not sure how else I would be able to get token. Because I do need to send a valid username and password to be able to get Bearer token from the server api. So here is where I am stuck. I dont know what I should :( – Thrillofit86 Dec 19 '19 at 11:21

1 Answers1

2

From your description, it seems the client in your use case is acting on its own behalf and NOT on behalf of a human user.

In such case, the OAuth2 grant type that is applicable is called "Client Credentials" where the client sends the client credentials (usually a client id and a client secret) in the "Authorization" header to the authorization server. The authorization server will then share an access token and/or refresh token that need to be stored on the client side in a cookie (usually in the form of JWT) and sent along with every subsequent request to the resource server. The only thing special about the "Authorization" header is that it tells the entire HTTP infrasrtucture not to cache the value in any shared cache.

Now, the question is, how do we store the client secret. Should we hard code it in the client? Certainly not. Usually the most secured way to handle this is to store it in a password Vault. Usually the vault stores the secrets, passwords and certificates in a tamper resistant Hardware Security Module (HSM). (But in the absence of a vault, it is also common to store the secret in encrypted form in a separate file).

The only question left being answered is, how the client connects to the Vault. The Vault trusts the platform (say the AWS or Kubernetes or any other cloud platform). When the VM or the container is launched in those platforms, a token is injected by the platform in the container. The application will then use the token to connect the Vault which can verify the authenticity of the token with the platform.

Saptarshi Basu
  • 8,640
  • 4
  • 39
  • 58
  • If the vault is not exposed to any external network (closed within a VPC), then the only way to misuse the vault is to send it a request from within the VPC itself. In that case, I am correct to say that using token injection (as opposed to storing it in a config file) would not add any additional security? – Rishabh Poddar Feb 06 '20 at 14:27