Kerberos Delegation with WSO2 API Manger

Ashen Weerathunga
8 min readMar 31, 2019

I hope now you know about kerberos if you read my previous article. In a nutshell Kerberos is a network authentication protocol, and is currently the default authentication technology used by Microsoft to authenticate users to services within a local area network.

So in this article I’m going to discuss on how, Kerberos delegation can be used to access a kerberos protected backed service, by a client application running on a Windows machine, via WSO2 API Gateway.

Kerberos Delegation?

Kerberos Delegation is used when a service requires access to another service on a different computer (backend server, database server) on behalf of another user.

Let’s see the steps needs to be followed in order to achieve the above use case,

AD domain setup

I have configured the following deployment where the Active directory, IIS server and client are in the same domain (WSO2.TEST). But the WSO2 APIM can be hosted in Linux or Windows environment. So the backend service is hosted in IIS server with windows authentication enabled and it acts as the backend of the API configured in APIM.

So I’m going to achieve the following scenario with the above setup via kerberos delegation.

So let’s see the steps you need to follow in order to successfully configure the kerberos delegation with WSO2 APIM.

Users setup

In Microsoft Active Directory (AD), create the following users.

  • clientuser
  • apimuser
  • serevertest

I’m going to use apimuser for the APIM. So the delegation capability should be enabled for apimuser. So follow the below steps,

  1. Go to Active directory Users and Computers.
  2. Click on Users.
  3. Search for your domain user account (in our case apimuser) and go to its properties.

Select the delegation tab and choose the second option (unconstrained delegation) Trust this account for delegation to any service where you are authorizing the domain account apimuser with the power to delegate the logged in credentials of a user to any backend service running on any machine.

We might have policies where we don’t want to enable delegation to all the services. So we don’t want to have unconstrained delegation setup due to some security policies in such cases we need to enable constrained delegation.

To enable constrained delegation on the delegation tab select the 3rd option where it says Trust this account for delegation to specified service and in the bottom windows you can add the list of backend services (servertest) specific to the machines to which your SPN account can delegate the login credentials.

SPN setup

Open up the command prompt and set the Service Principal Names (SPN) for your backend service, apim and client using the following commands:

  • setspn -s service/kerberos.api servertest
  • setspn -s HTTP/apim.com apimuser
  • setspn -s HTTP/client.com clientuser

IIS Setup

IIS (Internet Information Services) is a web server from Microsoft which runs on Windows systems. So I’m going to use it to host our backend service and protect it with windows authentication.

You can refer this documentation for IIS 8.5 installation steps,

Note: Ensure that you have administrative user rights on the computer on which you plan to install IIS 8.5. Note that by default, you do not have administrative user rights if you are logged on as a user other than the built-in administrator, even if you were added to the local Administrators group on the computer.

Hosting a web API in IIS

I’m going to use a C# web API as the backend and refer this article for the steps you need to follow,

You can download the sample web API which I implemented from below location.

Source code: https://github.com/ashensw/kerberos-delegation-demo/tree/master/CustomerAPI

Note: Make Sure you have open the relevant port in the IIS machine in order to access the API from outside.

Enable windows authentication

Click on the website (backend API), go to authentication and make sure that windows authentication is enabled. Make sure that when you want to use windows authentication, anonymous authentication is not enabled.

Enabling windows authentication doesn’t mean Kerberos protocol will be used. it might also use NTLM which is also a provider in windows authentication.

In order to setup Kerberos for the site, make sure Negotiate is at the top of the list in providers section that you can see when you select windows authentication. Negotiate is a provider or container which supports Kerberos protocol, and it also contains NTLM as a backup when Kerberos fails due to some reason. But one important thing to keep in mind over here is when we want to use Kerberos, Negotiate should be at the top.

Then go to the advanced settings of your application pool under which your website is running and change the identity to the domain account. In our case it will be WSO2.TEST\servertest

Now Click on the site and go to configuration editor and traverse to the path and make useAppPoolCredentials = true and useKernelMode = false

When you have useAppPoolCredentials set to true you are telling IIS that it needs to use its application pool identity (which we have changed in the previous step to point to domain account) to decrypt the Kerberos token which was obtained from KDC and forwarded by the client to the server to authenticate the user.

Configure WSO2 APIM

