JWT Authentication
5 minute read
This task provides instructions for configuring JSON Web Token (JWT) authentication. JWT authentication checks
if an incoming request has a valid JWT before routing the request to a backend service. Currently, Envoy Gateway only
supports validating a JWT from an HTTP header, e.g. Authorization: Bearer <token>
.
Envoy Gateway introduces a new CRD called SecurityPolicy that allows the user to configure JWT authentication. This instantiated resource can be linked to a Gateway, HTTPRoute or GRPCRoute resource.
Prerequisites
Follow the steps from the Quickstart task to install Envoy Gateway and the example manifest. Before proceeding, you should be able to query the example backend using HTTP.
Verify the Gateway status:
kubectl get gateway/eg -o yaml
egctl x status gateway -v
For GRPC - follow the steps from the GRPC Routing example.
Configuration
Allow requests with a valid JWT by creating an SecurityPolicy and attaching it to the example HTTPRoute or GRPCRoute.
HTTPRoute
kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/latest/examples/kubernetes/jwt/jwt.yaml
Two HTTPRoute has been created, one for /foo
and another for /bar
. A SecurityPolicy has been created and targeted
HTTPRoute foo to authenticate requests for /foo
. The HTTPRoute bar is not targeted by the SecurityPolicy and will allow
unauthenticated requests to /bar
.
Verify the HTTPRoute configuration and status:
kubectl get httproute/foo -o yaml
kubectl get httproute/bar -o yaml
The SecurityPolicy is configured for JWT authentication and uses a single JSON Web Key Set (JWKS) provider for authenticating the JWT.
Verify the SecurityPolicy configuration:
kubectl get securitypolicy/jwt-example -o yaml
GRPCRoute
kubectl apply -f https://raw.githubusercontent.com/envoyproxy/gateway/latest/examples/kubernetes/jwt/grpc-jwt.yaml
A SecurityPolicy has been created and targeted GRPCRoute yages to authenticate all requests for yages
service..
Verify the GRPCRoute configuration and status:
kubectl get grpcroute/yages -o yaml
The SecurityPolicy is configured for JWT authentication and uses a single JSON Web Key Set (JWKS) provider for authenticating the JWT.
Verify the SecurityPolicy configuration:
kubectl get securitypolicy/jwt-example -o yaml
Testing
Ensure the GATEWAY_HOST
environment variable from the Quickstart is set. If not, follow the
Quickstart instructions to set the variable.
echo $GATEWAY_HOST
HTTPRoute
Verify that requests to /foo
are denied without a JWT:
curl -sS -o /dev/null -H "Host: www.example.com" -w "%{http_code}\n" http://$GATEWAY_HOST/foo
A 401
HTTP response code should be returned.
Get the JWT used for testing request authentication:
TOKEN=$(curl https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/jwt/test.jwt -s) && echo "$TOKEN" | cut -d '.' -f2 - | base64 --decode
Note: The above command decodes and returns the token’s payload. You can replace f2
with f1
to view the token’s
header.
Verify that a request to /foo
with a valid JWT is allowed:
curl -sS -o /dev/null -H "Host: www.example.com" -H "Authorization: Bearer $TOKEN" -w "%{http_code}\n" http://$GATEWAY_HOST/foo
A 200
HTTP response code should be returned.
Verify that requests to /bar
are allowed without a JWT:
curl -sS -o /dev/null -H "Host: www.example.com" -w "%{http_code}\n" http://$GATEWAY_HOST/bar
GRPCRoute
Verify that requests to yages
service are denied without a JWT:
grpcurl -plaintext -authority=grpc-example.com ${GATEWAY_HOST}:80 yages.Echo/Ping
You should see the below response
Error invoking method "yages.Echo/Ping": rpc error: code = Unauthenticated desc = failed to query for service descriptor "yages.Echo": Jwt is missing
Get the JWT used for testing request authentication:
TOKEN=$(curl https://raw.githubusercontent.com/envoyproxy/gateway/main/examples/kubernetes/jwt/test.jwt -s) && echo "$TOKEN" | cut -d '.' -f2 - | base64 --decode
Note: The above command decodes and returns the token’s payload. You can replace f2
with f1
to view the token’s
header.
Verify that a request to yages
service with a valid JWT is allowed:
grpcurl -plaintext -H "authorization: Bearer $TOKEN" -authority=grpc-example.com ${GATEWAY_HOST}:80 yages.Echo/Ping
You should see the below response
{
"text": "pong"
}
Connect to a remote JWKS with Self-Signed Certificate
To connect to a remote JWKS with a self-signed certificate, you need to configure it using the Backend resource within the SecurityPolicy. Additionally, use the BackendTLSPolicy to specify the CA certificate required to authenticate the JWKS host.
The following example demonstrates how to configure the remote JWKS with a self-signed certificate.
cat <<EOF | kubectl apply -f -
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: jwt-example
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: foo
jwt:
providers:
- name: example
remoteJWKS:
backendRefs:
- group: gateway.envoyproxy.io
kind: Backend
name: remote-jwks
port: 443
backendSettings:
retry:
numRetries: 3
perRetry:
backOff:
baseInterval: 1s
maxInterval: 5s
retryOn:
triggers: ["5xx", "gateway-error", "reset"]
uri: https://foo.bar.com/jwks.json
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: Backend
metadata:
name: remote-jwks
spec:
endpoints:
- fqdn:
hostname: foo.bar.com
port: 443
---
apiVersion: gateway.networking.k8s.io/v1alpha3
kind: BackendTLSPolicy
metadata:
name: remote-jwks-btls
spec:
targetRefs:
- group: gateway.envoyproxy.io
kind: Backend
name: remote-jwks
sectionName: "443"
validation:
caCertificateRefs:
- name: remote-jwks-server-ca
group: ""
kind: ConfigMap
hostname: foo.bar.com
EOF
Save and apply the following resource to your cluster:
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: jwt-example
spec:
targetRef:
group: gateway.networking.k8s.io
kind: HTTPRoute
name: foo
jwt:
providers:
- name: example
remoteJWKS:
backendRefs:
- group: gateway.envoyproxy.io
kind: Backend
name: remote-jwks
port: 443
backendSettings:
retry:
numRetries: 3
perRetry:
backOff:
baseInterval: 1s
maxInterval: 5s
retryOn:
triggers: ["5xx", "gateway-error", "reset"]
uri: https://foo.bar.com/jwks.json
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: Backend
metadata:
name: remote-jwks
spec:
endpoints:
- fqdn:
hostname: foo.bar.com
port: 443
---
apiVersion: gateway.networking.k8s.io/v1alpha3
kind: BackendTLSPolicy
metadata:
name: remote-jwks-btls
spec:
targetRefs:
- group: gateway.envoyproxy.io
kind: Backend
name: remote-jwks
sectionName: "443"
validation:
caCertificateRefs:
- name: remote-jwks-server-ca
group: ""
kind: ConfigMap
hostname: foo.bar.com
As shown in the example above, the SecurityPolicy resource is configured with a remote JWKS within its JWT settings. The backendRefs
field references the Backend resource that defines the JWKS host. The BackendTLSPolicy resource specifies the CA certificate required to authenticate the JWKS host.
Additional connection settings for the remote JWKS host can be configured in the backendSettings. Currently, only the retry policy is supported.
For more information about Backend and BackendTLSPolicy, refer to the Backend Routing and Backend TLS: Gateway to Backend tasks.
Clean-Up
Follow the steps from the Quickstart to uninstall Envoy Gateway and the example manifest.
Delete the SecurityPolicy:
kubectl delete securitypolicy/jwt-example
Next Steps
Checkout the Developer Guide to get involved in the project.
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.