Security is one of the most important aspects to consider when making the move toward microservices. End-user authentication is a crucial part of that and enables enterprises to protect themselves from unauthorized access.

For example, a web-based application is deployed in the service mesh, and a user wants to access it over a 4G network from a mobile device. From the application’s point of view, all requests must be authenticated. In other words, the user should be verified as an authenticated user before a communication channel is established with the application server. But because the application is a microservice, it can’t handle authentication on its own.

Istio can solve this problem with “origin” or “end-user” JWT identity token verification. Within the token, you can easily specify user roles and permissions, as well as resources that a user can access. Istio offloads the authentication logic from services to a proxy. A request from our user to the web-based application will be authenticated and authorized within the Citrix ADC and will be forwarded to the back-end service. This enables developers to focus on coding and delivering business value.

In our posts on Citrix ADC as an Istio Ingress Gateway (Part 1 and Part 2), you can learn about deployment of Citrix ADC as an Ingress Gateway in Istio Service Mesh. Here, we’ll look at implementing end-user authentication in Istio Service Mesh using Citrix ADC.

End-user authentication using a JWT token.

First, you need a valid token for end-user authentication, as shown above. Here, I’m using pre-generated JWT and JWKS from the Istio code base. If you’ve applied Citrix ADC as an ingress gateway for the bookinfo application, you can use the yaml below to authenticate the user before allowing access to the bookinfo application.

cat <<EOF | kubectl apply -n citrix-system -f -
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
  name: "bookinfo-jwt"
spec:
  targets:
  - name: citrix-ingressgateway
  origins:
  - jwt:
      issuer: "testing@secure.istio.io"
      jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.4/security/tools/jwt/samples/jwks.json"
  principalBinding: USE_ORIGIN
EOF

export INGRESSIP =$(kubectl get pods -l app=citrix-ingressgateway -n citrix-system -o 'jsonpath={.items[0].status.hostIP}')

With this configuration, if a client tries to access the bookinfo application, the request wouldn’t make it to the bookinfo service unless the JWT authentication succeeds.

$curl  $INGRESSIP/productpage -s -o /dev/null -w "%{http_code}\n"
401

You can pass the TOKEN below to access the bookinfo application.

$TOKEN=$(curl https://raw.githubusercontent.com/istio/istio/release-1.4/security/tools/jwt/samples/demo.jwt -s)

$curl --header "Authorization: Bearer $TOKEN" $INGRESSIP/productpage -s -o /dev/null -w "%{http_code}\n"
200

Disable End-User Authentication for Specific URLs

End user authentication can be disabled for specific URLs, like a login page or health monitor. Let’s modify the “bookinfo-jwt” policy to disable end-user authentication for URL “/productpage”.

cat <<EOF | kubectl apply -n citrix-system -f -
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
  name: "bookinfo-jwt"
spec:
  targets:
  - name: citrix-ingressgateway
  origins:
  - jwt:
      issuer: "testing@secure.istio.io"
      jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.4/security/tools/jwt/samples/jwks.json"
      trigger_rules:
      - excluded_paths:
        - exact: /productpage
  principalBinding: USE_ORIGIN
EOF

The URL “/productpage” can be accessed without authentication while other URLs will require a valid JWT token.

$curl $INGRESSIP/productpage -s -o /dev/null -w "%{http_code}\n"
200

The request to a page URL other than “/productpage” will fail.

$curl $INGRESSIP -s -o /dev/null -w "%{http_code}\n"
401

Enable End-User Authentication for Specific URLs

It’s possible to enable end-user authentication for specific URLs. For example, you can enable authentication only for a URL that is used to display user logs (/logs). Let’s modify the “bookinfo-jwt” policy to enable end-user authentication only for the URL “productpage”.

$cat <<EOF | kubectl apply -n citrix-system -f -
apiVersion: "authentication.istio.io/v1alpha1"
kind: "Policy"
metadata:
  name: "bookinfo-jwt"
spec:
  targets:
  - name: citrix-ingressgateway
  origins:
  - jwt:
      issuer: "testing@secure.istio.io"
      jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.4/security/tools/jwt/samples/jwks.json"
      trigger_rules:
      - included_paths:
        - exact: /productpage
  principalBinding: USE_ORIGIN
EOF

All the traffic intended for the URL other than “/productpage” will not require a JWT token.

$curl $INGRESSIP/ -s -o /dev/null -w "%{http_code}\n"
200

Without a JWT token, access to the URL “/productpage” is denied.

$ curl $INGRESSIP/productpage -s -o /dev/null -w "%{http_code}\n"
401

With a valid JWT Token, you can access URL “/productpage”.

$TOKEN=$(curl https://raw.githubusercontent.com/istio/istio/release-1.4/security/tools/jwt/samples/demo.jwt -s)
$ curl --header "Authorization: Bearer $TOKEN" $INGRESSIP/productpage -s -o /dev/null -w "%{http_code}\n"
200

Citrix ADC seamlessly integrates with Istio Service Mesh in all ways, including security, and the end-user authentication use case I’ve covered here is one of the most common. Stay tuned for more blog posts on our integrations with Istio Service Mesh. And for more information on how to get started, check out our GitHub page.