RFC7523 in Apigee Edge - Exchanging JWT for Opaque OAuth tokens

Many of you are interested in OAuth, and JWT, and you may be aware of RFC7523, which describes how to exchange a JWT for an opaque OAuth token.

For those that are NOT aware, here is a little more detail. A JWT is just a signed JSON payload. Actually the JWT standard says it is possible to *Encrypt* the payload as well, but most cases I have seen just use signed payloads. Put a bunch of stuff into a JSON hash, and sign it. JWT describes a standard way to express things in the payload, like:

  • issued-at time
  • issuer
  • subject
  • expiry time
  • and more

The resulting signed thing can be used as an assertion. The signature, if produced with a private key, will assure any receiver of the JWT that the signer vouches for the payload. For example if Google Identity Service signs a JSON payload, and mushes the payload and the signature together into the JWT format, any holder of the resulting JWT can verify the signature using Google's public key. And if the sig is verified, the holder can be assured that the claims inside the JSON payload are valid and true, according to Google.

OK, so JWT is a standard way to sign a JSON payload.

RFC 7523 describes how a client (and remember, client = app) can use a JWT to assert its own identity. In this case the client self-signs a payload using its own private key. Then transmits the JWT to a server. The server can then verify the JWT with the client's public key. And then the server can be assured that the JWT is valid, and the client is who it claims to be. (or at least it holds the private key of who it claims to be) .

Because signed JWT are (relatively speaking) computationally expensive to verify, designers of systems want to find ways to amortize the cost of verifying the signature. RFC7523 describes how to exchange one of those client-signed JWT for an opaque OAuth token, which is computationally cheap to verify. The exchange of JWT-for-opaque-token uses a grant_type that is similar in effect to client_credentials, but different in execution. The name of that grant_type: urn:ietf:params:oauth:grant-type:jwt-bearer . The client can then use the generated opaque token for all subsequent API requests, and on the server side it's light and easy to verify that opaque token.

I've just put together an example that shows how you can embed that kind of token-exchange capability into any Apigee Edge API Proxy. In this example, the client generating the self-signed JWT is a Java application, but in YOUR application, it will be the dedicated client running on a mobile device, or on a server, etc.

The code is all available on github here. I've just updated this example (15 March 2018) to use the built-in JWT policies in Apigee Edge.

And I've put together a 9-minute screencast showing how it works, too. Check it out. (The screencast may mention the Java callout for handling JWT - ignore that part. The current code is using the builtin JWT policies. Everything else I say in the screencast still applies.)

6582-screenshot-20180314-134646.png

If you have any questions or feedback, on this, let me know! I'd love to hear it.

One suggestion was to include some proof-of-work requirement on the client. For example, require the client to produce a HashCash. Adding that would be no problem. The client would need to compute the HashCash and include the proof string into the JWT claims. On the server side, after the Apigee Edge proxy verifies the public-key signature on the JWT, it can verify the HashCash before declaring the JWT to be valid and acceptable.

@Srinandan Sridhar - FYI

Comments
akoo
New Member

Awesome demo, @Dino. I can think of a few other reason to use this aside from the computational expense of validating the signature on a JWT for every call:

  1. This solution allows for resource endpoints to now solely verify opaque tokens for all calls. This simplifies proxies for the resource endpoints so that the proxy developer does not need to consider a path for JWT and a path for opaque tokens in each proxy. This is a big deal IMO.
  2. Related to #1, this makes the solution architecture simpler for the smaller price of complexity to handle the JWT-for-opaque token exchange.
  3. The opaque token may be easier to work with for security reasons (e.g., PII in claims, revocability) than a corresponding JWT. It would take some steps to make sure the JWT used to make the opaque token doesn't have issues, but at least you've shown the foundation.

Thanks for highlighting the RFC 7523 in a way that's easy to see and try out for ourselves.

DChiesa
Staff

Yes, very good points, Alex! The complexity of handling the JWT is all contained within the token issuance flow. The rest of the API Proxies are very simple.

@Dino - the link to the screencast is missing

DChiesa
Staff

Thanks, Sai. I just added it in, again.

babuk0930
New Member

@Dino, @Sai Saran Vaidyanathan @Srinandan Sridhar

Let's say if we exchange jwt for opaque,

does even microgateway can verify the opaque token as well?

As currently we are having two different tokens

1. All edge proxies are thru opaque tokens

2. All microgateway services are thru JWT's

So can we make microgateway to accept opaque Tokens or viceversa (edge proxies to accept JWTs)

dchiesa1
Staff

No, microgateway cannot accept opaque tokens.

The Apigee gateway can accept JWT, if you like.

babuk0930
New Member

Is there any sample configuration that we can make edge proxies to generate JWT as well.

dchiesa1
Staff

Yes. The GenerateJWT policy allows a proxy to generate a JWT. If your question is more in depth, please ask a new question.

Version history
Last update:
‎12-14-2016 10:06 PM
Updated by: