API-the-Gluu-way

Ideal API Security

API’s are ubiquitous, so you’d think how to secure them is an established practice–except it’s not. The goal of this blog is to lay out how Gluu thinks about API security at a high level, in particular, how to use OAuth scopes to secure endpoints. We’ll start with API authentication. Then we’ll define a three-step approach to API security with enough flexibility to address a range of requirements.

 API Authentication

Authentication is who you are. But there are a few “who’s” in an API ecosystem:

  • A human (end user) using a web or mobile application to call an API
  • The software (“Client”) that is calling the API (the web or mobile application itself)
  • A central authorization server (“AS”) that issues “tokens” that protect the API. For this blog, a token is a piece of serialized data to represent identity or permissions.

Most of the time, these participants must prove who they are in order to establish “trust” –the most elusive quality of systems connected to each other via the Internet. If we conflate humans and software, confusion ensues. 

The most common modern way to authenticate humans is by presenting web pages in a browser.  Sometimes a mobile application may use the platform browser SDK, so it doesn’t look like you’re leaving the mobile app.  New protocols that don’t use the browser are also evolving. Most modern software represents an authentication event with a cryptographically signed JWT.  For example, the OpenID Connect identity layer defines an “id_token”–a standard JWT to represent the details of who was authenticated, by which AS, at what time. An id_token may include additional optional information like the authentication mechanism (“acr”) or “user claims” such as the person’s email address. For the purpose of API security, keep in mind that the API endpoint consumes data about an authentication event that already happened.

API’s are stateless, so the Client must prove its identity every time it calls an endpoint. One way to do this is to send client credentials (e.g. API key and secret) with every call. Most developers are familiar with using basic authentication. However, ideally, the Client authenticates less frequently by obtaining a token from an AS and presenting this token with each request. An API gateway does not have to validate tokens on each calls if they are cached, which saves time. Tokens enable the AS to do more complex authentication using asymmetric credentials, which are hard for “normal” API developers to implement.

The AS also needs to prove its identity. The AS verifies its server key during the establishment of the https session using Transport Layer Security (“TLS”). Without TLS, API security is a farce. API developers must validate the certificate of the AS. In some cases, TLS authentication is mutual–the AS also validates the certificate of the client. 

Step One:  Security for Developers that design an API

The right time to start thinking about API security is in the design phase. For many developers, this means using the OpenAPI format (i.e. Swagger) to define the endpoints, parameters and other details of the API. At the API level, we define that OAuth is used as a security scheme. Using the Janssen Config API as an example:

But this doesn’t tell us which scopes are required for which endpoints. Going back to the config API as an example, let’s look at the FIDO Config endpoint:

To do an HTTP GET for the fido/config endpoint, the API requires a token with the https://jans.io/oauth/config/fido2.readonly scope. While this type of security does not always provide sufficient granularity, it is powerful.

You probably remember the idea of “prime factorization” from your early math classes. Factors are the prime numbers you multiply together to get another number; for example, 6 is the product of 2 and 3. It may be helpful to think of scopes as the factors of your authorization policies.  To the extent we can factor out certain common policies, we can reduce the amount of authorization code in our application or policy management infrastructure.  Thinking about OAuth scopes may impact the URL namespace of your API.  

Step Two:  Security for Developers that call an API 

Developers need to get client credentials to call your API. These credentials, when presented at the AS, need to request tokens with certain OAuth scopes. How do we make sure that developers get the right level of access, i.e., that their client credentials can request only tokens with the scopes they need to do their job? This is where a little documented feature of OAuth comes into play: software statements. These special-purpose JWT’s are presented to the AS during client registration. Unfortunately, the OAuth specifications do not suggest what claims are contained in the payload of the software statement, but certainly they can contain authorization data. For example, a software statement may have a claim like this:

“authorization”: {“allowed_scopes”: [“read”, “write”]}

The next question you might wonder is: who issues these software statements? Well, that depends on who is trusted to control access to the API. In an enterprise API ecosystem, the software statement may be issued by the security department. Remember, developers (… humans), request software statements, and use them to obtain client credentials, which are then embedded in software. Thus, the process for obtaining software statements can be automated or manual. Another good example are open banking ecosystems, where the software statements are issued by a regulator.  

It would make a lot of sense for API management software that is used to design API’s to also create a workflow to review and issue software statements. This is one of the missing pieces of the puzzle in most API security solutions. It’s a component of managing Internet trust–who is trusted to call your API.  And not surprisingly, it’s an oft neglected component.

Step Three: Security Enforcement at Runtime

In Step 1 we defined what OAuth scopes are needed to call an API. In Step 2 we defined how developers can register clients authorized to obtain tokens with the right scopes. In this Step 3, the rubber meets the road: the client obtains a token and presents it in the API request. We have at least three tactics we could implement to control access: 1. the AS can decide on the fly (based on context) what claims (e.g. scopes) to mint into the access token; 2. the API or API gateway can determine whether to allow access by comparing the scopes in the access token to those specified in the design; 3. the API can send the access token (and other information) to an external policy decision point (“PDP”) to make an access decision. 

In the Gluu Server, we have an interception script for “token introspection” which is used to customize the content of the access token. Note, although the script is called “introspection”, it is also invoked for JWT access tokens.  Typically, scopes are added to a token based on the request, provided that the client is authorized for these scopes. However, the AS can decide not to issue scopes based on other contextual information. For example, perhaps the client is making the request from a risky IP address, or a fraud score is too high for a given transaction. 

If you are wondering where an API gateway comes into the picture, enforcement of the scope requirements is a good place. The API gateway sees the token and can introspect it (or validate the signature of a JWT access token). Ideally, an API gateway that does this would allow Boolean expressions to define which scopes are required (or not allowed). For example, perhaps to POST to an API endpoint, the client needs to include a token with the READ scope and either the FIDO or OTP scope.  Note: both the endpoint and the method are relevant for access control. We can have two identical endpoints (e.g., https://example.com/item/12345), with different permissions for the GET and DELETE methods. 

There are a number of authorization Policy Decision Points (“PDP”) available today. For example, Styra, Oso, Axiomatics, and PlainID come to mind.  Centralizing policies can have significant advantages–especially if you have many policies. For example, maybe you need to run a report to list all the policies that impact healthcare of foreign employees. If you have thousands of policies expressed in the API code, it may be hard to get this data. Having your policies in one place, in a declarative syntax, makes policy management easier. In terms of implementation, either the API gateway or the API code could call a PDP. The other nice thing about using a PDP is that you can make policies about all sorts of data, not just OAuth scopes. 

Conclusion

Hopefully this gives you a better idea of some of the elements of an API security undertaking. A successful program is not just a technology program. Trust requires human involvement. But after the humans step back, today we have more tools than ever to make authorization performant and scalable.