5 Steps Toward Military-Grade API Security

Curity
9 min readAug 2, 2024

--

The article was written by Curity’s Gary Archer and originally published on The New Stack

Cyberattacks against software are becoming increasingly sophisticated. Advancements in technical tooling provide many ways for malicious parties to automate attacks. For many organizations that provide digital services, counteracting threats can feel daunting. How do you best manage security when you have limited resources and want to focus on your business objectives?

Let me explain an iterative approach to embrace a “military-grade” security mindset. I will show that this does not require you to be a wealthy organization that allocates major resources to combating cyber threats. Instead, military grade is an approach where you continually review your security and strengthen it whenever it is practical. Examples might be using a stronger form of cryptography to secure connections, a more secure form of user authentication or a newer security design pattern that deals better with a particular threat.

The main goal should be an architecture that can protect your digital assets in ways that stand up to future threats. The best way to secure digital services is to start with a solid foundation and then ramp up security to military grade when possible. This enables you to keep your security up to date.

Step 1: Use Security Standards

You should implement application security based on standards vetted by many experts. The OAuth 2.0 authorization framework from RFC 6749 provides such a setup. OAuth is a family of specifications that maps to security use cases for organizations. These standards are continually evolving to stay up to date with new threats.

OAuth is centered on protecting data using an API message credential called the access token. This token is issued by a specialist security component called the authorization server. The access token is designed to be locked down based on business privileges and cryptographically signed by the authorization server. Clients request an access token from the authorization server and then send the access token to API endpoints. User-facing apps trigger user authentication at the authorization server when receiving an access token.

Using OAuth enables you to implement a zero-trust architecture that considers both API and frontend application best practices. An example deployment is illustrated below, where APIs and the authorization server are hosted behind an API gateway. APIs require an access token in the JSON Web Token (JWT) format and cryptographically verify the token on every API request. APIs then trust claims in the access token and use them for business authorization.

In this example, client best practices are also followed. Internet clients receive opaque (reference) access tokens that do not reveal access token data since that data is only intended for APIs. Browser-based apps often send an HTTP-only cookie when making API requests, rather than using access tokens directly.

The API gateway is a hosting best practice. Expose only the gateway to the internet rather than directly exposing APIs and the authorization server. The gateway can then perform common security checks like rate limiting. It can also perform token translation during API requests to convert opaque tokens or cookies sent from clients to JWT access tokens. This unifies your API security so that APIs only need to receive JWT access tokens, regardless of the client.

When an organization is new to OAuth, there is a learning curve to implementing its flows due to the distributed nature of the security. It takes some time to understand the coding techniques and deploy the overall system, but once you have a token-based architecture, your base setup enables you to evolve your security to use military-grade features.

Step 2: Strengthen API Credentials

OAuth can use strong security profiles such as those provided by FAPI 2.0. In some industries, such as banking and health care, it may be mandatory to implement this type of profile. Strong security is also recommended for other organizations.

First, you should focus on robust API access control. When using OAuth, an attacker cannot create valid access tokens for your APIs since doing so would require stealing the authorization server’s cryptographic private key. Yet, by default, access tokens are bearer tokens, meaning APIs cannot distinguish between legitimate or malicious callers. So, if an attacker somehow intercepts an access token, they can send it to your API to gain access to data.

To prevent this, use proof of possession tokens when possible. A common use case is when you provide APIs to business partners. In this case, you can use OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens specified by the RFC 8705 standard. The client authenticates at the authorization server with a client certificate and gets an access token bound to the client certificate. On subsequent API requests, the client must send the same client certificate on every API request, along with the access token. The API can then distinguish between a legitimate request, which provides proof of possession of the private key, and a malicious request that does not, and deny access to malicious callers.

An alternative proof-of-possession option you can consider, which does not require you to manage client certificates, is demonstrating proof-of-possession at the application layer (DPoP). This works in a technically similar manner to client certificates, except that the client generates a runtime key pair in the JSON Web Key (JWK) format. To authenticate, the client creates a proof JWT that it signs with its private key, and the access token is bound to the client’s proof-of-possession key. On every API request, the client must send a new proof JWT that is signed with the same private key. The API can again distinguish between a legitimate request, which provides proof of possession of the private key, and a malicious request that does not, and deny access to malicious callers.

Since proof-of-possession verification is a generic process, you can implement it in your API gateway by writing a small API gateway plug-in. This can help you share such logic across multiple APIs while keeping your API code business-focused.

Step 3: Strengthen Client Security

When evaluating client security, you must address environment-specific threats. In the browser, military grade starts with ensuring the best protections against token theft, where malicious JavaScript threats, also known as cross-site scripting (XSS), are the biggest concern. To reduce the impact of an XSS exploit, it is recommended to use the latest and most secure HTTP-only SameSite cookies to transport OAuth tokens to your APIs.

