Alibaba Cloud Service Mesh (ASM) handles JWT authentication through two Istio resources that work together:
-
RequestAuthentication defines how tokens are validated -- which issuers and signing keys to trust. It rejects requests that carry invalid tokens but allows requests that carry no token at all.
-
AuthorizationPolicy enforces access decisions -- whether to allow or deny a request based on token presence, claims, or request paths.
RequestAuthentication alone does not block unauthenticated requests. To require tokens, pair it with an AuthorizationPolicy.
What JWT algorithms does ASM support?
The supported algorithms depend on your ASM instance version:
-
Before v1.13: RSA only
-
v1.13 and later: All standard algorithms listed below
| Algorithm family | Supported algorithms |
|---|---|
| RSA | RS256, RS384, RS512 |
| RSA-PSS | PS256, PS384, PS512 |
| ECDSA | ES256, ES384, ES512 |
| HMAC | HS256, HS384, HS512 |
| Edwards-curve | EdDSA |
How do I use the jwksUri parameter?
Note: jwksUri requires ASM v1.13 or later.
The jwksUri field in a RequestAuthentication resource tells ASM where to fetch the public keys used to verify JWTs. How you configure it depends on where the JSON Web Key Set (JWKS) endpoint is hosted:
-
Inside the managed cluster -- Point
jwksUridirectly to the in-cluster service address. -
Outside the managed cluster -- Create a ServiceEntry first so that ASM can reach the external endpoint.
The examples below use the sample JWT and sample JWKS from the Istio project.
JWKS endpoint inside the managed cluster
In this example, the nginx-proxy service in the Container Service for Kubernetes (ACK) cluster serves JWKS at /get_jwks on port 80. The full jwksUri is http://nginx-proxy.{Namespace}.svc.cluster.local:80/get_jwks.
-
Verify that the JWKS endpoint is reachable:
curl nginx-proxy/get_jwksExpected output:
{ "keys":[ {"e":"AQAB","kid":"DHFbpoIUqrY8t2zpA2qXfCmr5VO5ZEr4RzHU_-e****","kty":"RSA","n":"xAE7eB6qugXyCAG3yhh7pkDkT65p****-P7KfIupjf59vsdo91bSP9C8H07pSAGQ****_xFj9VswgsCg4R6otmg5PV2He95lZdHtOcU5****_pbhLdKXbi66GlVeK6ABZOUW3WYt****-91gVuoeJT_DwtGGcp4ignkgXfkiE****-4sfb4qdt5oLbyVpmW6x9cfa7vs2WTfURiCrBoU****_-4WTiULmmHSGZHOjzwa8WtrtOQGsAFjIbno85jp6MnGGGZPYZ****_b3y5u-YpW7ypZrvD8BgtKVjgtQgZhLAGezMt0ua3DRrWnKqT****_EyxOGuHJrLsn00****"}]}If a valid JSON key set is returned, the endpoint is working.
-
Create a RequestAuthentication resource in the ASM console.
-
Log on to the ASM console.
-
In the left-side navigation pane, choose Service Mesh > Mesh Management.
-
On the Mesh Management page, find the target ASM instance. Click the instance name or click Manage in the Actions column.
-
In the left-side navigation pane, choose Mesh Security Center > RequestAuthentication.
-
On the RequestAuthentication page, click Create from YAML. Select a Namespace and a Template, paste the following YAML, and then click Create.
apiVersion: security.istio.io/v1beta1 kind: RequestAuthentication metadata: name: jwt-example namespace: foo spec: jwtRules: - issuer: testing@secure.istio.io jwksUri: 'http://nginx-proxy/get_jwks' selector: matchLabels: app: httpbin
-
-
Test the configuration by sending a request with a JWT from the
sleepPod to thehttpbinservice:# Retrieve and decode the sample JWT TOKEN=$(curl https://raw.githubusercontent.com/istio/istio/release-1.14/security/tools/jwt/samples/demo.jwt -s) && echo "$TOKEN" | cut -d '.' -f2 - | base64 --decode - # Send a request with the JWT kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" \ -c sleep -n foo -- \ curl "http://httpbin.foo:8000/headers" -sS -o /dev/null \ -H "Authorization: Bearer $TOKEN" -w "%{http_code}\n"A
200status code confirms that JWT authentication is working.
JWKS endpoint outside the managed cluster
When the JWKS endpoint is hosted outside the ACK cluster managed by ASM, create a ServiceEntry so that the mesh can reach it. This example uses HTTP. For HTTPS, add a DestinationRule as shown in the optional step.
-
Create a ServiceEntry for the external JWKS endpoint.
-
Create a file named service-entry.yaml:
apiVersion: networking.istio.io/v1beta1 kind: ServiceEntry metadata: name: external-svc-https namespace: foo spec: addresses: - 11.11.XX.XX # Replace with the IP address of your JWKS endpoint. endpoints: - address: 11.11.XX.XX # Replace with the IP address of your JWKS endpoint. hosts: - 11.11.XX.XX # Replace with the IP address of your JWKS endpoint. location: MESH_EXTERNAL ports: - name: http number: 80 protocol: HTTP - name: https number: 443 protocol: HTTPS resolution: STATIC -
Apply the ServiceEntry:
kubectl apply -f service-entry.yaml
-
-
(Optional) To fetch JWKS over HTTPS, create a DestinationRule that enables TLS:
apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: external-svc-https namespace: foo spec: host: ${The host where ServiceEntry resides} trafficPolicy: loadBalancer: simple: ROUND_ROBIN portLevelSettings: - port: number: 443 tls: mode: SIMPLE -
Create a RequestAuthentication resource.
-
Log on to the ASM console.
-
In the left-side navigation pane, choose Service Mesh > Mesh Management.
-
On the Mesh Management page, find the target ASM instance. Click the instance name or click Manage in the Actions column.
-
In the left-side navigation pane, choose Mesh Security Center > RequestAuthentication.
-
On the RequestAuthentication page, click Create from YAML. Select a Namespace and a Template, paste the following YAML, and then click Create.
apiVersion: security.istio.io/v1beta1 kind: RequestAuthentication metadata: name: jwt-example namespace: foo spec: jwtRules: - issuer: tes****@secure.istio.io jwksUri: '${Your jwksUri}' selector: matchLabels: app: httpbin
-
-
Test the configuration:
# Send a request with a JWT from the sleep Pod to httpbin kubectl exec "$(kubectl get pod -l app=sleep -n foo -o jsonpath={.items..metadata.name})" \ -c sleep -n foo -- \ curl "http://httpbin.foo:8000/headers" -sS -o /dev/null \ -H "Authorization: Bearer $TOKEN" -w "%{http_code}\n"A
200status code confirms that JWT authentication is working.
How do I skip JWT authentication for specific paths?
Combine a RequestAuthentication resource with an AuthorizationPolicy that uses action: DENY and notPaths. The RequestAuthentication validates tokens on the ingress gateway, and the AuthorizationPolicy denies unauthenticated requests to all paths except the ones you exempt.
The following example exempts /productpage from JWT authentication while requiring valid JWTs for /api/v1/products/0 and /api/v1/products/1.
-
Deploy the Bookinfo sample application and verify access.
Deploy the Bookinfo application in the ACK cluster that is added to the ASM instance. For more information, see Deploy an application in an ACK cluster that is added to an ASM instance.
Verify that all paths are accessible:
curl "http://<ingress-gateway-ip>/productpage" -sS -o /dev/null -w "%{http_code}\n" curl "http://<ingress-gateway-ip>/api/v1/products/0" -sS -o /dev/null -w "%{http_code}\n" curl "http://<ingress-gateway-ip>/api/v1/products/1" -sS -o /dev/null -w "%{http_code}\n"Each command should return
200. -
Create a RequestAuthentication resource that applies to the ingress gateway.
-
Log on to the ASM console.
-
In the left-side navigation pane, choose Service Mesh > Mesh Management.
-
On the Mesh Management page, find the target ASM instance. Click the instance name or click Manage in the Actions column.
-
In the left-side navigation pane, choose Mesh Security Center > RequestAuthentication.
-
On the RequestAuthentication page, click Create from YAML. Select a Namespace and a Template, paste the following YAML, and then click Create.
apiVersion: security.istio.io/v1beta1 kind: RequestAuthentication metadata: name: jwt-example namespace: istio-system spec: jwtRules: - issuer: testing@secure.istio.io jwks: >- { "keys":[ {"e":"AQAB","kid":"DHFbpoIUqrY8t2zpA2qXfCmr5VO5ZEr4RzHU_-e****","kty":"RSA","n":"xAE7eB6qugXyCAG3yhh7pkDkT65pHymX-P7KfIupjf59vsdo91bSP9C8H07pSAGQ****_xFj9VswgsCg4R6otmg5PV2He95lZdHtOcU5****_pbhLdKXbi66GlVeK6ABZOUW3WYtnNHD-91gVu****_DwtGGcp4ignkgXfkiEm4sw-4sfb4qdt5oLbyVpmW6x9cfa7vs2WTfURiCrBoU****_-4WTiULmmHSGZHOjzwa8WtrtOQGsAFjIbno85jp6MnGGGZPYZ****_b3y5u-YpW7ypZrvD8BgtKVjgtQgZhLAGezMt0ua3DRrWnKqT****_EyxOGuHJrLsn00****"}]} selector: matchLabels: app: istio-ingressgateway
This RequestAuthentication applies to the ingress gateway. It validates JWT signatures but does not block requests without tokens -- that is the AuthorizationPolicy's job.
-
-
Create an AuthorizationPolicy that requires JWTs on all paths except
/productpage.-
Log on to the ASM console.
-
In the left-side navigation pane, choose Service Mesh > Mesh Management.
-
On the Mesh Management page, find the target ASM instance. Click the instance name or click Manage in the Actions column.
-
In the left-side navigation pane, choose Mesh Security Center > AuthorizationPolicy.
-
On the AuthorizationPolicy page, click Create from YAML. Select a Namespace and a Template, paste the following YAML, and then click Create.
apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: test-exclude namespace: istio-system spec: action: DENY rules: - from: - source: notRequestPrincipals: - '*' to: - operation: notPaths: - /productpage selector: matchLabels: app: istio-ingressgateway
How this policy works: The DENY rule targets requests that meet both conditions: (1) the request has no valid JWT identity (
notRequestPrincipals: ['*']), and (2) the request targets any path except/productpage(notPaths: [/productpage]). As a result, unauthenticated requests to/productpagepass through, while unauthenticated requests to all other paths are denied with a403status code. -
-
Verify the configuration.
Set the sample JWT as an environment variable:
export TOKEN=eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1****.eyJleHAiOjQ2ODU5ODk3MDAsImZvbyI6ImJhciIsImlhdCI6MTUzMjM4OTcwMCwiaXNzIjoidGVzdGluZ0BzZWN1cmUuaXN0aW8uaW8iLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5p****.CfNnxWP2tcnR9q0vxyxweaF3ovQYHYZl82hAUsn21bwQd9****-LS9qd_vpdLG4Tn1A15NxfCjp5f7Q****-KC9PJqYpgGbaXhaGx7bEdFWjcwv3nZz****__ZpaCERdwU7igUmJqYGBYQ51vr2njU9ZimyKkfDe3axcyiBZde7G6dabliUosJvvKOPcKIWPccCg****_GNfwIip3-SsFdlR7BtbVUcqR-yv-XOxJ3Uc1MI0tz3uMiiZcyPV7sNCU4KRnemRIMHVOfuvH****_GhGbiSFzgPTAa9WTltbnarTbxudb_YEOx12JiwYToeX0DCPb43W1tzIBxgm8****Test requests without a JWT:
curl "http://<ingress-gateway-ip>/productpage" -sS -o /dev/null -w "%{http_code}\n" # Expected: 200 (exempted path) curl "http://<ingress-gateway-ip>/api/v1/products/0" -sS -o /dev/null -w "%{http_code}\n" # Expected: 403 (no JWT, access denied) curl "http://<ingress-gateway-ip>/api/v1/products/1" -sS -o /dev/null -w "%{http_code}\n" # Expected: 403 (no JWT, access denied)Test requests with a valid JWT:
curl "http://<ingress-gateway-ip>/productpage" -H "Authorization: Bearer $TOKEN" -sS -o /dev/null -w "%{http_code}\n" # Expected: 200 curl "http://<ingress-gateway-ip>/api/v1/products/0" -H "Authorization: Bearer $TOKEN" -sS -o /dev/null -w "%{http_code}\n" # Expected: 200 curl "http://<ingress-gateway-ip>/api/v1/products/1" -H "Authorization: Bearer $TOKEN" -sS -o /dev/null -w "%{http_code}\n" # Expected: 200Path Without JWT With valid JWT /productpage200(exempted)200/api/v1/products/0403(denied)200/api/v1/products/1403(denied)200