Now a day’s modern websites and mobile apps are built through more web services with APIs. By using APIs and web services every application functions around intelligent platforms every day for performance, scale, offload, and reliability to so-called “single-page” websites and mobile applications.
To protect the API certain protection should take like controlling API requests, inspect JSON and XML API calls to ensure web server remains available and the data on it is secure. Building custom or own REST API will need to consider the issues surrounding security, scalability, and reliability.
Security Preventions for Protecting API
- Protecting Simple App ID Key
- Secure the Communication Channel
- Prevent Call Tampering
- Securing the Secrets
- Handling User Credentials
- Switching to an OAuth2 Authorization
- Special Considerations for Mobile Clients
The simplest API key is just an application or developer ID string. To access an API, the developer registers his application with the API service and receives a unique ID to use when making API requests. For each API call, the client passes the API key within the HTTP request. An API key is part of the authorization header, for example:
authorization: key some-client-id
API key used to gather statistics about API usage such as call counting or traffic sourcing, can rejecting calls from non-app user agents. If the simple API request call and key are passes in the clear text, a man in the middle attack could successfully modify any API call or reverse engineer the API and can use the API key to create malicious API calls. If API key is compromised, it cannot be blacklisted without breaking existing application instances and requiring an upgrade for the entire installed base.
In this diagram, the client is a mobile application. The resource owner is the application user, and a resource server is a backend server interacting with the client through API calls.
There is a standard approach to secure an HTTP channel for confidentiality, integrity, and authentication through Transport Level Security (TLS). Client and server exchange verify each other’s public keys with mutual Transport Level Security (TLS). Client and server do know which public keys to expect by certificate pinning, so they compare the actual exchanged keys with the expected ones, rather than verifying through a hierarchical chain of certificates.
Client and server must keep the private keys secure. Once the keys are verified, the client and server negotiate a shared secret, a message authentication code (MAC) and encryption algorithms.
The SSL/TLS are secure communication channels which used for API to ensure the protection and its features are mentioned in below image:
Many aspects of such a channel are set through parameters and callback functions:
- The endpoint role: client or server
- Verification takes place in the authentication mode
- The TCP/IP module is provided in the Host-to-host communication channel
- The random number generator (RNG)
- The ciphers to use for encryption/decryption
- Session control functions
- 509 parameters for certificate-handling and key exchange
This module can be used to create an SSL/TLS server and client and to provide a basic framework to setup and communicate through an SSL/TLS communication channel. The attacks like Man in the Middle cannot be performed in TLS over client traffic when the victim is using an uncompromised mobile device.
Unfortunately, if an attacker can install your client application on a device he controls, he can use a packet sniffer to observe the public key exchange and use that knowledge to decrypt the channel to observe the API key and reverse engineer your APIs. While he may not be able to observe traffic on other clients, he can now create his own malicious app, freely calling your API over a TLS-secure channel. So even when using TLS, you will need additional security to prevent APIs being called from unauthorized applications.
To prevent web parameter tampering, when the user is authenticated it is authorization that grants him permissions to access particular resources. Authorisation in a REST scenario should be implemented on the server side. If a user Tom tries to modify purchase resources by sending an authenticated (e.g. using Basic HTTP Auth, authorized session cookie, etc.) POST request to /purchases/1 endpoint (supplied with appropriate payload). It is the server’s duty to validate if Tom is allowed to modify the entity (e.g. by checking if it was really Tom who made the purchase). If the permission is granted the server proceeds with the operation and responds with 2xx success HTTP status code. Otherwise, 403 error code will be returned informing that the user is not authorized to modify the given purchase. After authorization mechanisms are established an attacker tries to give malicious inputs to overcome authorization mechanisms.
The best improvement can be done is to separate the API key into an ID and a shared secret. The ID portion of the key is passed with each HTTP request, but the shared secret is used to sign and/or encrypt the information in transit. To ensure message integrity, the client computes a Message Authentication Code (MAC) for each request using the shared secret with an algorithm such as HMAC SHA-256. Using the same secret, the server computes the received message MAC and compares it with the MAC sent in the request.
An attacker can see the ID, without the secret, he cannot properly sign the request so an attacker can still deny or replay the request, but he cannot alter it. The communication channel should never have the secret stored but client and server know it. To further protect critical information from being observed, all or portions of a message can be encrypted before signing using key material derived from the shared secret.
The secrets will be protected by application package like SHARED_SECRET, this package backend can be compromised and further also extract the constant by a hacker in given time. To secure secrets first step is using code obfuscators to make it harder to locate and extract the secret constant. The second step would be encoding a static secret in some computationally simple way, cut that encoding into small segments, and distribute them around the binary. When checking the secret just reassemble and decode the secret in memory never save it in persistent storage.
The API secret should be secured at any cost, if it is stolen by any hacker all app instances will be compromised and have revocability issues too. Also, secure enhancing API security using application keys is first part but handling user credentials. When the client requests a user to provide user ID and password using basic authentication, which encodes and passes the credentials to the server. Valid credentials get logged and start a user session and return a user session key. When multiple authentications using same credentials should always return different key strings.
The popular way to authenticate user access by OAuth2 authorization token, which is secured by
- Switching to an Authorization Token
- Using separate User Authorization from Service
- Authenticate the App, not just user
- Should have short token life
The OAuth2 authorization framework defines several authorizations but most service providers follow the full specifications of developer implementation. The OAuth2 follows basic access authentication is called resource owner password credentials grant.
In this process, the mobile client can obtain the resource owner’s id and password credentials directly and also passes them to its back-end resource server. The back-end server validates and the credentials, and returns an access token to the client.
The above image explains about OAuth 2 basic authorization grant flow. JSON web tokens (JWT) which are secure, URL-safe method for representing claims and often used as OAuth2 access tokens. There are different ways that the token can be validated by the resource server. One common approach is to sign the JWT token using a secret known to both the resource server and the authorizing service, which in this case is the resource server itself. An attacker cannot modify a token’s claims without invalidating the signature.
A JWT contains a JSON formatted payload describing a set of claims by which the access token is also called a bearer token and is passed with every API call, typically as an HTTP request header.
The REST web services client uses XML or JSON to secure the API, but a better way to secure the web and mobile applications using JWT. Another step is to separate user Authorisation from service, security can be enhanced. By this way, the user credentials are never exposed to the client or the resource server. In OAuth the authorization and resource servers are separated, when the user submits his/her credentials the authorization server validates the credentials and redirects the access token through the user agent and back to the client. This can be a risky assumption. For example, if an attacker can compromise the user-agent, the attacker may be able to view the access token and subsequently use the token to make valid but malicious API calls.
The OAuth2 authentication using JWT access tokens has one great thing is short lifetime which means an expiration time it works for a limited period only. It refreshes the token after each expired and new token can be received along with an access token during initial authorization.
The above image shows the refresh tokens have longer lifetimes than access tokens but the resource owner will not need to authenticate again until the refresh token expires. If an access token is compromised, then its malicious use is limited to a short time with each refresh, in addition to the new access token, a new refresh token can also be sent. The old refresh token can be immediately blacklisted, or more complicated token rotation schemes can be used to frustrate the malicious use of an individual token.
The clients from both public and confidential are differentiated in OAuth2. A confidential client able to protect a secret, while a public client cannot make the same guarantee because the OAuth2 specification RFC6749 recommended only to confidential clients, so they can only use authorization grant flow, which uses client secret for authentication. Since public clients cannot protect a secret, they must use an implicit grant flow which does not authenticate the client nor allow refresh tokens. OAuth2 considers mobile apps to be public clients but most authorization service providers elected to implement the authorization grant flow for their mobile apps. This provides the user convenience of refresh tokens but at greater risk unless an alternative to client secrets is used for client authentication.
We have discussed how to secure REST API in a very simple example of API Key usage and iteratively enhanced the API protection to secure the communication channel and authorize both clients and users using API keys. Then We had the small introduction of JWT tokens and we moved keys to JWT tokens within several OAuth2 scenarios, in that final implementation, we will remove user credentials and static secrets.
We also combined both user and app authentication services, which provides a robust defense against API abuse.
finally,We have discussed a few threat scenarios and extended the authorization mediator to provide strong authorization.