JWT vs OAuth

We are in the process of building B2B API and evaluating the security model OAuth and JWT. I'm keen to understand the parameters that are critical to decide which approach to go for ?

Solved Solved
6 5 76.8K
1 ACCEPTED SOLUTION

The question is a common one, but it isn't quite sensible. JWT is a type of Token, and OAuth is a Framework that describes how to dispense tokens.

What do we mean by "framework"? Just the sequence of requests and responses, and the formats of those, that can and ought to be used to request tokens. OAuthv2 describes separate "flows" or grant types for different scenarios, and has different extensions (like PKCE) for extending the security of particular flows.

The result of a request-for-token via an OAuthV2 grant is... a token. That thing then is employed as a "bearer token" which means, any party that holds the token, can present it when making an api request-for-service (eg, "what's the balance on my stored value card?") . As a Bearer token, it works like cash money. If you're holding it, you can use it. (Though unlike cash money, a token is not use-it-and-lose it. Maybe a better analogy is an all-day ticket-to-ride on the public transit system, or an all-day ticket for Disneyworld.)

JWT is a particular type of token. Typically JWT are signed, and consist of three parts: the header, payload and signature, each base64-encoded and then concatenated. The result is a long string of base62 characters. JWT fill different roles; they can be "Identity tokens", which are tokens issued by an identity provider to a client application that provide information about an authenticated user (like name, email address, and other claims or attributes). JWT can also be used as "access tokens"; in this usage, the client application presents a JWT to a service as credentials with a service request. The service provider can evaluate whether to provide service based on the claims in the token. The distinction between ID token and access token is primarily one of intent, not of form. In some cases, a client may authenticate a user to an IdP, and receive an ID token in response. Then the client may send that same token as an access token to a service provider. Same token, different uses. JWT can absolutely be used as tokens within the OAuth framework, in other words, as an OAuth Bearer token. This is a very common practice. In light of that, "JWT vs OAuth" is a comparison of apples and apple carts.

People might think "OAuth token" always implies an opaque token - a random sequence of alphanumeric characters that contains no inherent meaning - that is granted by a OAuth token dispensary, that can then be validated only by that same OAuth dispensary system. But this is not the only kind of OAuth token. An opaque token is one kind of token; JWT can be used as a different kind of OAuth token. The OAuth specification does not require tokens to be opaque.

Today, the OAuthV2/GenerateAccessToken policy in Apigee generates opaque tokens. It returns a token consisting of a random sequence of alphanumeric characters (often 28 characters in length, though the size is tunable), and the holder has no idea what the token signifies. This is the meaning of "opaque". It's not that there is an obscure, hidden way to "decrypt" or unscramble the token and Apigee simply doesn't document it. It's that the token is really a random string. It's a pointer to some information describing who the token refers to, what the token should permit, when the token expires..., and that information is held in a secure store, inside the Apigee black box. Therefore, we call the token "opaque". To USE the token, the holder must present it back to the token dispensary, because the original dispensary is the only party that can relate the opaque string to the meaningful information associated to it. Bottom line: think of an opaque token as a pointer to information that is held only by the token dispensary.

