REST API and API KEY - api

Please someone explain me how to use an api key and what is it good for.
I have searched a lot about this and I got different and conflicting answers. One says that an API key is kept secret and its never sent as the part of the communication, while others send it to the client without any encryption. What is the client's signature? How can he generate it and what can do the server with it? Why should monkeying with api keys instead of using the good old username-password pair? Could someone explain me how the communications look between a client (Android device) and the server (php api) in detail.
I'd appreciate any good tutorials, code samples, and explanations for beginners.

The topic of API authentication is a complex one. Below I'm going to do my best to explain one part of the issue: why is an API key better than a username / password?
Here we go.
When building (or working with an API), a common question developer's ask is "Why does this service require an API key instead of my username and password?" It's a great question!
First, let's talk about what API keys typically are.
API keys are usually randomly generated strings of letters and numbers. Furthermore, an API key typically comes in two parts: an ID and a secret. If you're using a web service like Stormpath, for instance, you might have two API keys that look like this:
API_KEY_ID=kzjbOg3iOm4k4MRpBss76yxlZSPJtoOPaqxirsfX
API_KEY_SECRET=A8FnQWM7RpgGjU3sZjOUgMIq5t8mvAhQES9iE30S
You can think of an API key ID as a username. This is a globally unique identifier which allows the API service to find your account.
You can think of an API key secret as a password. This is a password that, when matched up with the correct API key ID, will grant you access to the API service in question.
The main reason you WOULDN'T want to use a username and password to authenticate against an API is that:
Even if the API is served over SSL, there are many exploits available which can compromise your credentials. If you used your username / password to log into API services, and an attacker grabs these credentials, they have access to your account as a whole.
If you use your username / password to authentication against an API, what happens if one of your servers / API clients is compromised? This means you need to reset your username / password and update it for all of the clients which are using it. This can be time consuming, and costly.
By using a username / password, you're usually restricting yourself to a certain type of API usage. By having API key pairs, you're able to separate out API credentials to different levels of access (maybe on key pair can only access certain data, while another can access other types of data).
API key pairs are, in general, a much better idea. In addition to the obvious security benefits, they also serve other purposes:
If an API key pair is leaked, you can usually create / cycle API key pairs without needing to update every single client you own.
You can use API key pairs to provide sub-account functionality for your API.
Hope that helps!

have a look at this
REST authentication and exposing the API key
Why do some API providers require an API key?
And study a lil about Oauth

Related

How to design the system to manage RESTful API keys/credentials for external developers to call

