Istio Enduser Authentication with WSO2 Identity Server

ajanthan
5 min readJun 17, 2019

Service meshes are becoming an essential tool to build distributed applications nowadays. You could call it microservices architecture or service-oriented architecture essentially all of them are distributed application architecture where applications communicate through the network. The network is always not reliable but the applications should be reliable and predictable. The only way we can build reliable applications over an unreliable network is by gracefully handling network failures in applications. This is where service meshes play a big role by providing a way to segregate the responsibilities of handling network failure in language or framework independent way from the applications.

There are a variety of service mesh implementations out there. Istio, Linkerd, AWS app mesh and consul connect are well-known service mesh implementations.

End-user authentication is one of the service mesh features. When the networked services or applications talk to each other, sometimes the communication will happen on behalf of an end user. In that case, the application should verify the end user identity in order to avoid unintended security issues. Traditionally the IAM(Identity and access management) systems are responsible for validating user identity. Service meshes along with IAM can validate the end user identity during any service to service communication.

In this article, we are going to look at how an end user authentication can be done in Istio using WSO2 identity server. WSO2 Identity Server is an open source IAM solution from WSO2 Inc.

Prerequisite

Followings are the prerequisite for this exercise.

  1. A Kubernetes environment
  2. WSO2 Identity Server deployment on Kubernetes
  3. Istio on Kubernetes

There are ranges of options for having a Kubernetes deployment. From Kubernetes as service from big cloud providers to Mini Kube. In this exercise, I am going to focus on testing it on Mini Kube which is convenient deployment to test in a developer work station. Follow the Mini Kube installation documentation and have a Mini Kube deployment with sufficient memory allocated(8 GB is a minimum required memory for this exercise).

The next step is to deploy WSO2 identity server on Kubernetes. I have written a post on how to do it. Feel free to follow it and have a functioning WSO2 identity deployment on your preferred Kubernetes deployment.

The next step is to install Istio. Istio official documentation is pretty comprehensive and anybody with little experience could follow the document and install it. For trying Istio for demo purpose the Quickstart evaluation guide is a best.

The final step is to deploy a sample service, apply an Istio end-user authentication security policy and test it.

Deploying a Sample Service

Istio comes with lots of samples. Here, we are going to use one of the samples. Httpbin sample is a proxy for the httbin site. In this exercise, we are going to deploy the Httbin sample. Goto the installation directory and issue following command.

kubectl apply -f <(istioctl kube-inject -f samples/httpbin/httpbin.yaml)

Here the assumption is the Istio auto sidecar injection is disabled. It will take a while to pull the docker images and start the PODs.

Applying Istio Traffic Rules

In order to access the service from outside of the Kubernetes, an Ingress gateway is needed. Istio itself has a Gateway that can act as an ingress gateway. Here we are going to use Istio Gateway instead of other Ingress Gateways. I have the required Istio policies in a GitHub repository.

Clone the repository and apply the Virtual service and gateway policy.

git clone https://github.com/ajanthan/istio-enduser-authentication-with-wso2is.git

cd istio-enduser-authentication-with-wso2is
kubectl apply -f httpbin-gateway.yaml
kubectl apply -f httpbin-virtualservice.yaml

Now the service could be accessed from outside using ingress host and the ingress port(to determine the host and the port follow Istio documentation). In this stage, the service is accessible by anybody who has network access. In the next step, an end user authentication policy is going to be applied and secure the service.

Applying End User Authentication Policy

Istio supports two kinds of authentication. First one is Transport Authentication or Service to Service Authentication through Mutual TLS(m-TLS) and the second one is Origin Authentication or End User Authentication through JWT. In the case of JWT authentication, Istio will be able to validate a request with a valid JWT issued by any OpenId Connect provider. Through the authentication policy, type of authentication and other required details are configured.

We are going to apply the following Authentication Policy to authenticate the service request with JWT issued by WSO2 Identity Server.

apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
name: "jwt-example"
spec:
targets:
- name: httpbin
origins:
- jwt:
issuer: "https://wso2is:9443/oauth2/token"
jwksUri: "http://wso2is-service.default.svc.cluster.local:9763/oauth2/jwks"
principalBinding: USE_ORIGIN

Here the important details are the issuer and the jwkUri. In the case of WSO2 identity server, those details could be found in the OpenID connect discovery configuration. The principalBinding also required to instruct the Istio to get the JWT from the header(in the form of Authorization: Bearer <jwt>).

The above policy is available in the Github repository mentioned in the previous step. Apply the policy as follows.

kubectl apply -f jwt-auth-policy.yaml

Now the service access is protected by JWT authentication. Only the requests with JWT issued by WSO2 Identity server will be allowed. In the next step, we are going to generate a JWT and call the service using CURL command.

Calling the Service

As mentioned before in order to call the service a JWT is needed from WSO2 Identity server. We have to use OAuth2 token API to generate a token(an OpenId token). The first step in Generating an OpenID connect token is to register an OAuth2 application. Access the WSO2 Identity Server management console at https://wso2is/carbon and create a new service provider with OAuth/OpenID Connect Configuration inbound authentication type.

After a successful application registration, get the Client ID and the Client secret of the registered application as mentioned in the last step of the above guide.

There are multiple ways you can generate a JWT using different grant types as mentioned in the above guide but the easiest one is the password grant type. In this guide, we are going to use the password grant type to generate an OpenID token.

curl -vk -d "grant_type=password&username=admin&password=admin&scope=openid" -H "Authorization: Basic base64encode(OAuth Client Key:OAuth Client Secret)" -H "Content-Type: application/x-www-form-urlencoded" https://wso2is/oauth2/token

This will give a JSON as response. From the response extract id_token, this is the JWT we are going to use to invoke the service.

Invoke the service as follows.

curl -kv  http://$INGRESS_HOST:$INGRESS_PORT/headers -H "Authorization: Bearer <id_token>"

Here the $INGRESS_HOST and $INGRESS_PORT should be determined using Istio documentation.

This time you will be able to get a response from the Httpbin service(a none 401 response). Yes, We just called the service successfully using a JWT issued by WSO2 Identity Server.

In Summary, In Istio through an Authentication policy, JWT authentication could be enforced along with OpenID connect provider like WSO2 Identity Server.

--

--