Now we need to configure an API with the above kerberos protected backend. So I have the backend APIs as below,

http://<IIS-Host>:port/api/customerhttp://<IIS-Host>:port/api/customer/{id}

So I can configure our API in the APIM as below,

Note: We need to define custom header to send the access token (for authenticating the API) instead of Authorization header since the Kerberos ticket will be sent in the Authorization header. So we can define the custom header (Ex: X-APIM-Auth) as below when creating the API to send the access token in the request.

Enable custom handler

Kerberos delegation capability does not comes with WSO2 APIM OOTB. So I have implemented a custom handler to achieve it. So let’s engage the custom handler to the above API in order to do enable Kerberos delegation. You can follow the below steps,

Source code: https://github.com/ashensw/kerberos-delegation-handler

Build the custom handler code below, and copy the resulting jar to following directory in path.

<API-M_HOME>/repository/components/dropins

Engage the custom handler using the API template as explained below:

You can engage a custom handler to all APIs at once or only to selected APIs. To engage a custom handler to APIs, you need to add the custom handler with its logic in the following file,

<APIM_HOME>/repository/resources/api_templates/velocity_template.xml

For example, the following code segment adds the custom authentication handler that you wrote earlier to the velocity_template.xml file

You can select to which API(s) you need to engage the handler. Given below is an example of adding only the CustomKerberosDelegationHandler to the sample KerberosDemoAPI.

Make Sure to configure the SPN of the IIS backend service as the targetSPN property in the handler as below,

#if($apiName == ‘admin — KerberosDemoAPI’)<handler class=”org.wso2.apim.kerberos.handler.CustomKerberosDelegationHandler”>
<property name=”targetSPN” value=”service/kerberos.api@WSO2.TEST”/>
</handler>
#end

Configuration Files

Create a directory called<APIM_HOME>/repository/conf/security/kerberos inside following path and add the following config files,

  • krb5.conf
  • login.conf
  • apim.keytab

Sample krb5.conf file:

[libdefaults]default_realm = WSO2.TEST[realms]WSO2.TEST = {kdc = 192.1xx.xx.158:88}[domain_realm].wso2.test = WSO2.TESTwso2.test = WSO2.TEST

Sample login.conf file:

KrbLogin {com.sun.security.auth.module.Krb5LoginModule requireduseTicketCache=falserefreshKrb5Config=truedoNotPrompt=trueuseKeyTab=truedebug=truestoreKey=trueprincipal=”http/apim.com@WSO2.TEST”keyTab=”repository/conf/security/kerberos/apim.keytab”;};

Command to create a Keytab (apim.keytab)

ktpass /out apim.keytab /princ HTTP/apim.com@WSO2.TEST /mapuser apimuser /pass password /crypto All /ptype KRB5_NT_PRINCIPAL

Let’s try it out!

Ok. Finally the setup is completed. Now let’s see how we can try it out. I have implemented a simple C# console app to do that. You can download the source code from below location,

Source code: https://github.com/ashensw/kerberos-delegation-demo/tree/master/KerberosClient

After downloading the app, configure the following in the program.cs file in the C# project according to your API and application which subscribed the API.

static string tokenEndpoint = “http://apim.com:8280/token";static string apiURL = “http://apim.com/demo/1.0.0/api/customer";static string apimSPN = “http/apim.com@WSO2.TEST”;
static string username = “TcY6H40VdgwdGyV1haxwtS9zxT8a”;
static string password = “2Fs1lm4hOZsPBe5ntyE50EfijkAa”;

Note: In this client app you have the capability to get the access token via kerberos grant type or password grant type. So if you are trying the kerberos grant you need to follow the steps as mentioned in the documentation.

After the configurations run the console application as below and you will see the succesfull API response at the end! 😊

Summery

In this article we discussed an advance use case of Kerberos and how we can implement it with WSO2 API Manger. We used a kerberos protected backend for a API deployed in WSO2 API Gateway and invoked it from a client application running on a Windows environment.

References:

  1. https://docs.microsoft.com/en-us/iis/install/installing-iis-85/installing-iis-85-on-windows-server-2012-r2
  2. https://dzone.com/articles/backend-web-api-with-c-step-by-step-tutorial
  3. https://manage.accuwebhosting.com/knowledgebase/2886/How-to-configure-IIS-to-access-website-using-IP-address.html

--

--