Background
I'm working on a web service with Python as backend using FastAPI.
As far as I know, for the front end user authentication and authorized requests there is JWT. Following the best practices, the token would expired in 15 minutes and refreshed before that.
However, if I want to expose some RESTful API endpoints (e.g. read/write data to my database) for other developers (e.g. Stripe users would call Stripe's API with some keys), I need to create a permanent API key with some configurable permission, like the personal access token for Github. It seems to me that using JWT is not a good option because it's not ideal to set long expiration time or ask external developers to refresh tokens frequently.
I had hard time finding related resources for designing such as system to manage these API keys, even though many companies provide this kind of service.
I would imagine the solution to be having a table in the database that stores the API keys with some permission levels as columns and links with the user table. However, with this method, each call from the external developers/service has to query the database to validate permission, which may hurt the response time compared to JWT. I'd like to know if this makes sense what are the best practices.
Questions
What is the work flow to generate the API keys for external developers/service to call my API endpoints that need user authentication?
How to revoke given API keys?
How to configure/validate API keys for different permissions?
How to design the table to manage API keys?
You should have a secured Web page for developers to generate API keys themselves. So, they can create, revoke, or delete API keys from this page.
Designing your API key table:
key
scopes (permissions)
expires (date)
revoked (boolean)
created (datetime)
modified (datetime)
userId
You can learn more on this article:
https://www.freecodecamp.org/news/best-practices-for-building-api-keys-97c26eabfea9/
Authentication process:
Authentication to the API is performed via HTTP Basic Auth. Provide your API key as the basic auth username value. You do not need to provide a password.
Example from Stripe:
curl https://api.stripe.com/v1/charges \
-u sk_test_dsadsaDSds123DSA:
On your backend, fetch username (API key) from Header and find the API key from the table. Retrieve user details of this API key and do authentication.

As an API creator, should I hide client API keys once they've been created?

I'm working on an API where a user of my API can sign up for my API to get an API key. When I generate this API key, I'm using asymmetric encryption to create a hash that I store in my database.
My question I have is this, once the user generates an API key and then signs out, the next time they sign in, I don't have the API key anymore to display in my app's dashboard. Is this normal / acceptable?
Do other APIs do it differently? i.e. do they offer the API key to the user? and if so, are they storing the unhashed API key in the DB? Is this a balance between user experience and security?
In OAuth2, it's pretty common for systems to show the OAuth2 client id at all times, but the OAuth2 secret exactly once.
If you want to make the user experience good, focus on making it easy to roll a fresh API key without expiring old ones. You can show a list of API keys (not the secret), and when they are last used so it's also easy to let the user disable keys that are likely out of use.
API Keys are not usually considered secure. Typically API Keys are visible to the clients. API keys should not be used to perform secure authorization. However, you can design any system as you want and in your current design if a third-party or attacker can make successful invocations to your API by obtaining the so called "API Key", it's better to hide it and let the user take the responsibility to securely store the key in somewhere else. Also you should make sure in your API, there must be a way to
Revoke an existing API key.
Generate a new API key with an expiry date.

Is there a way to secure an API key on a frontend page?

My service allow any HTML documents to be converted to PDF using a POST request.
It is mostly used on the backend of my client's server and thus, the API key used for the communication is kept private.
Now, I'm thinking of a way to let my client's visitors be able to call my service on behalf of my client API key, without exposing this secure API Key.
My main issue here is security. If my client add an XHR POST requests that contains the API key, someone can take that API key and use it for their own purpose and abusing my client's account.
I could filter by domain, but this is easily spoofed so it's not possible.
I was wondering if there was a way to call a private service and be identified without risking its identity to be stolen, from the client ('s client) side?
If you're providing this sublet for authenticated users, then it's fairly trivial to give them unique keys (something that hashes their user ID or session against the API key and an initial timestamp, and checks it / logs it / looks for brutes before accessing the API). If you're doing it on the open web, without any kind of user authentication, then rate limiting gets very tricky indeed. Generally you'd want to use a combination of session hashes, IP address, operating system and browser data to create an anonymous profile that gets a temporary key on the frontend. One fairly solid way to do this is to force users through a CAPTCHA before serving a temporary key that allows them a limited number of uses of the permanent key. Any user whose ip/browser/session matches the existing attributes of a known client key is shunted to that one (and gets to skip the CAPTCHA); anyone who doesn't match an existing profile gets the CAPTCHA. That makes you a less attractive target for spoofing. On top of that, you should always rate-limit the entire thing, within a reasonable number of hits per day based on what kind of traffic you expect (or can afford), just so you don't have any surprises. This is the minimal security you'd want if your client's money is on the line every time their API key is used. It will require a simple database to store these "profiles", track usage, check for brutes and maintain the currently valid client keys. Client keys should always be expired regularly - either with a time diff against when they were created, or a regular cron process, or a maximum number of uses, etc.
One other thing I frequently do is rate-limit based on a curve. If I think 5 uses per minute is reasonable, for example, then after 5 uses in a minute from a session, each usage adds a delay of a fraction of a second * the number of uses in the last minute, squared, before the data is served.
The best answer would be to put this all behind a login system and secure that.
Assuming that you are using OAuth kind of system, In that case, make use of Access Token Mechanism that provides access to private API/User's data on behalf of User(Client) without exposing his/her credentials or API Key(Authentication key), also the access token can be expired based on the time/usage.
Example: The access token is generated against a single endpoint that can be the Html Conversion endpoint and will be expired once the action completion.
https://auth0.com/docs/tokens/access-token
And following blog post would be helpful to architect your authentication system
https://templth.wordpress.com/2015/01/05/implementing-authentication-with-tokens-for-restful-applications/
there is no good way to do front-end secure storage but my recommendation is :
is an API that used HMAC signing of requests in combination with OAuth authentication. The API key is actually a signing key. they key does not get transferred. The API key can still get found on the front-end but it becomes useless because you still need the OAuth token to send a valid request.
i know users will have to login in, but you can see this as an advantage because atleast you can log who is using the app by getting information from oauth.
please consider back-end secure storage!
You can use JWT tokens in my opinion. On the basis of username, password or any other info you can generate unique jwt tokens for different users.
Anyone can decipher these jwt tokens but not he unique security token.
If you want to add more more security to tokens, use JWE, encrypted web tokens.
More about these schemes can be found at https://medium.facilelogin.com/jwt-jws-and-jwe-for-not-so-dummies-b63310d201a3
Hashing is a decent option and should be done anyway, but for a fully secure method that wouldn't add too much complexity, you could simply abstract away from the authorization/API key by building your own API to interface with the API. This way you could both limit the kinds of things that can be done with the API key and also completely obscure the API key from the user
I don't think you should always go for user auth or JWT, it just doesn't fit all use cases. The idea of using a Captcha is interesting but also somewhat complex.
If complexity is not an issue I would rather use an infrastructure approach, I'm most familiar with AWS so I'll focus on that. Assuming you can change the host of your front end you can have your site hosted on an S3 bucket, served through a CDN, and create a proxy Lambda function that will hold the logic to call your API and store the API key as an encrypted environment variable. This Lambda you call through an API Gateway that can only be called by a specific IAM role which the S3 bucket also uses. You can also use a Cognito User Pool without authentication.
Going back to a simpler alternative the Captcha approach can be implemented as an attestation provider. I know of two services that do this, Firebase and KOR Connect. Due to Firebase using this approach only for their own resources as of the time of this writing I much rather use KOR Connect as it’s a very simple middleware that basically solves this issue. I won't go into detail about these services as it’s not the main concern of this topic but you can check the documentation their respective links.

Securing non authenticated REST API

I have been reading about securing REST APIs and have read about oAuth and JWTs. Both are really great approaches, but from what I have understood, they both work after a user is authenticated or in other words "logged in". That is based on user credentials oAuth and JWTs are generated and once the oAuth token or JWT is obtained the user can perform all actions it is authorized for.
But my question is, what about the login and sign up apis? How does one secure them? If somebody reads my javascript files to see my ajax calls, they can easily find out the end points and the parameters passed, and they could hit it multiple times through some REST Client, more severely they could code a program that hits my sign up api say a thousand times, which would be create a thousand spam users, or they could even brute force the login api. So how does one secures them?
I am writing my API in yii2.
The Yii 2.0 framework has a buil-in filter called yii\filters\RateLimiter that implements a rate limiting algorithm based on the leaky bucket algorithm. It will allow you to limit the maximum number of accepted requests in a certain interval of time. As example you may limit both login and signup endpoints to accept at most 100 API calls within a 10 minutes interval of time. When that limit is exceeded a yii\web\TooManyRequestsHttpException exception (429 status code) will be thrown.
You can read more about it in the Yii2 RESTful API related documentation or within this SO post.
I didn't use it myself so far but from what I did read about it in official docs, and I mean this:
Note that RateLimiter requires
$user
to implement the
yii\filters\RateLimitInterface.
RateLimiter will do nothing if
$user
is not set or does not implement
yii\filters\RateLimitInterface.
I guess it was designed to work with logged in users only maybe by using the user related database table, the default one introduced within the advanced template. I'm not sure about it but I know it needs to store the number of allowed requests and the related timestamp to some persistent storage within the saveAllowance method that you'll need to define in the user class. So I think you will have to track your guest users by IP addresses as #LajosArpad did suggest then maybe redesigning your user class to hold their identities so you can enable it.
A quick google search let me to this extension:yii2-ip-ratelimiter to which you may also have a look.
Your URLs will easily be determined. You should have a black list of IP addresses and when an IP address acts suspiciously, just add it to the black list. You define what suspicious is, but if you are not sure, you can start with the following:
Create something like a database table with this schema:
ip_addresses(ip, is_suspicious, login_attempts, register_attempts)
Where is_suspicious means it is blacklisted. login_attemtps and register_attempts should be json values, showing the history of that ip address trying to log in/register. If the last 20 attempts were unsuccessful and were within a minute, then the ip address should be blacklisted. Blacklisted ip addresses should receive a response that they are blacklisted whatever their request was. So if they deny your services or try to hack things, then you deny your services from them.
Secure passwords using sha1, for example. That algorithm is secure-enough and it is quicker than sha256, for instance, which might be an overkill. If your API involves bank accounts or something extremely important like that, important-enough for the bad guys to use server parks to hack it, then force the users to create very long passwords, including numbers, special characters, big and small letters.
For javascript you should use OAuth 2.0 Implicit Grant flow like Google or Facebook.
Login and Signup use 2 basic web page. Don't forget add captcha for them.
For some special client such as mobile app or webServer:
If you sure that your binary file is secure, You can create a custom login API for it. In this API you must try to verify your client.
A simple solution, you can refer:
use an encryption algorithm such as AES or 3DES to encrypt password
from client use a secret key (only client and server knows about it)
use a hash algorithm such as sha256 to hash (username + client time + an other
secret key). Client will send both client time and hash string to
server. Server will reject request if client time is too different
from server or hash string is not correct.
Eg:
api/login?user=user1&password=AES('password',$secret_key1)&time=1449570208&hash=sha256('user1'+'|'+'1449570208'+'|'+$secret_key2)
Note: In any case, server should use captcha to avoid brute force attack, Do not believe in any other filter
About captcha for REST APIs, we can create captcha base on token.
Eg.
For sign up action: you must call 2 api
/getSignupToken : to get image captcha url and a signup token
respectively.
/signup : to post sign up data (include signup token and
captcha typed by user)
For login action: we can require captcha by count failed logins base on username
Folow my api module here for reference. I manager user authentication by access token. When login, i generate token, then access again, client need send token and server will check.
Yii2 Starter Kit lite

Confused about OAuth

Call me a newbie, call me dumb, rate down this topic. Do as you like, I'm just here to ask a question and hopefully learn something from it.
So I've been making an API for my website today (well attempting to) and I've noticed this "thing" on most popular sites API's such as Twitter, Foursquare, Tumblr called "OAuth". From my research today I have gathered that it's basically a way of giving the consumer a token to access restricted data from the provider depending on what the user chose without the user handing over their password and username.
But why do I have to use OAuth, why can't I just give out an API to the consumer key and they just use that? I will then see if the user has allowed access for the application, and they will have to grant access for the app to take information from their account, such as photos.
Something that also confused me is why the Tumblr API uses both. It seams on reading blog details they use a simple api key but posting on blogs you need an OAuth Signature.
OAuth is a protocol and has a set of specification defined by some expert group to define how to share data.
Basically what you are seeing is just a part of the OAuth mechanism,and there is a lot of communication and hand shaking mechanism to ensure the security of user data as well avoiding unauthorized access to data.
OAuth mechanism exits at 2 levels
three-legged authentication
Two-legged authentication
Both have their positives and negatives and there are a set of procedure which needs to be taken care for security and data integrity.
Allowing access only based on access_token/consumer key is really a very weak security mechanism and can easily be hacked by any one who happens to get access to your consumer key while OAuth system make sure by sharing a time bound access_token.
For details refer to this thread oauth-2-0-benefits-and-use-cases-why