JWT vs Oauth2 Open Discussion


#1

What pattern do you secure your APIs with and why?

I see JWT and Oauth2 being similar in nature, you have a few secret elements that produce hash and protection via some sort of token expiry.

Strengths of JWT:

  1. Simple logic client side, use the Auth0 libraries and even if they implement poorly and don’t cache its no skin off the gateways back :slight_smile: .

Weakness:

  1. Client gets to prep their own exp timeout in the signed JWT, I dislike this because a dumb client could start passing tokens valid for say a year or ten years. I suppose you could add extra logic kong side to make sure jwt’s are not set to expire that far out and reject them but that just seems non-elegant.

Strengths of OAuth2:

  1. Timeout is set in the gateway config logic for tokens being issued.

Weaknesses of OAuth2:

  1. Added network time calling an endpoint to generate the token.
  2. Clients that implement Oauth2 poorly will decide to generate a token every request, this will rek Kong because Kong then stores every token in the db and then Kong’s cache has to cache all these stupid tokens.

I thought of one idea where I actually create jwt auth ontop of our “global” oauth2 token endpoint our gateways have to implement rate limiting, but that also feels a bit excessive to force clients to do that to use oauth2 at that point haha.

In my mind JWT wins out due to its simplicity and I feel like on the Kong side it simply is cleaner because Kong is not storing each of those jwt tokens, it simply validates the JWT’s recieved based on the stored secrets.

Kong dev’s thoughts? Community thoughts? I am just curious others rational when thinking about the two methods.

Thanks,
-Jeremy


#2

Oh wow, sorry, this was a while ago.

But I’d like to give it a shot anyway: To me, it is not JWT or OAuth2, but rather whether you use JWT or opaque tokens with OAuth2. OAuth2 should always be your go-to.

The big advantage of JWT is that the tokens which the Authorization Server issues do not need to be looked up i some kind of database, but can be validated independent of the Authorization Server, e.g. using an API Gateway such as Kong.

The way Kong handles OAuth2 is just an implementation detail of the OAuth2 spec; Kong uses opaque tokens (random strings, give or take) to look up X-Authenticated-UserId and X-Authenticated-Scope, whilst you would bake in that into your JWT token as claims.

Another implementation detail of OAuth2 would then be how you validate your tokens - either using the Kong OAuth2 plugin (opaque tokens which it also issues itself, Kong (partially) acting as the Authorization Server), or using JWT tokens which need to be issued by a custom Authorization Server, such as one provided by Auth0.

HTH,
Martin


#3

Happy to see yah here @DonMartin76, been awhile since we last chatted but I am sure you have been busy on your end with Kong :slight_smile: . I am confused when you specify “JWT is that the tokens which the Authorization Server issues”, the Authorization server(In my case would just be Kong) houses the public key generally in JWT(Kong in this case stores both public and private key, and for good measure anyways) and then the client proxy consuming application generates and signs their JWT tokens interally using their private key for the Authorization Server(In my case Kong) to validate.

JWT direct with Kong
Kong -> Consumer -> Generate HS256 Pub/Priv Key
Consumer App (Generate JWT signed using priv key) -> Kong (Validate JWT with Pub key) -> Backend API

VS OAuth2 direct with Kong
Kong -> Consumer -> OAuth2.0 Client Credentials client_id/secret
Consumer app -> Call token endpoint get a temp token (requires extra db storage and records)
Consumer app -> Pass token in Auth Bearer header to Kong proxy(Validate bearer token) -> Backend API


#4

I think the possible misunderstanding is this:

the client proxy consuming application generates and signs their JWT tokens

This is not what you usually (should) do. You should have one authority (an authorization server) which issues JWTs; each client should not be able to do that. You want to be able to cut off compromised clients without having to invalidate all other clients, and thus you would never give out the secret (private key) to clients, but have that secretly stored in the authorization server. In the end, you should still end up with one of the OAuth2 flows, with the only difference that less of the bits is implemented inside Kong, but on the other hand you have a more decoupled architecture. The Authorization Server should authorize use of the API, and the means of transporting this authorization can be a JWT (which is validated in Kong), or it can be an opaque token (which is created and validated in Kong).

Kong is only half an Authorization Server, and only for the Client Credentials case. If you need more, you will have to roll some custom code to implement the other flows.

I feel this just makes it more confusing, amiright?


#5

Hmm I still don’t see how one client having their private key somehow compromised would jeopardize all other Kong consumers with their own individual jwt public and private keys(held within their own individual apps referenced in secure manners).

What I do is this. I give individual consumers the option of OAuth2.0 Client credential grant or JWT Auth with HS256. Each proxy consumer is their own Kong “consumer” resource with their own JWT key and secret OR client_id/secret (if OAuth). If a client were detected to be compromised I would delete their corresponding JWT key+secret and issue them a fresh one(we may implement mandatory credential rotation in the future as well). I suppose I am not seeing much of the hazard. I have not researched setting up a 3rd party authorization server for managing the jwt/oauth2 tokens, because I generally lean towards less dependencies and run as slim as possible unless I see major hazards. But to each their own :slight_smile: .

And no I am not confused, I see where you are coming from and enjoy the discussion, tis refreshing!


#6

Okay, now I get how you are doing it. You are offloading the part of the Authorization Server to the client by handing them the secret and letting them craft their own tokens. This is perhaps a little dangerous depending on the nature of your clients; if you are dealing with well-known clients, it is possibly fine. If you are dealing with clients which are able to self-register (and this is where I am coming from), this can be highly dangerous, as you are actually letting the clients (as themselves) decide on the scope/claims in their JWT.

I still think this should be the domain of an Authorization Server. As it is here, your backend must take care that your tokens do not contain anything you don’t expect, as they are crafted by the clients, as opposed to crafted in only a single place (in the Authorization Server).

In effect, this means you are 110% trusting your clients to behave, and as I see it you do not actually gain much, security-wise, over just using an API Key. It might just be more complicated for the client.

But, as you have noticed, you need additional components/custom code to pull it off; Kong CE alone will not cut it.

And yes, I also enjoy these discussions :wink:


#7

as they are crafted by the clients, as opposed to crafted in only a single place (in the Authorization Server).

One more small clarification on this thing: Using the approach of having an Authorization Server would actually mean that you are not using the concept of clients in Kong to model the actual clients. This would just be a claim inside the JWT, and you would just have one single client to which you would attach the JWT certificate which would validate access/check that the signature of the JWT is correct.

The downside of this is that you would need to roll your own client management, and/or use the consumer API of Kong, but just as a data store and let the Authorization Server look up client id and secret via calls to the Admin port 8001.