We have kubernetese cluster deployed on AWS EKS with Istio 1.11.4.
We are using JWT for authentication and passing it in the header x-jwt-assertion
.
To validate the JWT we are using Istio RequestAuthentication.
Here is the definition
apiVersion: "security.istio.io/v1beta1"
kind: "RequestAuthentication"
metadata:
name: "graphql-jwt"
namespace: graphql
spec:
selector:
matchLabels:
app: graphql
jwtRules:
- issuer: "https://login.<mycompany>.io/"
jwksUri: "https://<mycompany>.us.auth0.com/.well-known/jwks.json"
outputPayloadToHeader: "my-data"
fromHeaders:
- name: x-jwt-assertion
prefix: "Bearer "
We have another service deployed in the cluster that determines based on the request headers and body whether the request should be forwarded or not. We are using Istio CUSTOM Authorization Policy for this. The definition for the AuthorizationPolicy is as following
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: ext-auth-my
spec:
selector:
matchLabels:
app: graphql
action: CUSTOM
provider:
name: my-ext-auth
rules:
- { }
The configurations for this AuthorizationPolicy are defined in the istio
configmap under the istio-system
namespace. The configurations are specified below
apiVersion: v1
data:
mesh: |-
extensionProviders:
- name: "my-ext-auth"
envoyExtAuthzHttp:
service: "my-api-svc.foo.svc.cluster.local"
port: "8080"
pathPrefix: "/hasaccess"
includeRequestHeadersInCheck: ["my-data", "content-type"]
includeRequestBodyInCheck:
maxRequestBytes: 1000000
Now in my service (my-api-svc.foo.svc.cluster.local:8080/hasaccess) I am not getting the my-data
header. If I change the value of includeRequestHeadersInCheck
and remove content-type
, my service throws an error of invalid mime type, and if I replace my-data
with x-jwt-assertion
the request doesn't make it through to my service and I get Jwt issuer is not configured
. So this validates that the headers are getting detected, its for some reason just not making through to my service.
The headers that make it to my service are
x-request-id
x-b3-parentspanid
x-b3-traceid
x-b3-spanid
x-forwarded-client-cert
x-b3-sampled
X-Forwarded-Proto
X-Forwarded-For
Host
Content-Length
Content-Type
I am not able to figure out why my-data
header is not making its way to my api which is to Authorize the request. This header does reach the destination service for which the request was intended for, so it's not getting lost.
I was able to resolve the issue by adding my JWT token in Authorization header instead of x-jwt-assertion and using the forwardOriginalToken property in my RequestAuthentication.
So now RequestAuthentication is
apiVersion: "security.istio.io/v1beta1"
kind: "RequestAuthentication"
metadata:
name: "graphql-jwt"
namespace: graphql
spec:
selector:
matchLabels:
app: graphql
jwtRules:
- issuer: "https://login.<mycompany>.io/"
jwksUri: "https://<mycompany>.us.auth0.com/.well-known/jwks.json"
outputPayloadToHeader: "my-data"
forwardOriginalToken: true
fromHeaders:
- name: Authorization
prefix: "Bearer "
and my istio configmap is
apiVersion: v1
data:
mesh: |-
extensionProviders:
- name: "my-ext-auth"
envoyExtAuthzHttp:
service: "my-api-svc.foo.svc.cluster.local"
port: "8080"
pathPrefix: "/hasaccess"
includeRequestHeadersInCheck: ["Authorization", "content-type"]
includeRequestBodyInCheck:
maxRequestBytes: 1000000
For further details here is the link to the github discussion.