OAuth2 Access Tokens vs API Keys — Using JWTs (2024)

8 min read

·

Jul 15, 2020

--

OAuth2 Access Tokens vs API Keys — Using JWTs (2)

There are several approaches to securing APIs. Every API Gateway vendor supports the same core set of API security mechanisms. API Keys and OAuth2 are two examples of these authentication (plus authorization) mechanism. When should one be used over the other? What are the differences between the two if they both use JSON Web Tokens (JWT)? I was at a client site a while back when this topic came up. Okay, it was actually several years ago. I’m that far behind in writing blog posts:). Regardless, the topic is still relevant.

Before we jump into API Keys and OAuth2, we need to talk about Bearer Tokens. API Keys and OAuth2 Access Tokens are both forms of Bearer Tokens.

I have previously described the concept of a Bearer Token, but it didn’t much attention. So, let’s do that now.

A Bearer Token is a string of bytes/characters that may be opaque or have a higher-level structure that uniquely identifies a user or application of a system. The token can be used in this manner because the user or application has it and no one (nothing) else does — it is known only to the holder and the Identity Provider. Hence, the name, “bearer” token — only one principal is holding it. Of course, this assumes that the token has not been compromised in someway.

Assuming the token has not been compromised, the act of providing the token in a request means that the request came from the user or application to whom the token belongs.

In its purest (though, hardly securest) form, this token is just a unique string of bytes known only to the holder (bearer) and the Identity Provider, which does not use any type of digital signature or encryption within its structure. Some of the leading API Management platforms do this. That’s one of the reasons why you tend to see the big deployments of those platforms integrated with one of the big identity provider vendor’s stacks.

A more useful form of Bearer Token would include an embedded digital signature and be encrypted. The digital signature confirms that they token came from a trusted source. The use of encryption means only systems meant to be able to read the token can read it; this is only useful if there is a higher-level structure that supports claims data. From a practical standpoint, most Bearer Tokens are going to be digitally signed, but not encrypted. The performance and operational overhead associated with encrypting tokens is usually not worth the marginal security improvement.

To protect the Bearer Token, it must only be passed over encrypted channels — generally, this means the use of TLSv1.2 or better at every network hop. The use of TLS will not protect against intermediaries who are actually bad actors. So, any node that is going to be able to read the token as it traverses the system must be trusted. The use of an encrypted token would help protect against intermediaries that are bad actors.

If a Bearer Token has a higher structure to it such as being a JWT, then it is possible to convey additional information about the application or user that token describes. This additional information is called claims. This idea is used extensively in OpenID Connect. A SAML2 Assertion or IBM LTPA2 tokens are also examples of Bearer Tokens.

Again, API Keys and OAuth2 Access Tokens are both forms of Bearer Tokens. JWT, SAML2, or IBM LTPA2 tokens could be used as OAuth2 Access Tokens or API Keys, but one doesn’t usually see the last two used for either purpose.

We’ve covered this topic many times in earlier blog posts. Check out:

  • Understanding OAuth2
  • The Benefits of JWTs as OAuth2 Access Tokens

For most of my writing on this topic, I have assumed that OAuth2 Access Tokens are JWTs. This doesn’t have to be true, but typically is in practice.

Regardless of whether the OAuth2 Access Token is a JWT or something else, it is a Bearer Token.

I have mentioned API Keys several times, but not formally defined the concept in earlier blog posts. So, we’ll go ahead and do that now.

An API Key is a unique identifier that authenticates an API Consumer (whether the caller is an application, user, or developer), which is usually long-lived so that it is easy to manage for the API consumer. For production environments, the key will usually be tied to an application identity. API keys allow an application to access a resource (API) independent of what user is currently using the application. This is usually the simplest type of API security mechanism. Does this sound like a repeat of the Bearer Token definition given above? It mostly is, just specific to the API space.

The size of the key/token can vary widely. As a Bearer Token, the API Key may be an opaque token (randomly generated sequence of characters) or some type of spec-defined token format — like JSON Web Token (JWT). Again, this is a fairly generic concept.

While it is simple, it is a blunt instrument in terms of Authorization. Either the caller has access to all of something or none of something. That something is highly context-specific. A system can tie data to a specific API Key, but cannot be more nuanced than that. Either the request (key, identity, caller) has access to all data tied to that key or none of it. In this case, there concept of individual users simply does not exist.

If you are attempting to issue API Keys per user, it is likely that OAuth2 or OpenID Connect would be better fit for your use case.

For the very paranoid, the API Key may need to based upon modern cryptographic principles. Important safety tip: a string of randomly generated characters doesn’t generally meet the criteria. Though, using a cryptographically secure pseudo-random number generator is vastly superior to using one that is not where security is concerned; this means that it is really hard to guess what the next random number would be. With just a little more effort, you could issue X509 Private-Public Key Pairs to all API Consumers. Then, use that key pair as a client certificate during a TLS handshake to authenticate the client. Whether or not this is warranted depends upon the type of data and functionality being exposed through the API. Using X509 certificates on a potentially large scale in this manner requires a level of sophistication surrounding PKI management that many organizations do not possess. Also, many API Management solution do not ship with PKI support for this use case out-of-the-box, but can be customized to do so.

