JWT claim based routing
Note: this feature only supports Istio ingress gateway and requires the use of both request authentication and virtual service to properly validate and route based on JWT claims.
The following information describes an experimental feature, which is intended for evaluation purposes only.
Understand Istio and virtual service concepts.
Install Istio using the .
Deploy a workload, in a namespace, for example
foo
, and expose it through the Istio ingress gateway with this command:Follow the instructions in Determining the ingress IP and ports to define the
INGRESS_HOST
andINGRESS_PORT
environment variables.-
$ curl "$INGRESS_HOST:$INGRESS_PORT"/headers -s -o /dev/null -w "%{http_code}\n"
200
If you don’t see the expected output, retry after a few seconds. Caching and propagation overhead can cause a delay.
The Istio ingress gateway supports routing based on authenticated JWT, which is useful for routing based on end user identity and more secure compared using the unauthenticated HTTP attributes (e.g. path or header).
In order to route based on JWT claims, first create the request authentication to enable JWT validation:
$ kubectl apply -f - <<EOF
apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
name: ingress-jwt
namespace: istio-system
spec:
selector:
matchLabels:
istio: ingressgateway
- issuer: "testing@secure.istio.io"
jwksUri: "https://raw.githubusercontent.com/istio/istio/release-1.15/security/tools/jwt/samples/jwks.json"
EOF
The request authentication enables JWT validation on the Istio ingress gateway so that the validated JWT claims can later be used in the virtual service for routing purposes.
The request authentication is applied on the ingress gateway because the JWT claim based routing is only supported on ingress gateways.
Note: the request authentication will only check the JWT if it exists in the request. To make the JWT required and reject the request if it does not include JWT, apply the authorization policy as specified in the task.
Update the virtual service to route based on validated JWT claims:
$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
metadata:
name: httpbin
namespace: foo
spec:
hosts:
- "*"
gateways:
- httpbin-gateway
http:
- match:
- uri:
prefix: /headers
headers:
"@request.auth.claims.groups":
exact: group1
- destination:
port:
number: 8000
host: httpbin
EOF
Claim of type string, list of string and nested claims are supported. Use the
.
as a separator for nested claim names. For example,"@request.auth.claims.name.givenName"
matches the nested claimname
andgivenName
. Claim name with the.
character is currently not supported.
Validate the ingress gateway returns the HTTP code 404 without JWT:
You can also create the authorization policy to explicitly reject the request with HTTP code 403 when JWT is missing.
Validate the ingress gateway returns the HTTP code 401 with invalid JWT:
$ curl -s -I "http://$INGRESS_HOST:$INGRESS_PORT/headers" -H "Authorization: Bearer some.invalid.token"
HTTP/1.1 401 Unauthorized
...
The 401 is returned by the request authentication because the JWT failed the validation.
Validate the ingress gateway routes the request with a valid JWT token that includes the claim
groups: group1
:$ TOKEN_GROUP=$(curl https://raw.githubusercontent.com/istio/istio/release-1.15/security/tools/jwt/samples/groups-scope.jwt -s) && echo "$TOKEN_GROUP" | cut -d '.' -f2 - | base64 --decode -
{"exp":3537391104,"groups":["group1","group2"],"iat":1537391104,"iss":"testing@secure.istio.io","scope":["scope1","scope2"],"sub":"testing@secure.istio.io"}
$ curl -s -I "http://$INGRESS_HOST:$INGRESS_PORT/headers" -H "Authorization: Bearer $TOKEN_GROUP"
HTTP/1.1 200 OK
...
Validate the ingress gateway returns the HTTP code 404 with a valid JWT but does not include the claim
groups: group1
:$ curl -s -I "http://$INGRESS_HOST:$INGRESS_PORT/headers" -H "Authorization: Bearer $TOKEN_NO_GROUP"
HTTP/1.1 404 Not Found
...
-
$ kubectl delete namespace foo