What's the benefit of having a key and secret when authenticating an api over just one single secret string? - authentication

The key tells who you are..
The secret tells if it's true...
But, both of these can be achieved by having a unique secret string. Sort of a token.
What is the advantage of one approach over the other?

The OAuth process has more to do with just using the key and secret. In short this is what happens. The key/clientId and secret cannot be used to call API
you give a button on your page/app to authorize with the key and redirect_url
user clicks and provides their consent
the provider calls your redirect_url with a code
the code is packed with the secret, key and redirect_url and sent to provider token url to get the access_token and refresh_token
you can then use this access_token to call the api
the access_token has an expiry, so a refresh request needs to be made again using the key, secret and refresh_token
I work with Pathfix and do this for a living. We essentially take your key and secret and complete the whole process and store the tokens for you. You can use our universal endpoint to make all your API calls and we keep your tokens alive and stamp you API and complete your request for you :)

Related

Theory of API development: why create a refresh token method instead of simply ask user to relogin?

Most of APIs around the web provide two methods:
login: given credentials, returns the access_token and the refresh_token
refreshToken: given refresh_token, returns another access_token and a new refres_token.
My question is: why is so widely preferred to do login and then a possible sequence of periodic refreshToken instead of simply login again when access token expires?
Which are the benefits of a refresh versus a full login?
After doing some more research, I find that it's to limit the space for a Man-In-The-Middle attack.
If someone intercept your user/password you have lost. And if you send it in plain at each call, the probability will increase that someone intercept them.
If you login and then for a while use access_token , a bad actor could intercept the access_token, but at least it willl use it until it will expire.
Again, instead of relogin, remote server will use the refresh_token to obtain a new access token.
the refresh token expire after first use so it's useless to intercept.
And so on.
So for server to server, the actually best practice is
login
- receiving access_token and refresh_token
when access_token expire, use refresh_token to obtain a new access_token.
If both access_token and refresh_token expired, relogin with app_id/app_secret pair

Securing a JWT token

In general, JWT has an encoded message with a signature. The signature uses for checking the genuinity of the data. My question is, this signature is for assuring the client about the server, but how server can trust the client? In other words, if a client sends a JWT to the server, how the server can be sure this is the right/authenticated client?
My second question is about JWT's lifetime. I know there is a claim (exp) which can be set to indicate JWT's expiry. But what if the client changes that claim? Should I keep expiry date on the server to make sure the JWT is still valid? Wikipedia says: To validate the session stored in the token is not revoked, token assertions must be checked against a data store. This renders the tokens no longer stateless, undermining the primary advantage of JWTs.
Given a JWT, the server knows that the client is legitimate by verifying that the HMAC of the header and payload is equal to the signature. The server has a secret key that it uses when computing the HMAC, so if someone wanted to create a fake JWT with a proper signature, they would need to have access to this key.
Your second question shares the same idea as the first. If a client wanted to change the expiration of their JWT, they would have to recompute the signature, and to do this successfully, they'd have to know the secret key.
The point of using JWTs is not to store data like the expiration date on the server, all of this data lives inside the token itself, and the integrity of this data is protected by the secret key used to compute the signature.
JSON web token (JWT) can come in two flavours. Typical, the most widely used form is to use JWT with a JSON web signature (JWS). In security world, this provide integrity. Other form is JWT with JSON web encryption (JWE). This form provides both integrity and confidentiality.
So if you have a specific requirement to identify that you get a valid, condifential JWT, then you should adopt JWE based approach. You can read more about this in RFC7516. For encryption, you can use either symmetric or asymmetric keys. Once you receive JWE based JWT, you can validate that it was sent by intended party by successful decryption of the JWT payload.

Auth0: Managing authentication on Lambda functions

Current Implementation
My current application utilizes Vue.js + Auth0 on the frontend.
Vue.js utilizes AWS API Gateway, POST/GET methods are sent via:
https://xxxx.execute-api.us-east-1.amazonaws.com/dev/
On the API Endpoints that require authentication I have a "jwtRsaCustomAuthorizer" Authorizer. Which is documented here.
Remaining Concern
However is validating IF the token is valid enough? In this scenario I want to make a POST function that will do two things:
Update the users app_metadata
Save data associated to user
How do I KNOW User id auth0|123456 is who they say they are?
With the JWT being validated by the Authorizor, do I know the token hasn't been manipulated? E.g. if I just decode the passed data, can I assume the userID is valid?
The short answer is: You do not really care in the frontend. Validation of the token normally happens via the backend, which is in your case through the jwtRsaCustomAuthorizer you were talking about. If the backend trusts the token it returns data, and if it does not it returns an authorisation error.
Your backend, and in particular jwtRsaCustomAuthorizer, does validate that the content of your JWT token is valid and trusted. A JWT token consists of three parts. The first part describes the algorithm used. The second part is the payload, which contains the claims, a nonce, an issuer and an expiration date. The third part is used to verify if the JWT token is issued by a trusted party by using a secret and generating a signature with it. In your case you are using RS256 with a private and public key pair.
Since the first two parts of the JWT token are used to generate the signature, you cannot change the algorithm or the payload without invalidating the signature. Since RS256 uses assymetric encryption using a public and private key pair, you can either verify the JWT token by performing the same steps using the private key and comparing the newly generated signature against the signature in the JWT token, or in case of your api endpoint, using the public key to decrypt the signature and checking that against the first two parts of the JWT token.
jwtRsaCustomAuthorizer ensures that the JWT token was created by auth0 by checking the JWT token against the public key that is provided by auth0. If the signature matches the payload, it means that the issuer must have had access to the private key, which is only available to the issuer. This allows you to trust the payload.
You can find more information via jwt.io and this stackoverflow question on the difference between hs256 and rs256.