Use a backend-for-frontend (BFF) component to issue cookies to JavaScript apps. The BFF should also use a client credential when getting access tokens. If you use OAuth to secure single-page applications (SPAs), the token handler pattern can be a convenient option to enable this with low impact. A utility API then does the cookie issuing on behalf of its SPA without adversely affecting your web architecture.

In an OAuth architecture, clients obtain access tokens by running an OAuth flow. To authenticate users, a client uses the OpenID Connect standard and runs a code flow. The client sends request parameters to the authorization server and receives response parameters. However, these parameters can potentially be tampered with. For example, an attacker might replay a request and change the scope value in an attempt to escalate privileges.

To protect against request tampering, you can use Pushed Authorization Requests (PAR) from RFC 9126. This is just another form of the code flow, requiring some minor code changes. To use PAR, the client first sends a POST request to the authorization server, along with a client credential. The client can then receive a request_uri and use it during its browser redirect. To prevent replay attacks, each request_uri can only be used once.

An equivalent solution for protecting responses is to use the JWT Secured Authorization Response Mode (JARM) from the OpenID Foundation. The authorization response parameters are received in a signed JWT so they cannot be tampered with. You can use PAR and JARM together without any additional key management since only the authorization server’s keys are used to sign response JWTs.

Step 4: Strengthen User Authentication

OAuth standards do not provide recommendations on how to strengthen user authentication. Yet, in practice, the authorization server should enable your user-facing apps to use solid security for user logins, such as by applying multifactor authentication. Weak authentication methods are vulnerable to account takeover attacks, where a malicious party gains access to a user’s data.

Start by phasing out passwords since they are the source of many security weaknesses. For example, a phishing attack might steal a user’s password from one site and then use it successfully on another site. Even worse, there have been many online occurrences of server breaches that revealed the passwords of many users.

A military-grade alternative would instead be based on asymmetric cryptography, where keys used for one server origin cannot be used at another. This means users keep their private keys locally, and servers only deal with public keys. This type of solution is phishing-resistant and does not require servers to store user secrets.

For many organizations, the most convenient way to harden user authentication is to use passkeys based on the WebAuthn specification from the FIDO alliance. Passkeys are now provided by the main desktop and mobile operating systems, so there are no difficult user prerequisites. Passkeys can also use the same account recovery behaviors as passwords.

Step 5: Use Extensible Security

Your application security is not static and will evolve as newer threats are discovered and best practices are designed to mitigate them. You will occasionally need to introduce additional security components or integrate with third-party systems. Therefore, your security architecture should be extensible and able to use newer security capabilities when they become available.

In the future, there will likely be stronger ways to implement OAuth-secured mobile apps. A current concern is that they usually cannot store a client credential safely, so they operate as OAuth public clients by following OAuth for Native Apps as published in RFC 8252. The most secure option is to use a claimed HTTPS scheme-based redirect URI to prevent a malicious app from potentially impersonating the actual app. Yet newer Android and iOS devices now support client attestation features that can prevent impersonation. Apps can cryptographically sign a challenge to prove their identity and receive a JWT response from a cloud service. This JWT could be sent to the authorization server at the beginning of a code flow to enable a hardened mobile flow.

Authentication will continue to need hardening over time. Although passkeys improve upon the security of passwords and are suitable for many digital services, you do not really know who the user is. When you need real proof of a user’s identity, your authorization server should support extensibility to enable you to integrate with third-party systems that provide identity proofing. In the future, authorization servers that support authentication using digital credentials will enable you to receive real proof of user identity from trusted third parties.

To counteract automated attacks, I expect systems that track usage patterns to become more widely used in security decisions. These patterns can be applied during both user authentication and API access. A policy-based approach to authorization might be the preferred way to implement this type of dynamic authorization requirement. A policy engine such as Open Policy Agent might consult the usage data and return a risk score to applications, which could then be used to make security decisions.

Of course, these types of integrations would typically only be needed once in a while. The important behavior is that your setup is able to adapt to new requirements and plug in new security behaviors when required.

Learning Military-Grade Security

Military grade is an approach to software security that uses strong cryptography and up-to-date standards that are vetted by many experts. To integrate military grade, you use specialist security components that implement the complex standards needed.

Security for digital services requires a security architecture with a separation of concerns, where you outsource the complex security from application-level components. Once you have the right setup, it is straightforward to upgrade to military-grade features, since only minor changes to application code should be needed. Follow these main steps and you have a future-proof setup that can adapt to new requirements:

  • Use security standards
  • Strengthen API credentials
  • Strengthen client security
  • Strengthen user authentication
  • Use extensible security

At Curity, we work on security all day, every day. You can read our website articles or run our code examples to learn more about modern security standards and design patterns. Our resources will enable you to improve your OAuth architecture or upgrade areas of your current security to military grade. Our resources are based on standards and not tied to our product:

--

--

Curity

Curity is the leading supplier of API-driven identity management, providing unified security for digital services. Visit curity.io or contact info@curity.io