Kong: OpenID Connect

Created on 2 Sep 2015  Â·  39Comments  Â·  Source: Kong/kong

Most helpful comment

Having Kong act as an OIDC Relying Party seems like a good opportunity to better fit in the enteprise world where IDPs are usually already in place. We currently have a central OpenID Connect (KeyCloak) that powers the whole company. Central authentication is key for us and we don't want Kong GW to act as a duplicated provider. https://github.com/pingidentity/lua-resty-openidc seems like a good option and would respond to https://github.com/Mashape/kong/issues/1449. Should we maybe split the issue ?

All 39 comments

+1

this week at AWS re:invent we got tons of requests for this.

This seems to be related to #1014 and #1060, since OpenID Connect uses JWT heavily and it is a profile of OAuth2 (that is, it extends OAuth2 to bring identity and authentication capabilities to it). OpenID Connect is not related to the previous OpenID 2.0 protocol (they are two distinct families of protocols), which required an extension to interact with OAuth1.

@daviesf1 could you update the title of this issue to "OpenID Connect"?

@thefosk Is there any progress on this? I'm looking at implementing it myself since we need it now. If you haven't started working on it, have you put any thought into how signing with JWS will work in Lua?

I think the rest of the work will be fairly straight forward--just have to do it.

@ingshtrom I haven't had the chance to work on it, but if you want to give it a try I will review your PR.

O.o, the less work I have to do the better. I'll definitely take a look at that. Thanks.

+1

