apim
2020/03/22
22 Mar, 2020

Basic Authentication for API Clients in WSO2 API Manager

  • Johann Nallathamby
  • Director - Solutions Architecture - WSO2

Introduction

Many organizations that embrace an API strategy would have experienced a situation where they had to support Basic Authentication (BasicAuth) for their API clients in addition to OAuth2 due to reasons such as clients’ reluctance to move from BasicAuth to OAuth2. This is even more so a case for 3rd party API clients and partner API clients who can be large in numbers, rather than for 1st party API clients, whom the API product managers have more control over.

BasicAuth credentials that are used in such situations can fall under one of the following categories:

  1. System credentials
  2. End-user credentials

In most BasicAuth scenarios, the credentials are system credentials. Each client receives a unique set of credentials that they will use to authenticate to the backend resources when performing backend resource calls on behalf of the end-user accessing the particular system, regardless of who the end-user is. In other words, the end-user identity is not really considered for the backend resource access. Reasons could be either the backend resources consumed are not handling any end-user specific data or the client system is considered a trusted subsystem which will authenticate and authorize the end-user reliably and pass on only the end-user context to the backend resource.

In some other scenarios, the credentials can be the end-user credentials themselves.

Limitation in Basic Authentication Support in API Manager 3.0.0

Basic Authentication support was introduced in WSO2 API Manager 3.0.0. You won’t be able to get application level throttling and application level API analytics for your API clients if you go with Basic Authentication for them. This is because WSO2 API Manager’s throttling and API analytics implementations are tightly coupled with the OAuth2 client identifier. In the cases described above, it will be invaluable to have throttling and API analytics for the individual API clients.

Three Possible Solutions to Overcome the Limitation

We will look at 3 potential solutions that you may be able to implement in your environment to overcome the above limitations.

Solution 1  - Customize DevPortal for System Credentials

This solution is applicable only if the BasicAuth credentials are system credentials. The idea behind this solution is to use the BasicAuth system credentials as the user provided OAuth2 client credentials.

WSO2 API Manager versions prior to version 3.0.0 had non-editable “Consumer Key” and “Consumer Secret” fields. The Developer Portal only allowed you to generate these values. However, with some UI level customizations, you can make them optionally editable text fields so that the application developers have the option of providing their own client identifier and client secret. Some identity providers already provide this as a feature, but unfortunately WSO2 Developer Portal is not one of them. This also becomes a very strong requirement in scenarios where WSO2 Developer Portal has to be integrated with a 3rd party OAuth2 authorization server under the authorization server replacement pattern, where the applications have to be registered with existing OAuth2 client credentials in the 3rd party authorization server. After completing the above customization, add the username and password values sent by the BasicAuth client to the “Consumer Key” and “Consumer Secret” fields. When the API call arrives at the API Gateway with BasicAuth credentials, a custom APIHandler that is placed before the APIAuthenticationHandler will extract the credentials and call the OAuth2 token endpoint with client_credentials grant flow to obtain an OAuth2 access token. The OAuth2 access token will replace the BasicAuth credentials and be passed downstream to the next set of handlers as if the request had arrived at the WSO2 API Gateway with an OAuth2 access token.

Finally, in some scenarios, it is required to pass the BasicAuth credentials sent from the client, all the way down to the backend resource server. Most of these backend resource servers expect the BasicAuth credentials in the standard Authorization header. In order to support this requirement, you can do the following:

  1. Customize the header that carries the OAuth2 access token so that it is different to the standard “Authorization” header [3]. You can configure this at different levels such as global, tenant, and API based on your use case as described in the document.
  2. The custom APIHandler can set the OAuth2 access token that it generates to the specific custom HTTP header that has been configured in point 1.

Solution 2  -  Embed OAuth2 into BasicAuth

This solution is applicable for both cases where BasicAuth credentials are system credentials or end-user credentials. The idea behind this solution is to re-use the parameters that are used to pass BasicAuth credentials to include the OAuth2 client credentials as well.

Generally, when an application is implemented in a particular technology, the variable parameters of that application are read from a configuration file or something similar, where you could provide values for such parameters from the external environment. The benefit of externalizing these variable parameters is that these external sources can be then managed and governed independently of the applications. Generally speaking, a change of value in any one of these external sources is not considered an application change, since it doesn’t require developers to perform source code changes or source code compilation, and it doesn’t affect the user experience.

