Kong / kong

🦍 The Cloud-Native API Gateway and AI Gateway.
https://konghq.com/install/#kong-community
Apache License 2.0
39.06k stars 4.79k forks source link

Adding OAuth2 to multiple APIs #1488

Closed vitorsdcs closed 6 years ago

vitorsdcs commented 8 years ago

Hi,

I have multiple microservices behind Kong and I'd like to protect them all with OAuth2, using the Resource Owner Password Credentials flow. I also would like to let users access all of them once they have an access token.

However, when my web app authenticates a user, it has to make a POST call to a single API behind Kong in order to generate the token. Which doesn't make much sense, since the user will be getting a token to access multiple APIs.

I think it would be nice if I had an option to add the OAuth2 plugin to a group of APIs and then call http://kong/oauth2/token instead of http://myapi/oauth2/token.

Or is there a better approach?

Tieske commented 8 years ago

just a quick thought; can't you create one by redirecting through kong itself? (untested!)

vitorsdcs commented 8 years ago

You mean calling http://kong/oauth2/token? I've tried it already but it doesn't work.

markyjones commented 8 years ago

We ended up creating a host name routed login api with a dummy upstream (coded to give back a 404) and the oauth plugin for issuing oauth bearer tokens e.g. login.domain.com

All our actual backends are then path based routed behind api.domain.com/X, api.domain.com/Y, api.domain.com/Z

It is a bit of a workaround but it seems many API clients are tolerant (i.e. configurable) of the bearer token issuing and the actually api's being on different subdomains.

I would most certainly +1 the idea of having an ability to have the OAuth token and authorization endpoints become independent of the API definition.

michallis commented 8 years ago

+1

michallis commented 8 years ago

At the moment we have a workaround, we defined a api.domain.com/oauth2 and use this endpoint as a dummy api to work with oauth consents. All oauth2 enabled apis are published AFTER this endpoint, for example: api.domain.com/oauth2/someapi, and that works. We use ACLs to protect different apis as well.

mdan1eli commented 8 years ago

I am also using a similar workaround. It would be good also to be possible to specify a realm to which the token is issue and be able to check the realm match in the plug-in. That makes sense in a shared environment

sisp commented 7 years ago

+1 for being able to add a single OAuth2 plugin to multiple APIs so that a logged in user has access to all protected APIs with the same token.

allenlkq commented 7 years ago

+1 for this feature

powerLambda commented 7 years ago

+1

awfm9 commented 7 years ago

Any comment from the team on this? It seems like a pretty obvious one to me. I assumed POSTing the plugin to /apis/ would do this and was surprised to find out that I had to do it API by API.

Having to create an application for each consumer doesn't really make too much sense, either, in a resource owner based authentication scheme. It would make a lot more sense to have tokens as well as applications on the top level, just like consumers.

ghost commented 7 years ago

+1

ghost commented 7 years ago

+1

gitomato commented 7 years ago

Actually this is possible if you want to do it for all APIs without exception. It is written in the documentation: https://getkong.org/plugins/oauth2-authentication/#configuration

You can also apply it for every API using the http://kong:8001/plugins/ endpoint. Read the Plugin Reference for more information.

The plugin reference is not clear on this point but you can call POST /plugins. I managed to have two microservices sharing the same token.

Tell us if this works for you!

Mattzr commented 7 years ago

+1

@gitomato - installing oauth2 plugin globally doesn't make a difference since the access token can be generated only for a single api (but applied to all apis when installed globally).

I am currently experiencing the same problem. Can someone clarify the workaround @michallis / @markyjones suggested above with an example ?

I don't see how to "publish the oauth2 enabled API after that dummy api" with /oauth2/my_api using access token generated from the dummy api.

Thanks !

rusith commented 7 years ago

+1 Need this badly

nbroers commented 7 years ago

+1

The solution proposed by gitomato is not sufficient - when retrieving the tokens from Kong via your API URL (https://getkong.org/plugins/oauth2-authentication/#resource-owner-password-credentials), this part is still API specific. The token granted is not valid when used to access other API's.

In addition, I do not see how any of the workarounds posted here could work.

Even when adding API's as accessed by path, they are still separate API's. The tokens granted are still API specific.

What is the use of having an OAuth plugin if it is only able to serve on API?

troyanov commented 7 years ago

@Mattzr @rusith @nbroers

guys,

i was reading kong's oauth plugin source code and noticed this line:

global_credentials = {type = "boolean", default = false}

you can find it here, and dig further about how this property is used in the logic: https://github.com/Mashape/kong/blob/3c44c1c410333429ff8be3038c6bb618bfc71988/kong/plugins/oauth2/schema.lua#L33

you can configure it like so:

http POST localhost:8001/plugins \
          name=oauth2 \
          config.enable_password_grant=true \
          config.scopes=profile \
          config.global_credentials=true

with this config option, access_token obtained from /api1 is working for /api2 (also oauth2 plugin must be configured globally for all APIs)

tallsam commented 7 years ago

This (global credentials) really should be added to the OAuth documentation

devenfan commented 7 years ago

thanks to @troyanov , we have successfully used the same access_token between /api1 and /api2. Those apis that have "global_credentials=true" will share the same access_token.

BTW, can we have a "group" property for this plugin in the future? In this way, those apis that in the same "group" with "global_credentials=true"(or maybe "group_credentials") will share the the same token.

amifeanyi commented 6 years ago

About to try @troyanov :+1: solution right now, wish me luck. :pray: I will report my success story. :relieved:

amifeanyi commented 6 years ago

Nice one @troyanov. Working perfectly for me. :+1:

kikito commented 6 years ago

I think @vitorsdcs 's original request is covered with config.global_credentials (which is documented now so I am going to close this issue down.

Everybody else, if you want to continue this conversation about extending the oauth2 plugin (i.e. with "groups") please use the Kong Nation forum. Thanks!

gerson-evocorp commented 5 years ago

Here is what I do for my gateway and consider it a good practice (Not sure if it's a good approach).

Step 1. Create a service pointing to a dummy backend. Enable the Oauth2 plugin on this service with global_credentials set to true. You now have a single oauth endpoint to grant access token:

Step 2. Create the other services and enable the oauth2 plugin on them, set global_credentials to true here as well.

What we have now is a standardized central endpoint that will handle all token generations for you. I hope this will help!

frihed commented 4 years ago

Nice one @gerson-evocorp

Step 3 (optional). Restrict access to a service by whitelisting or blacklisting consumers using ACL group names. Thus same group will share the the same token.