JWT, in contrast, are not opaque. (Now I will confine this discussion to just signed JWT. There are also encrypted JWT, we won't talk about them here). The JWT is not a "pointer" or reference to information. It actually contains lots of specific information, that can be extracted and interpreted by any party that has the token. Because the JWT contains real information, a JWT can be large; 300 bytes, 500 bytes, or more, depending on the claims contained within it, and the algorithm used to sign it. When people say "JWT are self-validatable" what they mean is, any holder of the signed JWT can open it, validate it, and then make authorization decisions based on the claims presented in it. Validating the JWT means: verifying its structure, decoding the base64 encoding, verifying the key is correct, verifying the signature, verifying the validity times (eg, the token is not expired), then verifying the required claims are present in the token. It's not a simple thing, rather a multi-step process, but of course there are plenty of libraries in various programming languages that help with this, if you are writing your own code.

In Apigee, the VerifyJWT policy helps you verify a JWT from within an Apigee API proxy. The GenerateJWT policy allows you to generate a JWT from within a proxy.

Any actor with access to the appropriate keys can produce a signed JWT, and any holder or receiver with access to the required keys can verify a signed JWT. Because of this, we say that JWT supports "Federation" - anyone can generate a token, and anyone can read and validate a token.

In summary, opaque tokens and JWT are just two different kinds of tokens. Both can be bearer tokens, both can be passed in the Authorization header. Apigee can generate and verify opaque tokens and can generate and verify JWT.

Now, What are the places you'd want to use opaque tokens versus JWT?

Use JWT when...

  • Federation is desired. For example, you want to use Azure AD as the token issuer, and then use Apigee Edge as the token validator. With JWT, an app can authenticate to Azure AD, receive a token, and then present that token to Apigee Edge to be verified. (Same works with Google Sign-In. Or Paypal. Or Salesforce.com. etc)
  • Asynchrony is required. For example, you want the client to send in a request, and then store that request somewhere, to be acted on by a separate system "later". That separate system will not have a synchronous connection to the client, and it may not have a direct connection to a central token dispensary. a JWT can be read by the asynchronous processing system to determine whether the work item can and should be fulfilled at that later time. This is, in a way, related to the Federation idea above. Be careful here, though: JWT expire. If the queue holding the work item does not get processed within the lifetime of the JWT, then the claims should no longer be trusted.

Use opaque tokens when...

  • There is no federation. The issuer of the token is the same party that validates the token. All API requests bearing the token will go through the token dispensary.
  • There is no need or desire to allow the holder of the token to examine the claims within the token.
  • When you wish to unilaterally allow token revocation. It is not possible to revoke JWT. They expire when they are marked to expire at creation time.

Things that DON'T recommend one versus the other:

  • The need for OAuth. You can use opaque tokens or JWT as OAuth bearer tokens.
  • custom claims. Both JWT and opaque OAuth tokens can carry custom claims about the subject.
  • security. Both are bearer tokens. Both need to be protected as secrets.
  • expiration. Both can be marked with an expiration. Both can be refreshed.
  • The authentication mechanism or experience. Both can present the same user experience.

Edit: And are there situations where you'd use a JWT for something OTHER than a traditional bearer token?

Sure! For example, RFC7523 explains how to implement something like a client_credentials grant (as described in OAuth v2.0 RFC6749), but rather than sending in a base64 encoded payload with id:secret, the client sends in a self-signed JWT. To make this happen the client needs to sign with HMAC 256, or the client needs to have a public/private keypair provisioned in place of the traditional "client secret". You can read more about RFC7523 in Apigee Edge, here.

And of course some systems ONLY use JWT for identity purposes. If you want to see a Google-provided JWT ID token, you can try this page which lets you inspect your own.

View solution in original post

5 REPLIES 5

Not applicable

JWT works best for use cases that need self authenticating tokens, where the token (that you get as a function of Authentication response) has lot more context about the user, session - including the signature. For example, if you have to go to an external server to authenticate each API request and that call can be expensive, JWT can get you a better performance. As an extension, if you become an IDP and you expect your partners (developers) to use you for Identity, they will have to call you for each API call- so a JWT can make their Apps perform better. The flip side to having self validating tokens is- they are valid till the pre-defined rules are valid- any invalidation of these tokens will not have immediate effect. As a side effect, you are forced to have lower expiry times to these tokens ( may not be ideal in some cases)

If you do not have such requirements, and its a simple API request/response pipeline (which seems to be the case, based on what you are describing) and with Apigee, since Access Tokens are validated off of Cassandra (meaning no additional latency) a simple OAuth Access Token makes more sense.

[Edit] As @Dino, @sarthak pointed out, you can use JWT in your OAuth flow itself. But my comment in more in-line with whether you want to have a simple access token validation or JWT validation as part of your auth flow.

The question is a common one, but it isn't quite sensible. JWT is a type of Token, and OAuth is a Framework that describes how to dispense tokens.

What do we mean by "framework"? Just the sequence of requests and responses, and the formats of those, that can and ought to be used to request tokens. OAuthv2 describes separate "flows" or grant types for different scenarios, and has different extensions (like PKCE) for extending the security of particular flows.

The result of a request-for-token via an OAuthV2 grant is... a token. That thing then is employed as a "bearer token" which means, any party that holds the token, can present it when making an api request-for-service (eg, "what's the balance on my stored value card?") . As a Bearer token, it works like cash money. If you're holding it, you can use it. (Though unlike cash money, a token is not use-it-and-lose it. Maybe a better analogy is an all-day ticket-to-ride on the public transit system, or an all-day ticket for Disneyworld.)

JWT is a particular type of token. Typically JWT are signed, and consist of three parts: the header, payload and signature, each base64-encoded and then concatenated. The result is a long string of base62 characters. JWT fill different roles; they can be "Identity tokens", which are tokens issued by an identity provider to a client application that provide information about an authenticated user (like name, email address, and other claims or attributes). JWT can also be used as "access tokens"; in this usage, the client application presents a JWT to a service as credentials with a service request. The service provider can evaluate whether to provide service based on the claims in the token. The distinction between ID token and access token is primarily one of intent, not of form. In some cases, a client may authenticate a user to an IdP, and receive an ID token in response. Then the client may send that same token as an access token to a service provider. Same token, different uses. JWT can absolutely be used as tokens within the OAuth framework, in other words, as an OAuth Bearer token. This is a very common practice. In light of that, "JWT vs OAuth" is a comparison of apples and apple carts.

People might think "OAuth token" always implies an opaque token - a random sequence of alphanumeric characters that contains no inherent meaning - that is granted by a OAuth token dispensary, that can then be validated only by that same OAuth dispensary system. But this is not the only kind of OAuth token. An opaque token is one kind of token; JWT can be used as a different kind of OAuth token. The OAuth specification does not require tokens to be opaque.

Today, the OAuthV2/GenerateAccessToken policy in Apigee generates opaque tokens. It returns a token consisting of a random sequence of alphanumeric characters (often 28 characters in length, though the size is tunable), and the holder has no idea what the token signifies. This is the meaning of "opaque". It's not that there is an obscure, hidden way to "decrypt" or unscramble the token and Apigee simply doesn't document it. It's that the token is really a random string. It's a pointer to some information describing who the token refers to, what the token should permit, when the token expires..., and that information is held in a secure store, inside the Apigee black box. Therefore, we call the token "opaque". To USE the token, the holder must present it back to the token dispensary, because the original dispensary is the only party that can relate the opaque string to the meaningful information associated to it. Bottom line: think of an opaque token as a pointer to information that is held only by the token dispensary.

JWT, in contrast, are not opaque. (Now I will confine this discussion to just signed JWT. There are also encrypted JWT, we won't talk about them here). The JWT is not a "pointer" or reference to information. It actually contains lots of specific information, that can be extracted and interpreted by any party that has the token. Because the JWT contains real information, a JWT can be large; 300 bytes, 500 bytes, or more, depending on the claims contained within it, and the algorithm used to sign it. When people say "JWT are self-validatable" what they mean is, any holder of the signed JWT can open it, validate it, and then make authorization decisions based on the claims presented in it. Validating the JWT means: verifying its structure, decoding the base64 encoding, verifying the key is correct, verifying the signature, verifying the validity times (eg, the token is not expired), then verifying the required claims are present in the token. It's not a simple thing, rather a multi-step process, but of course there are plenty of libraries in various programming languages that help with this, if you are writing your own code.

In Apigee, the VerifyJWT policy helps you verify a JWT from within an Apigee API proxy. The GenerateJWT policy allows you to generate a JWT from within a proxy.

Any actor with access to the appropriate keys can produce a signed JWT, and any holder or receiver with access to the required keys can verify a signed JWT. Because of this, we say that JWT supports "Federation" - anyone can generate a token, and anyone can read and validate a token.

In summary, opaque tokens and JWT are just two different kinds of tokens. Both can be bearer tokens, both can be passed in the Authorization header. Apigee can generate and verify opaque tokens and can generate and verify JWT.

Now, What are the places you'd want to use opaque tokens versus JWT?

Use JWT when...

  • Federation is desired. For example, you want to use Azure AD as the token issuer, and then use Apigee Edge as the token validator. With JWT, an app can authenticate to Azure AD, receive a token, and then present that token to Apigee Edge to be verified. (Same works with Google Sign-In. Or Paypal. Or Salesforce.com. etc)
  • Asynchrony is required. For example, you want the client to send in a request, and then store that request somewhere, to be acted on by a separate system "later". That separate system will not have a synchronous connection to the client, and it may not have a direct connection to a central token dispensary. a JWT can be read by the asynchronous processing system to determine whether the work item can and should be fulfilled at that later time. This is, in a way, related to the Federation idea above. Be careful here, though: JWT expire. If the queue holding the work item does not get processed within the lifetime of the JWT, then the claims should no longer be trusted.

Use opaque tokens when...

  • There is no federation. The issuer of the token is the same party that validates the token. All API requests bearing the token will go through the token dispensary.
  • There is no need or desire to allow the holder of the token to examine the claims within the token.
  • When you wish to unilaterally allow token revocation. It is not possible to revoke JWT. They expire when they are marked to expire at creation time.

Things that DON'T recommend one versus the other:

  • The need for OAuth. You can use opaque tokens or JWT as OAuth bearer tokens.
  • custom claims. Both JWT and opaque OAuth tokens can carry custom claims about the subject.
  • security. Both are bearer tokens. Both need to be protected as secrets.
  • expiration. Both can be marked with an expiration. Both can be refreshed.
  • The authentication mechanism or experience. Both can present the same user experience.

Edit: And are there situations where you'd use a JWT for something OTHER than a traditional bearer token?

Sure! For example, RFC7523 explains how to implement something like a client_credentials grant (as described in OAuth v2.0 RFC6749), but rather than sending in a base64 encoded payload with id:secret, the client sends in a self-signed JWT. To make this happen the client needs to sign with HMAC 256, or the client needs to have a public/private keypair provisioned in place of the traditional "client secret". You can read more about RFC7523 in Apigee Edge, here.

And of course some systems ONLY use JWT for identity purposes. If you want to see a Google-provided JWT ID token, you can try this page which lets you inspect your own.

Great Answer @Dino , +1

sarthak
Participant V

@Sunandita Dam JWT and OAuth are complete different things, not at all comparable. You can see an article which tries to clear up the exact same misconception: http://www.seedbox.com/en/blog/2015/06/05/oauth-2-vs-json-web-tokens-comment-securiser-un-api/

OAuth is a framework

JWT is a token format for carrying claims. As it's definition states:

"JSON Web Token (JWT) is a compact, URL-safe means of representing claims to be transferred between two parties." You can learn more about it here: https://tools.ietf.org/html/rfc7519. Another great place to start is here: https://jwt.io/introduction/

If you are familiar with SAML assertions then JWT is similar to that.

There is actually an OAuth flow with JWT, you can see the spec here: https://tools.ietf.org/html/rfc7523

You take OAuth framework then you add stuff to it to make other things happen. Once example is OpenID Connect. Which is built on top of OAuth 2 and also heavily uses JWT to define the final spec.

That article is completely wrong. OAuth 2 is a delegated authorisation. While JWT is the secure token that contains information. Per the RFC 7523 "JWT Bearer Token can be used to request an access token when a client wishes to utilize an existing trust relationship"