BOOK THIS SPACE FOR AD
ARTICLE ADThe REST API or RESTFUL API contains 2 parts REST and API. REST (Representational state transfer) represents a client-server architecture. It mostly uses HTTP protocol to perform CRUD operations. API (Application programming interface) is a way of communicating between two programs. In a nutshell, REST API is an API constructed based on rest architecture. Just like any other piece of code, API’s also need to be protected from various threats as it is used to communicate and transfer sensitive information. The best way to protect it is to make it secure while creating it. Here are some best practices for creating a secure RESTFUL API.
The most common way of securing software is authentication. It helps in security by permitting only the authenticated users. When talking about authentication in RESTFUL API there are a few most commonly used methods they are,
HTTP Basic Authentication.API Key Authentication.OAuth Authentication.JWT Authentication.HTTP Basic Authentication:
The easiest method of authentication is to use HTTP and send the username and password through the AUTHORIZATION HTTP HEADER in each API call. This header encodes the content in base64, but it’s not encrypted so it can be used efficiently only through SSL / tls, else a simple man in the middle attack can reveal the credentials to the API.
Example:
get / http/1.1host: example.orgauthorization: basic zm9vomjhcg==HMAC HTTP Basic Authentication:One can make this more secure by using HMAC ( hash-based message authentication). The advantage of using HMAC over the normal HTTP authentication is that we just need to send the password hash instead of the actual password which makes it safer. Another advantage of using HMAC is that we can prevent tampering by hashing the message body. Also, unlike normal HTTP authentication, it doesn’t need SSL/tls to work efficiently. We can even introduce nonce to protect against replay attacks.
Example:
#generating hmacdigest = base64encode(hmac(“sha256”, “secret”, “get+/users/username/account”))#Sending it over httpget /users/username/account http/1.1host: example.orgauthentication: hmac username:[digest]API Key Authentication:
This is a second process (ie) this happens after one authenticates their identity. This is a popular way of authentication for APIs, it is a quicker and easier method but also comes with its own security concerns like if some unauthorized person ends up with the API key they can use it to access the API. There are various methods of implementing this, they are,
HTTP headers.Query string.Request Body Parameter.HTTP headers:
The API keys can be passed through the HTTP headers, like X-API-KEY in AWS, or We can combine the HTTP basic authentication and send the api key through the username or password field. The third way of doing it is by using the bearer keyword in the authorization header. But just like normal HTTP basic authentication, it must be used with SSL/tls.
Query string:
This is one of the riskiest ways to pass an API key as it directly passed through a parameter in a URL. It was used in the early days but considering more advanced and secure methods now available this method is basically no use.
Example:
https://example.com/endpoint/?api_key=abcdef12345Request Body Parameter:
This is also very risky to use just like the Query string method used in the early days. In this method the API key is sent as a part of JSON in the POST body, another disadvantage of this method is that the API Key is mixed with other data in JSON.
Example:
curl -X POST`https://example.com/endpoint/’ \-H ‘content-type: application/json’ \-d ‘ {“api_key”: abcdef12345”}’OAuth Authentication:
It is the most commonly used form of authentication in APIs. OAuth (open-standard authorization protocol or framework) is an authentication protocol that uses authorization tokens to verify the identity between consumers and service providers. It allows one application to interact with another without the need for passwords. The authentication process, commonly known as the “OAuth dance” works by the resource owner granting access to their information on the resource by authenticating a request token. The consumer uses the request token to obtain an access token from the resource. Once the client has an access token, it uses it to make authenticated requests to the resource until the token expires or is revoked.
Best practices when using OAuth:
Always validate redirect_uri server-side to allow only whitelisted URLs.Always try to exchange for code and not tokens (don’t allow response_type=token).Use a state parameter with a random hash to prevent CSRF on the OAuth authentication process.Define the default scope, and validate scope parameters for each application.JWT Authentication:
JWT or JSON WEB TOKEN is a mechanism used to verify the owner of some JSON data. It’s an encoded string, which is URL safe, that can contain an unlimited amount of data and it’s cryptographically signed so the data can be trusted because it is signed by the source. Although it is just a way of proving the integrity of the data so it must be used with SSL/tls. This is also most commonly used for API authentication. On the client-side, a token is created, using the secret token to sign it. Then it is passed as part of the API request, and the server will know it’s that specific client because the request is signed with its unique identifier.
JWTs can be broken down into three parts: header, payload, and signature. Each part is separated from the other by dot (.) and will have Header.Payload.Signature structure.
Example:
Authorization: Bearerey JhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5cBest practices when using JWT:
Use a random complicated key (JWT Secret) to make brute-forcing the token very hard.Don’t extract the algorithm from the header. Force the algorithm in the backend (HS256 or RS256).Make token expiration (TTL, RTTL) as short as possible.Don’t store sensitive data in the JWT payload, it can be decoded easily.After authentication comes authorization, the API must know and provide access according to the user, it is also called as role-based access control (RBAC). For example, admin users, ordinary users, etc… The most common way of doing this is determining the access levels by using policies and rules.
Example:
$roles = array (‘ADMIN’ => array (‘permit’ => array ( ‘/^((\/system\/(clouds|device)$/’ ), // The regular expression of which URLs are allowed to be accessed‘deny’ => array ( ‘/^(\/system\/audit)$/’ ) // Regular expression of which URLs are forbidden to access),‘AUDIT’ => array (‘permit’ => array ( ‘/^(\/system\/audit)$/’ ), //Regular expression of URL allowed to be accessed‘deny’ => array ( ‘/^((\/system\/(clouds|device).*)$/’ )));Additional access control best practices include:
Mapping between token formats as appropriate when crossing boundaries, such as an opaque token on the public side and a signed token on the private sideEnforcing authorization rules at each API siloEnabling access control rules for third-party applications acting on behalf of users and controlling the scope granted for each applicationEnabling the definition and enforcement of user privacy preferences and general data governanceThis is a very important step in API development. The rate limit is the number of requests a user is allowed to make in a given time period. Without a rate limit, anyone can use the API for as long as they want without any restrictions, also it brings in threats like DDoS / Brute-force attacks.
API owners typically measure processing limits in Transactions Per Second (TPS). Some systems may have physical limitations on data transference. Both are part of the Backend Rate Limiting. To prevent an API from being overwhelmed, API owners often enforce a limit on the number of requests, or the number of data clients can consume. This is called Application Rate Limiting.
Example:
const delay = interval => new Promise(resolve => setTimeout(resolve, interval));const sendMessage = async params => {await delay(1000);return axios(params);};Improper handling of errors can introduce a variety of security problems for a website. The most common problem is when detailed internal error messages such as stack traces, database dumps, and error codes are displayed to the user. These messages reveal implementation details that should never be revealed. So the errors should be handled accordingly and send HTTP status codes, Common error HTTP status codes are,
400 Bad Requests — This means that client-side input fails validation.401 Unauthorized — This means the user isn’t not authorized to access a resource. It usually returns when the user isn’t authenticated.403 Forbidden — This means the user is authenticated, but it’s not allowed to access a resource.404 Not Found — This indicates that a resource is not found.500 Internal server error — This is a generic server error. It probably shouldn’t be thrown explicitly.502 Bad Gateway — This indicates an invalid response from an upstream server.503 Service Unavailable — This indicates that something unexpected happened on the server-side (It can be anything like server overload, some parts of the system failed, etc.).One of the most common phrases in security is “Never trust a user input” and that is for a good reason. Input validation is the first step of checking the type and content of data supplied by a user or application. Improper input validation is a major factor in many web security vulnerabilities, including cross-site scripting (XSS) and SQL injection. Here are some best practices for input handling in REST API,
Use the proper HTTP method according to the operation: GET (read), POST (create), PUT/PATCH (replace/update), and DELETE (to delete a record), and respond with 405 Method Not Allowed if the requested method isn’t appropriate for the requested resource.Validate content-type on request Accept header (Content Negotiation) to allow only your supported format (e.g. application/xml, application/json, etc.) and respond with 406 Not Acceptable responses if not matched.Validate content-type of posted data as you accept (e.g. application/x-www-form-urlencoded, multipart/form-data, application/json, etc.).Validate user input to avoid common vulnerabilities (e.g. XSS, SQL-Injection, Remote Code Execution, etc.).Don’t use any sensitive data (credentials, Passwords, security tokens, or API keys) in the URL, but use the standard Authorization header.Use an API Gateway service to enable caching, Rate Limit policies (e.g. Quota, Spike Arrest, or Concurrent Rate Limit), and deploy APIs resources dynamically.Handling the data we send out is as much as important as handling the input data. If an application has improper output handling, the output data may be consumed leading to vulnerabilities and actions never intended by the application developer. Here is a list of things to consider in output handling,
Send X-Content-Type-Options: nosniff header.Send X-Frame-Options: deny header.Send Content-Security-Policy: default-src ‘none’ header.Remove fingerprinting headers — X-Powered-By, Server, X-AspNet-Version, etc.Force content-type for your response. If you return application/JSON, then your content-type response is application/JSON.Don’t return sensitive data like credentials, Passwords, or security tokens.API endpoints are typically a URL exposed by a server, allowing other systems to connect and consume its services. API endpoints are entry points into corporate networks and often provide valuable or sensitive information. This makes them an attractive target for attackers, This is a reason why endpoints are need to be managed properly, Some of things considered while managing endpoints are,
Avoid exposing management endpoints via the Internet.If management endpoints must be accessible via the Internet, make sure that users must use a strong authentication mechanism, e.g. multi-factor.Expose management endpoints via different HTTP ports or hosts preferably on a different NIC and restricted subnet.Restrict access to these endpoints by firewall rules or use of access control lists.