Generally, the key will be attached to API requests via RFC6750, which means that the API Key is included in the Authorization header in the following format:

Authorization: Bearer abc...123

The API Key that is issued to an application is used across all instances of that application for all calls to the API. For this discussion, let’s assume that there is one API in play. The API Key can only be securely used if it has a server-side component where the API Key can be kept secret. If you attempt to embed an API Key in a native application, browser-based Javascript application, or anything else that involves distributing the API Key across many instances of a client application on end user devices as part of the application code bundle, that key can be compromised. This is because these are all examples of what the OAuth2 spec calls Public Clients — something that can’t keep a credential like an API Key secret. This is an important; so, I am going to repeat it in all caps: DO NOT EMBED LONG-LIVED, APPLICATION-SCOPED API KEYS IN PUBLIC CLIENTS THAT CANNOT PROTECT SECRETS. DO NOT HARD-CODE YOUR API KEY IN YOUR NATIVE MOBILE (OR DESKTOP) APP or JAVASCRIPT APPLICATION IN A BROWSER. IT IS TRIVIAL TO RETRIEVE THE API KEY. Some organizations do this, but rotate the keys frequently believing that this will be enough to prevent competitors from reusing the keys in their own applications. At best, it caused the competitor to get errors for a couple of hours every few weeks. Don’t rely upon an approach like this. It isn’t secure.

If one attempts to issue API Keys to each individual user for an application, this could be done in a secure manner, but how are keys issued, distributed, and rotated at a large scale? The OAuth2 spec and its use of Access Tokens addresses this problem. This is where OAuth2 Access Tokens are a better solution than API Keys.

If one is using JWTs as API Keys, then one has to consider how the tokens are issued and used. Let’s assume that the JWT contains claims that are useful to the application; otherwise, what’s the point of using JWT? Therefore, the JWT will have to be digitally signed. In order for the signature to be trusted, the token must come from a source that is trusted by both the application (or user) and API. So, we need an Identity Provider (IdP) that can securely issue JWTs. Now, we have to somehow authenticate the user or application against this IdP. This negates the whole point of using an API Key and we once again start seeing something that looks very much like OAuth2 Access Tokens.

Assuming that we are still trying to use JWTs, what is the life time of the JWT acting as an API Key? The shorter the lifetime, the more secure the solution is, but API Keys tend to be long-lived tokens. So, what are we accomplishing? We once again are seeing something that starts to look like OAuth2 Access Tokens.

It is true that you can build an IdP mechanism into your API layer that issues JWTs (that will act as API Keys) based upon user or application credentials. But, this approach starts to blur the line between what most practioners would consider to be an API Key and what is now in play. I would argue that you have simply constructed something that could be described as OAuth2-esque (maybe psuedo-OAuth2). So, why not just embrace OAuth2 or better yet OpenID Connect if your use case involves end users?

  • Use API Keys to describe applications, not end users, for production systems.
  • If your API Keys are used to describe applications, the same thing can be accomplished with OAuth2 Authorization Client Credential Grant (with spec-defined token rotation, support for basic authorization decisions, and more). The application is issued a client_id and client_secret (or other credential) instead of an API Key.
  • You could use JWTs as an API Key, but it’s very likely your use case is going to evolve into something that looks very similar to OAuth2.
  • If end-users need to be uniquely identified, use OAuth2/OIDC.
  • JWTs as OAuth2 Access Tokens are quite common among the major IdP vendors.
  • A JWT as an API Key probably only makes sense for short-lived tokens/keys. But, API Keys tend to be longer lived than OAuth2 Access Tokens (typically by a very long period of time). If you need to rotate tokens often, look at OAuth2.
  • Issuing a JWT that is trusted requires an IdP; authenticating against the IdP requires another set of credentials. This negates the point of using the API Key to begin with.
  • Do not embed API Keys (of any type) in applications that cannot keep the key a secret. This is done often, but easy to compromise.

Bottom-line: I generally recommend the use of OAuth2 as a starting point for API Security (whether JWTs are in use or not). I’ve never used JWTs as API Keys in my projects.

Image: Ankor Wat / Rob Tiggelman

OAuth2 Access Tokens vs API Keys — Using JWTs (2024)
Top Articles
Latest Posts
Article information

Author: Msgr. Refugio Daniel

Last Updated:

Views: 6470

Rating: 4.3 / 5 (74 voted)

Reviews: 81% of readers found this page helpful

Author information

Name: Msgr. Refugio Daniel

Birthday: 1999-09-15

Address: 8416 Beatty Center, Derekfort, VA 72092-0500

Phone: +6838967160603

Job: Mining Executive

Hobby: Woodworking, Knitting, Fishing, Coffee roasting, Kayaking, Horseback riding, Kite flying

Introduction: My name is Msgr. Refugio Daniel, I am a fine, precious, encouraging, calm, glamorous, vivacious, friendly person who loves writing and wants to share my knowledge and understanding with you.