When developing a BasicAuth client in their application, most application developers will externalize the BasicAuth credentials to a file or some other source. In such a case, we should be able to easily replace the values for the “username” and “password” fields to include the client_id and client_secret values as follows:

username = base64({client_id}:{username})

password = base64({client_secret}:{password})

Effectively, the authorization header value that will be passed on from the API client to the API Gateway will have the following format:

Basic base64(base64({client_id}:{username}):base64({client_secret}:{password}))

The above convention assumes that the “client_id” and “client_secret” don’t contain “:” (colon), which is the case at least up to WSO2 API Manager 3.0.0. When the API call arrives at the API Gateway with BasicAuth credentials, a custom APIHandler that is placed before the APIAuthenticationHandler, will read the Authorization header value, split and identify the individual tokens such as client_id, client_secret, username, and password.

Based on whether the BasicAuth credentials are system credentials or end-user credentials, the custom APIHandler may do one of the following two:

  1. If the credentials are system credentials, it would call the authenticate operation in the API Key Manager’s RemoteUserStoreManager API with the username/password pair. If the authentication passes, then it will construct an OAuth2 client_credentials grant request to the OAuth2 token endpoint, using the client_id/client_secret pair and generate an access token.
  2. If the credentials are end-user credentials, it would construct an OAuth2 password grant request to the OAuth2 token endpoint, using the tokens identified above, and generate an access token.

Then, as demonstrated in solution 1, the custom APIHandler will replace the BasicAuth credentials with the generated OAuth2 access token and pass it downstream to the next set of handlers, as if the request had arrived at the API Gateway with an OAuth2 access token.

Finally, as we discussed under solution 1, scenarios, where you are required to pass the BasicAuth credentials sent from the client all the way down to the backend resource server, may exist. Follow the same steps as listed in solution 1 to support this requirement.

Solution 3  - Blanket Application

In scenarios where you are not able to enforce either solution 1 or 2 above for some reason, this solution could work. However, it doesn’t give the exact benefits as the other solutions. The idea behind this solution is to group all BasicAuth clients concerned under one designated application which is known as a blanket application and handle throttling and API analytics on the group of clients.

  1. Create a separate designated application for the concerned BasicAuth clients and generate keys in the Developer Portal.
  2. When the API call arrives at the API Gateway with BasicAuth credentials, a custom APIHandler that is placed before the APIAuthenticationHandler will construct an OAuth2 password grant request and send it to the OAuth2 token endpoint. This will use the designated client_id/client_secret pair baked into the APIHandler, along with the username/password pair found in the BasicAuth credentials, and obtain an OAuth2 access token.
  3. Then the custom APIHandler will replace the BasicAuth credentials with the generated OAuth2 access token and pass it downstream to the next set of handlers as if the request had arrived at the API Gateway with an OAuth2 access token.

In this solution, the throttling and API analytics will be performed treating all clients as a single application in WSO2 API Manager. This will at least separate the non-standard applications from the standard OAuth2 applications of WSO2 API Manager - based on which you can enforce specific white listing, black listing, and throttling policies to mitigate potential security breaches.

Even in this case, since the BasicAuth credentials can differ from one call to another, either based on the client or end-user, you can drill down the API analytics data further based on the end-user context of the API calls. However, since in the default API Analytics dashboards you don’t have many drill-down capabilities on this aspect, you may have to build your own reports for this using the API analytics data. For throttling based on the end-user context of the API calls, you may use the advanced throttling capability of WSO2 API Manager.

Summary

In this article we’ve looked at some of the reasons why Basic Authentication for APIs is still widely prevalent, limitations in the Basic Authentication support provided in API Manager 3.0.0, and 3 possible solutions to overcome those limitations. Learn more about WSO2 API Manager here.

References

[1] https://medium.com/@johann_nallathamby/identity-propagation-in-a-gateway-architecture-e898b9eec5ca

[2] https://wso2.com/library/article/2019/09/architecture-for-third-party-authorization-server-integration

[3]https://apim.docs.wso2.com/en/latest/learn/api-security/api-authentication/secure-apis-using-oauth2-tokens/#customizing-the-authorization-header

 

About Author

  • Johann Nallathamby
  • Director - Solutions Architecture
  • WSO2