wso2 / product-apim

Welcome to the WSO2 API Manager source code! For info on working with the WSO2 API Manager repository and contributing code, click the link below.
http://wso2.github.io/
Apache License 2.0
845 stars 785 forks source link

Support Basic Authentication for Subscribers #6804

Closed markokocic closed 6 days ago

markokocic commented 4 years ago

Right now the consumers that support only basic authentication are not able to use APIs exposed by Api Manager.

Many consumers are not customizable enough to go through the whole OAuth2 dance, but wast majority of even legacy systems support have ability to add consume services secured using basic authentication, and it's mostly the only authentication schema they support.

This includes various SAP products (S4, ERP, Customer Cloud, Marketing Cloud, ...), as well as many other ERP, CRM and other enterprise systems. Without Basic Authentication support in Api Manager, the only alternatives are:

TomasTokaMrazek commented 4 years ago

Newly released APIM 3.0.0 does support Basic Auth. We currently use it in our environment.

markokocic commented 4 years ago

Yes for backend endpoints. For Api I couldn’t find the option.

TomasTokaMrazek commented 4 years ago

API Publisher -> Runtime Configurations -> Application Level Security image

tmkasun commented 4 years ago

@Tomas-Mrazek correct, Now we support Basic Authentication for API clients as well. You can enable the Basic option under the application-level security as shown above. This will allow API consumers to invoke this API using their username password combination.

markokocic commented 4 years ago

Ok, looks like I was looking on the same place. Just tested it and it works.

This brings more questions.

How do subscriptions work with basic auth? Seems like any user can invoke any Api, independent of subscriptions? Is there a way to "assign" users to specific applications so that they can invoke only API to which application is subscribed?

If both Prod and Sandbox share the same Gateway, how is determined which one is invoked when doing basic auth?

These two questions wouldn't need an answer if we were to use application key and application secret instead of username and password in basic auth.

Maybe I am missing something, so it would be good if you could point me to the documentation.

TomasTokaMrazek commented 4 years ago

How do subscriptions work with basic auth? Seems like any user can invoke any Api, independent of subscriptions? Is there a way to "assign" users to specific applications so that they can invoke only API to which application is subscribed?

No, it should work the same as with oauth2 token. Only subscribed user can invoke API, doesn't matter if via token or Basic Auth.

You can't assign users to applications, because it works the opposite ways - applications belong to user. If you want more fine-grained control, create roles in /carbon console and assign it to the users. In API publisher, go to API settings, change visibility on devportal to specific role. Then create scopes with specific role for each resource, assign this scope to the resource, enable security. Subscribed users than can ivoke the API, but without you assigning a role to the user, they cannot call any protected resource.

If both Prod and Sandbox share the same Gateway, how is determined which one is invoked when doing basic auth?

Good question. I don't know the answer.

By the way, this wouldn't work with consumer key and secret. Endpoint is specified during /token generation AFAIK.

markokocic commented 4 years ago

Hi @Tomas-Mrazek and @tmkasun , this is exactly my issue with Basic authentication now. Let me try to summarize my thoughts on the authentication:

OAuth2 - we subscribe App to an Api. Based on the key and secret, we know the App and the Environment. So, in order to allow App to use Api all we need to do is to subscribe it. Then, any user can call that Api given that he knows key and secret.

Static Api Keys - here we know the Key, and that gives enough information to know which Application is calling the Api, and which environment it uses. The concept of App subscribing to the Api in order to use it still applies. We only need to subscribe App to an Api.

Basic authentication as is now - I will call it "user based basic auth". It completely abandons the concept of App and subscription, and requires using different concept (user-based permissions) and different tools like using Carbon admin instead of Publisher or Store/DevPortal. And it can't distinguish between production and sandbox environment when a single gateway is used for both. It also gives additional level of complexity to set up and administer. Now it's not enough to look at the list of subscribed Apps, one must also go to carbon admin and look at the users and permissions. And if I want to rate limit one specific App for an Api, or have different subscription levels, I can't do that for the user.

What I would see as a "correct" way of supporting Basic Authentication would be the following:

App-level Basic Authentication - We drop the user from the concept (like with static keys) and use the application authentication instead. Application still needs to subscribe to the Api. Consumer Key and Consumer secret are used as basic authentication credentials. That way we keep App / Api Subscription concept, can continue to use the same tools as for everything else (publisher / devPortal, no need for Carbon Admin), and we know which App uses which Api and which environment based on the keys.

How to get there?

There are two options. Either change the current Basic implementation to the one proposed above, or implement a new one called "App Basic authentication". There's also a third option, to support both user/pass and key/secret in the existing basic auth, but that's the dirtiest one.

TomasTokaMrazek commented 4 years ago

Basic Auth implementation is not enough. For example you can limit API visibility on devportal based on roles -> which needs to be created and associated with user via Carbon console.

tmkasun commented 4 years ago

Hi @Tomas-Mrazek and @markokocic Thank you for your suggestions, Please find my answers inline.

How do subscriptions work with basic auth? Seems like any user can invoke any Api, independent of subscriptions? Is there a way to "assign" users to specific applications so that they can invoke only API to which application is subscribed?

Basic auth support for client requests does not require subscriptions to be present. If an API creator has enabled Basic Authentication support for a particular API, That API can be invoked without subscribing to that API (By application). and @markokocic yes, how subscription works is , An Application subscribed to an API.

Furthermore with Baisc auth: you still get:

you won't get:

If both Prod and Sandbox share the same Gateway, how is determined which one is invoked when doing basic auth?

Yes, we couldn't differentiate the environment by username and password, Hence when using basic auth, you will not have option to select the environment, Production endpoint will be used.

@Tomas-Mrazek

Endpoint is specified during /token generation AFAIK.

No, Endpoints (Prod & Sandbox) are defined by the API creator when creating the API, API consumers can provide callback URL for an application if they want to use re-direction based grant type(s) (i:e implicit)

@markokocic regarding

App-level Basic Authentication

This is possible with current implementation as well. You can use the client credentials grant type to get token pair on behalf of the application owner.

markokocic commented 4 years ago

App-level Basic Authentication

This is possible with current implementation as well. You can use the client credentials grant type to get token pair on behalf of the application owner.

@tmkasun Yes, it's possible to use Basic authentication to generate token using client credentials. You use something like this:

curl -k -X POST https://localhost:8243/token -d "grant_type=client_credentials" -H "Authorization: Basic Base64(consumer-key:consumer-secret)"

However, to use the API, your consumer still needs to be able to:

It's OK if a programmer program your consumer, or you have a vendor that can do it. As described, the issue is with many legacy enterprise clients that are not customizable. For example in SAP if you want to consume external service the only thing you can set is URL, and optionally username and password for basic authentication. There you don't have ability to fetch token or set custom headers.

What I described as App-level Basic Authentication above is actually the ability to skip the step of token generation, and directly use Basic Authentication based on client credential to invoke the API.

Something like:

curl -k -X POST https://localhost:8243/my/nice/Api/doSomething -H "Authorization: Basic Base64(consumer-key:consumer-secret)"

This would allow me to still use the same App to API subscription model in an uniform way, without the need to create, setup and manage users.

As another benefit, since Basic authentication standard provides an ability to include authorization header as part of the URL, we could even support legacy Consumers with something like this:

curl -k -X POST https://consumer-key:consumer-secret@localhost:8243/my/nice/Api/doSomething

EDIT: Now that I think about it, maybe the clearer name would be the Client-Credentials based Basic Authentication for API.