Generating an API Secret

I have created an API that I only want certain clients having access to. After a bit of research, I found that API Keys and API Secrets are pretty good way of controlling that.
I want to basically generate my own secrets using information I control. For example, if I create the secret 1500315177265-8005550000-System, the secret itself has information I can reference and validate. From what I understand, it doesn't matter what the secret is, as long as its not shared, and that's what makes it a secret. I can append some long salt values to make it much harder to guess. Can I use secrets securely this way?
Along the same lines, I am thinking what the need for the API Key is needed if the secret itself has identifying information. More than likely, I'm missing something here or more APIs would do it this way.
You don't need to suffer creating this mechanism by your own, you could just use OAuth for this. Actually by reading how OAuth works, I'm pretty sure that you'll get an overall idea of what the "API Key" is doing.
Long story short. OAuth allows you to create access tokens that will be requested by your users, once the user has asked for an access token, he'll be able to use it to get authenticated on the API.
You can also configure the duration for these access tokens, for example, let's say that you only want them to be valid for one hour. Then the user will use a new access token every hour, helping you to minimize risks against compromised access tokens.
If you want to take a look at the pipeline used by OAuth, it will be something like this:
The user sends an identifier and a shared secret (see them as username and password). If the identifier and the secret are correct, he'll receive a "refresh token", this token will be used to send requests to the token server to receive new "access tokens". The client sends a request to the tokens server to receive an access token, and now he'll be able to send requests to your API, where he'll use his access token as an identifier, and only if the token is valid, he'll get access to your application.
Maybe you could be curious about expired tokens, for example, What happens when the token has expired? Now our user needs to repeat all process again? No, because if the token has expired, he can just send a new request to the tokens server, sending his refresh token, and he'll get a new token to be used with your API.
I'm pretty sure that you already noticed that your API key is the "access token" equivalent, and your shared secret is the equivalent to the credentials used at the beginning of the OAuth process.
You can create your own mechanism, but you will need to take a lot of considerations that are already covered by OAuth. For example, Will you expire your API keys? After all, you should not trust a single key to be sent over every request for an undetermined amount of time. How will you handle the process to request new keys? Do you really want your users to send their secret every time they want a new key? Refresh tokens are useful for this.

Encoding and Decoding API Access token with keys

I am planning to secure my rest API in django with a ACCESS_TOKEN.
When ever user is logged in using their username and password, once they are authenticated, I generate a ACCESS_TOKEN and passed to frontend be it Website or Native application. and then later used that ACCESS_TOKEN for further communication.
I am generating this token based on some user data and then encrypting this with public key. Later when application send this for in any request, I decrypt the ACCESS_TOKEN with private key and extract user data data and process the request. This is something similar to session where session data is in encrypted form in ACCESS_TOKEN and only private key and decrypt the ACCESS_TOKEN. This is what I am planning to do.
Please suggest me for following questions:-
1. Is is the best way to secure my REST API? I want to use my API in same way from Web-application(AJAX calling) and NATIVE application(Android/IOS etc) ?
2. What is the best way to expire the token? Do I need to keep track of access token at my end in order to expire them?
Also I do want to use the Oauth in my API.
Most people I see use JWT's that are signed but not encrypted so they store non-PI data like user_id or session_id. I guess you could encrypt it if needing to store personal information but I don't see any other reason. Assuming you are using HTTPS, then only the end client would have access to the information. Sounds like asking for trouble if the secret gets leaked so you would want a really good key rotation scheme since you may not even know its leaked until too late.
Many people using JWTs do so because they don't want a centralized auth server, thus the token is short lived like a few hours or days. If you need really tight control on expiring tokens, you can take a blacklist approach where a blacklist of JTI's (JWT Ids) are stored in a K/V to be checked against. https://www.moesif.com/blog/technical/restful-apis/Authorization-on-RESTful-APIs/