I have been looking into this quite some during the implementation of generic Authorization Servers for wicked.haufe.io (e.g. https://github.com/Haufe-Lexware/wicked.auth-passport or https://github.com/Haufe-Lexware/wicked.auth-saml), and the only thing which actually prevents me from implementing OpenID Connect on top of Kong's OAuth2 plugin is the following thing:

I cannot reliably implement the /userinfo end point.

It is supposed to work like this: When presenting a valid bearer token, then end point should return a standardized user profile (see http://openid.net/specs/openid-connect-core-1_0.html#StandardClaims and http://openid.net/specs/openid-connect-core-1_0.html#UserInfo); my Authorization Server would need to store a map Access Token --> UserInfo, and additionally would have to check whether the access token is still valid. What breaks me here would be any refreshing of tokens, which is done purely over Kong's /oauth2/token end point (I don't see that).

It would be incredibly awesome if I could associate a UserInfo object with the access token, which would be handled by Kong, and which also survives refresh_token requests. Kong would ideally also implement the /userinfo end point (e.g. as /oauth2/userinfo or similar). With such a functionality in place, I think implementing an OpenID Connect type Authorization Server would be really simple.

There would be two places where the UserInfo object would have to be passed into Kong, and those are either when creating the Authorization Code (for the Authorization Code Grant), or when creating the Access Token for the Implicit Grant.

This is still a first assessment from my side (and I will not continue down this path currently without additional functionality in Kong; it wouldn't make sense to build a separate data store for this), and I fear there will be other implications when implementing this into Kong (like: Scopes are mandatory for OpenID Connect, but they are "kind of" an additional layer on top of existing ones)... I am not a Lua god unfortunately, so I fear I would really struggle in tacking this into Kong, but I could give it a try.

Thoughts? What are your current plans on OpenID Connect?

I realized I also cannot completely implement the Autorization Code Flow, as the ID token needs to come from the token end point (with the access token). The only thing I could partially implement is the Implicit Flow, with the above restriction in the /userinfo end point.

The easiest way to get this kind of functionality into Kong would most probably be to actually extend the oauth2 plugin to include the OIDC extensions. It ought to be perfectly possible to keep the changes backwards compatible to the current oauth2 implementation.

I just had a look at the https://github.com/pingidentity/lua-resty-openidc library, and that's rather a library to implement an OpenID Connect "Relying Party", and not a an "OpenID Provider", which is what I tried to implement on top of oauth2. These are two quite distinct things -- both might make sense for Kong, even though I think enabling "OP" Authorization Server implementations would fit better into what's already there (which would mean extending the oauth2 plugin).

Having Kong act as an OIDC Relying Party seems like a good opportunity to better fit in the enteprise world where IDPs are usually already in place. We currently have a central OpenID Connect (KeyCloak) that powers the whole company. Central authentication is key for us and we don't want Kong GW to act as a duplicated provider. https://github.com/pingidentity/lua-resty-openidc seems like a good option and would respond to https://github.com/Mashape/kong/issues/1449. Should we maybe split the issue ?

@hutchic your link seem to be private.

Sorry @bg-o mistake on our end as we are experimenting with Trello.

Are we going to support the OIDC "Replying Party" in the plugin? Or is it just good enough to use lua-resty-openidc?

I am asking, as I am trying to auth against Keycloak from Kong.

@meggarr, I am right now implementing the libs that we would like to have for this. And I'm focusing mostly on RP side of the OpenID Connect right now. It would be valuable to us if you could describe your use case and what part of it you would like the Kong handle. This is high priority for us as well.

@bungle, I am trying to use an existing Keycloak server to authN against username/password - direct access grant. So I hope Kong can have a plugin to authN against Keyclock.

If it is possible, I want to authZ the API resource as well. Not figure that out in Keycloak yet. On the other hand, if Kong's plugin can recognize the role/group in Keycloak, it would be much better.

Based on that Kong already support OAuth2 provider via provider, it wouldn't be surprised to see OIDC provider plugin. :)

We've written a plug-in for Kong acting as OIDC RP, based on lua-resty-openidc. We're still doing some testing and found issues in lua-resty-session, but expect a PR soon.

@tookko good to hear. Have you reported the issues on lua-resty-session as I am an author of that.

Sorry actually turns out the issue we had was with lua-resty-jwt instead of lua-resty-session. In any case it's reported and already closed.

@tookko Any news about the OIDC RP Kong plugin? We are also trying to integrate Kong with keycloak.

We have it already working and in use against Keycloak. Still writing some more tests before we make the PR.

Sorry for being pushy... but can you give some estimate on when that will happen?
We're on a short schedule, and need to decide to wait for the plugin or roll our own solution.

@abustya just being curious here, what are you looking for the OpenID Connect (RP) plugin in Kong to do (e.g. your use case)?

@bungle can't answer for @abustya, but I would be happy if it allowed me to use Keycloak as the source of truth for client+user identity and for authorization in line with the OpenIDConnect specification.

I believe this would translate to:

  1. Understanding JWT bearer tokens in the Authorization header
  2. Only allowing requests through that are valid JWT
  3. Map the client_id in the JWT to a kong consumer
  4. Correctly set the WWW-Authenticate response header when Authentication fails
  5. Allow me to specify scopes/claims that must be present for in order to access each API (bonus points as that gives me role based authorization)

I can already do a lot of this with the JWT plugin, but I'm interested in seeing what extras are provided by @tooko's work

@bungle I'm looking for a plugin that can make back channel token requests...

As I understand (I'm quite new to OIDC), if I use the Kong JWT plugin, the client first needs to get the Id Token+OAuth Access token. This means that my client, and not (only?) my backend service must be registereg into keycloak, access tokens will leave the server side, and my client needs to know about some OIDC logic.

I've looked at the lua-resty-openidc code, and as I understood, it can handle all of this: it can work with a client and backend, that have no knowledge about OIDC, because it contains all the logic for when to redirect where, when to logout etc.

So I basically want to use lua-resty-openidc in Kong - its "OpenID Connect user authentication" feature to be precise.

@abustya,

So it looks like you are looking to use authentication based on authorization code flow, and want something like this:

  1. Kong to provide an endpoint for which your client sends a request to initiate authrorization code flow
  2. Kong authorization endpoint will generate an url where the client is redirected with Location header. To make things a bit more secure, Kong would setup state and nonce parameters as well. But that will also mean that now Kong needs to setup a session for the client (so that it can check the parameters when Client returns from the OpenID Connect provider). With web browsers you usually send a cookie to client (that's what lua-resty-session could do, and that is the reason lua-resty-openidc depends on it on this authorization code flow). Cookie can be self-contained or it can only store an identifier (the actual data is stored on a server then). The mentioned session library supports both with different backends.
  3. User authenticates and authorizes the client and he is returned back to a redirect_uri that in this case should be Kong's endpoint (because only Kong knows about the response parameters). When user is redirected back the client should also send back this session identifier, a cookie in this example.
  4. Kong will validate the return parameters (like state)
  5. Assuming everything is fine, Kong will make request to token endpoint to retrieve say access_token and id_token. And it will validate the response (e.g. JWS signatures (possibly JWE stuff as well), the nonce parameter, validate the opaque access token (at_hash on id token), or JWT access token (say JWS validation, plus claims validation).
  6. Kong will store (cache) these tokens so that they can be later retrieved from some store (it could store them to session state or separately).
  7. Kong could use id token claims to make mappings to a Kong consumer (so that rate limiting etc. could be applied by consumer).
  8. Kong could handle refreshing the access token as needed (using the refresh_token it may have got from token endpoint (see 5.).

Now everything is setup. Then user just needs to send requests with session cookie to APIs (actually to Kong) and the Kong will check that user has a valid session. Kong can append a bearer token (access token) to a request for the API to use and possibly remove session cookie from upstream request (as it has no meaning there). It could also add id token to request or some claims from it. Signing out is basically just destroying the session (expiring, deleting etc.), although Kong could call OpenID Connect's end_session endpoint as well.

I do see value in this (the client in this case would be most probably be a web browser). Some users may want to do this so called Dance (auth/authz flows) outside Kong, and as a result they do have access_token and possibly id_token that they could send to a service (API) through Kong (access token in Authorization header and id_token in some payload (header, query string, application/x-www-form-urlencoded, multipart/form-data, application/json). Kong could then validate these (it cannot validate the nonce, but it can validate JWS signatures, and the at_hash etc.), make possible mappings (consumer), retrieve other info, etc.

@bungle
Thanks for breaking it down! Yes this is what I want to do - I want to use the authrorization code flow, and I want to do the "Dance" inside Kong.

As I've seen most of this is already implemented in lua-resty-session (except for token refresh maybe?).
So what has to be done is wrapping lua-resty-session in a Kong plugin. Which is what @tookko is working on. Or am I missing something?

Great! Good to hear these different use cases, and it totally makes sense to provide both. I think that I should make PostgreSQL and Cassandra storage adapters to lua-resty-session so that we do not require other server dependencies (Kong works with the either, but lua-resty-session currently only supports cookie (client side encrypted and signed — no extra dependencies), shm (shared memory, no extra dependencies, but doesn't work on cluster without a sticky load balancer), memcached (needs memcached server as well), and redis (needs Redis server as well).

I do not know any further details on @tookko's work, so I cannot comment on that. But I also do look forward to it! There are multiple different usage scenarios, so I rather see multiple plugins than the one big monolith that tries to support them all.

Hi everyone. It is nice to see such a contribution as https://github.com/nokia/kong-oidc that seems to wrap lua-resty-openidc in a nice and neat Kong plugin.

TLDR, I will close this issue as there are currently solutions to support OpenID Connect (both Open Source and Supported Enterprise Plugins) , and we do not plan to include any of those in Kong repository. At this point we generally prefer having plugins outside of the core Kong repository (and we look forward implementing infrastructure for a better plugins ecosystem in a future).

I have been personally busy with implementing OpenID Connect plugins for Kong Enterprise. A short introduction of the plugins can be found from here (the plugins are available to all Kong Enterprise customers): https://getkong.org/plugins/openid-connect-rp/

It is a suite of OpenID Connect related plugins. Here is a bit longer description of the plugins.

OpenID Connect Verification Plugin

This is a stateless plugin that can be used to verify signed JWT tokens (or JWS tokens) (support for JWE will be added in a future). It supports signature validation and claims validation for ID Tokens and Access Tokens (and even arbitrary tokens). It also supports Kong consumer mapping based on a claim in a JWT token. You can also in addition to specify arbitrary session cookie that is matched to a JWT claim if you want to allow only tokens with a matching session cookie to pass. It also supports dynamic rate limiting based on a claim. It also enables passing the JWKS used in validation to upstream. I have tried to have much of this configurable so that you can only enable things that you need. The plugin supports OpenID Connect related automation such as automatic discovery and key rotation.

OpenID Connect Authentication Plugin

This plugin reminds a bit of the https://github.com/nokia/kong-oidc plugin mentioned above. This plugin implements the Authorization Code Flow (and soon the other flows as well) inside the Kong. Making Kong as a Relying Party for a 3rd Party OpenID Connect Provider. Early talks about this was discussed in this comment: https://github.com/Mashape/kong/issues/522#issuecomment-301011132. The plugin setups a session with the client and Kong using a session cookie. This plugin is designed to be applied in a specific (global) endpoint, and it is not designed to protect the APIs. For API protection we have developed OpenID Connect Protection Plugin (discussed below). This plugin does the authentication of the client and either returns ID Token to the client or redirects the client to a specified URL on successful authentication with ID Token applied in URL fragment.

OpenID Connect Protection Plugin

This is a sibling plugin to the OpenID Connect Authentication Plugin but this time you can place this in front of an upstream API to protect the access only to the authenticated clients (those that have authenticated with OpenID Connect Authentication Plugin endpoint). This plugin also enables automatic refreshing of Access Token using the Refresh Token. It also exchanges the session cookie with the Access Token automatically (removing the session cookie and adding the access token as a bearer token to the request before proxying to the API). As with verification plugin, we also support verifying the claims and scopes, and provide automated consumer mapping based on a arbitrary claim. Dynamic rate-limiting based an arbitrary claim is also supported with this plugin.

OpenID Connect Logout and Revocation Plugin

The OpenID Connect Logout plugin implements the OpenID Connect Back-Channel Logout as specified here:
http://openid.net/specs/openid-connect-backchannel-1_0.html

The above mentioned Protection and Verification plugins may be configured to check if the supplied tokens should be revoked the access based on back-channel logouts. At this point only a few providers support back-channel logout. For this reason and for added flexibility and protection we also provide a way to revoke arbitrary tokens using OpenID Connect Revocation Plugin. The Protection and Verification plugins do check for revoked tokens and deny the access if the token is revoked.

OpenID Connect Dereferencing Plugin

This plugin allows the request to be modified to include additional information (or claims) based on standard OpenID Connect endpoints such as User Info endpoint, and Client Info endpoint. This allows you also to exchange an opaque access token to a value (or JWT) token using introspection. The plugin will cache the results on a first use for a configurable amount of time.

OpenID Connect Microservice Plugin

This is similar to the OpenID Connect Dereferencing Plugin but allows you to specify your own microservice that can be used to exchange access token to a more full featured token for APIs to consume. Kong caches the results for configurable amount of time.

In total we have currently seven (7) plugins for many different usage scenarios for Kong Enterprise customers, and we are happy to give hands-on guidance on those. All these plugins are build on top of our OpenID Connect Library that we developed together with these plugins. The plugins have been tested with several OpenID Connect Providers (both local and cloud providers):

If your favourite provider was not listed, please let us know and we will happily test against new providers as well (provided that we have some sandbox to test them).

Now that I have described a several solutions and others have linked to other solutions, I think this can be closed. Please contact to the authors of the plugins through the channels, respectively.

@bungle Just one more short question, but maybe it's just me being thick: This is all for Kong acting as an OIDC Relying Party (to Authenticate/Authorize against e.g. KeyCloak), right? There is not yet support for Kong implementing an OIDC Provider (as that would mean extending the OAuth2 plugin, in my eyes)?

Will such a functionality (OIDC Provider) also be exclusively for the Enterprise edition, or would a PR for extending the OAuth2 plugin possibly be considered for merging?

@DonMartin76, you got it right. At this point we are not planning to implement OpenID Connect Provider functionality in a new plugin or in OAuth2 plugin. If we decide to implement the separate provider plugins, they will be a part of the enterprise offering. What we are looking for, are the use cases for reverse proxy / API gateway like Kong acting in middle of a API client and 3rd party identity platform talking OpenID Connect and the API service. So far we have identified a few (as mentioned above) use cases (and implemented those ideas as a enterprise plugins), but we are always looking for feedback. In fact we want to develop these in close cooperation with our customers and the open source community.

There are a lot of good providers for identity management (and it is already a pretty well established market with a lot of options). Both on-premises and cloud services. Both open and closed source products and services with different kind of contracts and support deals. A few of them are mentioned in a post above. While OpenID is a standard or tries to standardize things, it looks like the providers are reading the standard in different ways (or implementing just some of that). They seemingly do like to follow 99% similarly, but there are a lot of details that need to be considered. Of course a lot of OpenID Connect (and OAuth2) related specifications are still changing and new specifications (or new versions of them) come out monthly. E.g. this just got standardized this month: https://tools.ietf.org/html/rfc8176.

That said, you and the community is more than welcomed to ship a PR for OAuth2 plugin to implement OpenID Connect related features OR fork the OAuth2 plugin to OpenID Connect Provider Plugin (which ever does seem the right way to do). I guess that would mean a login and consent page and a support for returning ID Tokens, implementing User Info endpoint and possibly also Dynamic Client Registration and Client Info endpoints, among the other details forgotten to mention here (and there are a lot more in development in OpenID Connect community).

I'm not sure (personally), if provider features should even be part of Kong. Maybe something lightweight, simple, and not full featured provider functionality could be provided as a Kong plugin. But soon the project would grow (as more requests would come in; there is almost 100 issues for OAuth2 plugin alone) that it would warrant a new product (with a GUI?). And that could then be added to the list of providers (see the above post). Of course that would be a neat thing to have, e.g. easier to start developing microservices as you could basically just put Kong in front, that provides you an API Gateway and Identity Platform in an integrated package. But then again, a lot of our customers and open source users do already have a separate identity solution in place, and they are looking for a better way to integrate with it. And this is what we have been focusing with our Kong Enterprise OpenID Connect Plugins.

@bungle Thank you very much for your thorough answer.

A lightweight enablement of Kong to make it act as an OIDC provider would be fairly straightforward, if you can extend the OAuth2 plugin just a wee little bit, as I described in https://github.com/Mashape/kong/issues/522#issuecomment-261721732. This would very much help me with some of my use cases (where we act as API providers with a strong need to incorporate arbitrary partner IdPs, some not even using standard authentication mechanisms). I currently get around with other custom extensions, getting the userinfo from the Authorization Server instead, but OIDC has a standard for just this which I cannot implement on top of Kong right now, because of the given reasons.

Forking the OAuth2 plugin might be a solution, but the OIDC Provider additions should be feasible totally without breaking or altering existing functionality.

Perhaps we can talk sometime.

@DonMartin76, I checked your comment, and I do think your idea is a good one, but I fail to see why associating User Info with Access Token is problematic? Could you just cache this on a first use with a TTL of the access token? And I do think you may need to add additional admin api endpoints to store the User Info claims, something like /consumers/:username_or_id/claims/ (otherwise you may need to extend a core thing such as consumerto include more fields, and that might not be something we are willing to accept as is (btw. we are looking to implement a new model for Kong, and I will bring this to discussion).

I'm happy to discuss more with you.

@bungle I could indeed cache that inside the Authorization Server, but I wouldn't be able to detect when an access token is replaced by using a refresh token (for the flows where this applies); inside Kong's model it would fit a lot better, as you could do real housekeeping for that. And yes, storing the userinfo is indeed something which I think could/should/would suit best to store inside Kong's database as well, much like instead of just storing Authenticated-UserId and -Scope also an OIDC shaped userinfo object attached to that exact credential.

By doing it that way, the OIDC Provider implementation is up to the person implementing the Authorization Server, but Kong could correctly serve the /userinfo endpoint and track the token to userinfo mapping automatically. Right now, I just can't (in a nice and decoupled way) implement the OIDC Provider additions on top of OAuth2 because of these minor problems.

Implementing it in Kong should be very straightforward.

Associating the userinfo with consumers is not the way to go, in my opinion. In those cases where you would want to implement the OIDC Provider within Kong, the consumer is rather an application than an end user (just like you handle the OAuth2 stuff today, or how you recommend it in the example code), and thus should be treated similarly as the Authenticated-UserIdI mentioned above.

Very happy to continue discussing, and I would also be happy to contribute this extension, once I get my development environment for Kong up and running again... I do have another PR pending I need to bring up to 0.10.x shape, where I haven't had the time just yet...

Ok, so as @bad79s already spotted, we pushed the RP plugin here: https://github.com/nokia/kong-oidc

We're using it against Keycloak and works fine, there's still an issue that it has hardcoded filters for a few API endpoints. This will need to be generalized when someone has time to do it, of course contributions are welcome too :)

@tookko can you clarify what you mean about the hardcoded filters above?

Was this page helpful?
0 / 5 - 0 ratings