Over the past decade, REST APIs have become a de facto architectural approach for modern web and mobile application platforms. They separate data and presentation layers, allowing systems to scale in size and feature sophistication over time.
However, as data moves across boundaries, security becomes a key concern for REST APIs containing sensitive information. One of the most straightforward ways to secure these APIs is to implement authentication mechanisms that control their exposure, mainly through user credentials and encrypted access codes.
To that end, there are five fundamental approaches to authentication in REST APIs that are important to understand. Each of these approaches present their own benefits, but also introduce different levels of complexity -- from straightforward credentials verification to proxy-controlled layers of permissions validation.
Basic authentication is an HTTP-based authentication approach and is the simplest way to secure REST APIs. It uses a Base64 format to encode usernames and passwords, both of which are stored in the HTTP header. This is an effective approach to set up various API access credentials when the priority is for an application to remain lightweight and simple. However, this approach doesn't offer out-of-the-box support for multifactor authentication (MFA) or dynamic, user-specific credentials, which would require the use of additional browser-based extensions and authorization tooling.
Thanks to its simplicity, Basic authentication enjoys widespread support across development toolchains, technologies and platforms. One of the key challenges with this authentication scheme, however, is that sensitive credentials often travel between systems unencrypted. Hence, using Secure Sockets Layer (SSL) and Transport Layer Security (TLS) channels is a must when sharing sensitive data between multiple web applications -- especially third-party applications -- because threat actors can intercept traffic moving through unsecured channels and steal credentials.
The API keys approach is a variation of the HTTP Basic authentication strategy. This approach uses machine-generated strings to create unique pairs of identifying credentials and API access tokens. API keys can be sent as part of the payload, HTTP headers or query string, making them a good fit for consumer-facing web applications.
The benefit of API keys is that they decouple API access from the necessary credentials and validation tokens. Those credentials and tokens can be revoked and reissued as needed, such as if a user's permission level changes, or there is reason to believe the information has been compromised.
Unfortunately, API keys are susceptible to the same risks as Basic authentication, in that hackers could intercept and exploit the associated credentials. While they do provide a unique identification mechanism for front-end user interactions that can both apply and revoke credentials on demand, the simplicity of its design inhibits its ability to support layered authentication or MFA.
Another form of REST API authentication known as hash-based message authentication code (HMAC) is often used when the integrity of the REST API's data payload is a priority. HMAC uses symmetric encryption -- sometimes called single-key encryption -- to determine the hashing of a REST API's data payload. It then generates a unique code associated with that hashing and attaches that code to the relevant messages. The caller and receiver will share the key and use it to ensure the integrity of the data within the payload.
To illustrate, here is a basic example of HMAC authentication:
- A developer uses URL addresses to provide access to a REST API's data but wants those URLs to expire after a certain period.
- The session duration and expiration timestamp is placed in the URL and signed using an HMAC encryption key.
- The client server calling the API uses the encryption key embedded within the URL address to validate the data payload. Both the client and server will mark the URL as expired after the indicated time limit has passed.
- If the client or server detects any unexpected changes to the URL or receives a message that uses a previously expired URL, it will alert the API of a key signature mismatch and prompt it to deny access requests.
The HMAC approach to REST API authentication requires little operational overhead in terms of management or tooling. It's useful in scenarios when you can directly control both the client and server applications involved. However, it can become challenging to store encryption keys securely when dealing with mobile and web applications that are outside of your control.
For example, a mobile application that uses URL-based HMAC encryption keys to facilitate data requests is a vulnerable target for attacks, especially if those encryption keys don't contain a fixed time frame for expiration. If a threat actor acquires that unique key, it can easily coerce the application to accept a malicious data payload simply by embedding the stolen encryption code within the URL.
OAuth (specifically, OAuth 2.0) is considered a gold standard when it comes to REST API authentication, especially in enterprise scenarios involving sophisticated web and mobile applications. OAuth 2.0 can support dynamic collections of users, permission levels, scope parameters and data types. It's a preferred approach for organizations looking to secure large numbers of REST APIs that contain sensitive information.
OAuth 2.0 creates secured access tokens that are refreshed periodically using a series of procedural verification protocols known as grant types. These grant types act as proxy authentication mechanisms that direct the flow of API access requests without exposing the underlying credentials, tokens and other authentication information associated with those requests.
The five major grant types in OAuth 2.0 are:
- Authorization Code
- Proof Key for Code Exchange (PKCE)
- Client Credentials
- Device Code
- Refresh Token
In addition to recycling access keys, OAuth supports the concept of scopes, a method of limiting an application's access to a user's account and associated credentials. This helps control the degree to which third-party applications can access a user's account data. Another advantage of this approach is the ability to define multiple scopes and issue unique tokens for different types of requests and permission levels.
OAuth can use a JSON Web Token (JWT) to perform payload integrity checks using a process similar to the HMAC authentication approach discussed in the last section. JWT tokens securely store encrypted, user-specific data, and then transmit that data between applications as needed. Because these web tokens can be signed, it's possible to imbue the token with new user roles and permissions once the user has been authenticated. Tokens can be readily invalidated or recycled as deemed fit.
Adding a shared symmetric key across application services can help all participating services verify the integrity of the token concurrently, rather than through a series of validation checks. This mitigates the risk of creating a single point of failure in the validation process. However, managing the distribution of symmetric keys required for payload integrity verification is a daunting security challenge in dynamic, highly scalable application environments, as described in previous sections.
OpenID Connect is an open standard authentication protocol built on top of OAuth 2.0. It provides a simple way for a client application -- referred to as a relying party (RP) -- to validate a user's identity. This single standard facilitates information sharing without the need for explicit management of credentials for third-party applications.
REST APIs covered by OpenID Connect become usable once users have been authenticated by the RP. Eventually, the API associated with that RP can perform validation using its own variation of the OAuth grant types mentioned above. These grant types are:
- Authorization Code
While OpenID Connect always resides under the API provider's control, multiple RPs can make use of these grant types on their own, as needed. This approach is ideal for REST API providers that can't support the complexity of dynamic, enterprise-level credential management tooling, but do need to securely share user data across a variety of third-party web applications.
Choosing a REST API authentication approach
Given the variety of REST API authentication approaches, carefully consider the pros and cons of each approach against your unique application requirements before adoption. The HTTP-focused approach of Basic authentication is great for restricting public access to low-risk data and resources, but still needs at least some level of security controls. API keys, meanwhile, lends itself to scenarios where API providers need to identify individual consumers and regulate their permissions as needed.
The sensitivity of data is, of course, a major part of the decision. While HMAC provides a fair degree of data payload integrity support for relatively contained operations, OAuth is a better fit for complex use cases that involve rotating access tokens and adjustable permission levels. For those who reside in the middle, OpenID provides a nice balance between OAuth's dynamic access management and the simplicity of HMAC.
No matter the approach, it's always a good idea to limit REST API exposure to secured SSL and TLS channels. Avoid transmitting sensitive credentials as embedded parts of API data payloads, URLs or querystrings, as applications may inadvertently store copies of these credentials through automated logging procedures. Finally, automate procedures such as encryption key rotations, as a manual approach may result in repetitive oversights and errors.