To verify and authorize the source of HTTP requests in a service mesh, configure JSON Web Token (JWT) request authentication to implement origin authentication (end-user authentication). This configuration validates the Access Token in the request header, allowing only trusted requests to access your service. It enhances service security and simplifies inter-service identity verification.
Prerequisites
You have added a cluster to the ASM instance, and the ASM instance version is 1.6 or later.
Background information
Service Mesh supports two authentication methods:
-
Transport authentication: Uses mutual TLS (mTLS) and is commonly used for inter-service communication.
-
Origin authentication: Uses JWT and is commonly used for request authentication between clients and services.
JWT is a standard for securely transmitting claims between parties. For more information, see the JWT official documentation.
Step 1: Create a namespace and deploy sample services
-
Create a namespace named foo with the label istio-injection set to enabled. For details, see Manage global namespaces.
-
Create httpbin.yaml and sleep.yaml using the following content.
-
Connect to your cluster using kubectl and run the following commands to deploy the httpbin and sleep services in the foo namespace.
For instructions on connecting to your cluster using kubectl, see Obtain the cluster KubeConfig and connect to the cluster using kubectl.
kubectl apply -f httpbin.yaml -n foo kubectl apply -f sleep.yaml -n foo -
Access the httpbin service from the sleep service.
-
Run the following command to enter the sleep pod and start a bash shell.
kubectl exec -it deploy/sleep -- sh -
Run the following command to send a request to the httpbin service.
curl -I httpbin.foo.svc.cluster.local:8000Expected output:
HTTP/1.1 200 OK server: envoy date: Thu, 21 Dec 2023 07:39:55 GMT content-type: text/html; charset=utf-8 content-length: 9593 access-control-allow-origin: * access-control-allow-credentials: true x-envoy-upstream-service-time: 14The response
200 OKindicates a successful request.
-
Step 2: Create request authentication
-
Log on to the ASM console. In the left-side navigation pane, choose .
-
On the Mesh Management page, click the name of the ASM instance. In the left-side navigation pane, choose . On the page that appears, click Create from YAML.
-
Set the Namespaces to foo. Enter the following YAML content for request authentication in the text box, then click Create.
This YAML configures the
httpbinservice to require requests to match the rules defined injwtRules. Specifically, if the request header contains an Access Token, the decodedissclaim must betesting@secure.istio.io. Thejwksfield defines token generation details. For more information, see the JWT official documentation.apiVersion: "security.istio.io/v1beta1" kind: "RequestAuthentication" metadata: name: "jwt-example" namespace: foo spec: selector: matchLabels: app: httpbin jwtRules: - issuer: "testing@secure.istio.io" jwks: '{ "keys":[ {"e":"AQAB","kid":"DHFbpoIUqrY8t2zpA2qXfCmr5VO5ZEr4RzHU_-envvQ","kty":"RSA","n":"xAE7eB6qugXyCAG3yhh7pkDkT65pHymX-P7KfIupjf59vsdo91bSP9C8H07pSAGQO1MV_xFj9VswgsCg4R6otmg5PV2He95lZdHtOcU5DXIg_pbhLdKXbi66GlVeK6ABZOUW3WYtnNHD-91gVuoeJT_DwtGGcp4ignkgXfkiEm4sw-4sfb4qdt5oLbyVpmW6x9cfa7vs2WTfURiCrBoUqgBo_-4WTiULmmHSGZHOjzwa8WtrtOQGsAFjIbno85jp6MnGGGZPYZbDAa_b3y5u-YpW7ypZrvD8BgtKVjgtQgZhLAGezMt0ua3DRrWnKqTZ0BJ_EyxOGuHJrLsn00fnMQ"}]}' -
Parse the token.
This example uses the following token:
TOKEN='eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjQ2ODU5ODk3MDAsImZvbyI6ImJhciIsImlhdCI6MTUzMjM4OTcwMCwiaXNzIjoidGVzdGluZ0BzZWN1cmUuaXN0aW8uaW8iLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyJ9.CfNnxWP2tcnR9q0vxyxweaF3ovQYHYZl82hAUsn21bwQd9zP7c-LS9qd_vpdLG4Tn1A15NxfCjp5f7QNBUo-KC9PJqYpgGbaXhaGx7bEdFWjcwv3nZzvc7M__ZpaCERdwU7igUmJqYGBYQ51vr2njU9ZimyKkfDe3axcyiBZde7G6dabliUosJvvKOPcKIWPccCgefSj_GNfwIip3-SsFdlR7BtbVUcqR-yv-XOxJ3Uc1MI0tz3uMiiZcyPV7sNCU4KRnemRIMHVOfuvHsU60_GhGbiSFzgPTAa9WTltbnarTbxudb_YEOx12JiwYToeX0DCPb43W1tzIBxgm8NxUg'Run the following command to parse the token:
echo $TOKEN | cut -d '.' -f2 - | base64 --decode -Expected output:
{"exp":4685989700,"foo":"bar","iat":1532389700,"iss":"testing@secure.istio.io","sub":"testing@secure.istio.io"}The JWT website provides the same token parsing capability. The graphical output appears as follows.
HEADER: { "alg": "RS256", "kid": "DHFbpoIUqrY8t2zpA2qXfCmr5VO5ZEr4RzHU_-envvQ", "typ": "JWT" } PAYLOAD: { "exp": 4685989700, "foo": "bar", "iat": 1532389700, "iss": "testing@secure.istio.io", "sub": "testing@secure.istio.io" } VERIFY SIGNATURE: RSASHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), Public Key in SPKI, PKCS #1 ) -
Access the httpbin service from the sleep service.
-
Run the following command to enter the sleep pod and start a bash shell.
kubectl exec -it deploy/sleep -- sh -
Run the following command to send a request to the httpbin service with a valid Access Token in the request header.
Replace
your_valid_access_token_herewith an actual valid access token.TOKEN=your_valid_access_token_here curl -I -H "Authorization: Bearer $TOKEN" httpbin.foo.svc.cluster.local:8000Expected output:
HTTP/1.1 200 OK -
Run the following command to send a request to the httpbin service with an invalid Access Token in the request header.
Replace
your_invalid_access_token_herewith an actual invalid access token.INVALID_TOKEN=your_invalid_access_token_here curl -I -H "Authorization: Bearer $INVALID_TOKEN" httpbin.foo.svc.cluster.local:8000A response of
401 Unauthorizedmeans the request was rejected by authentication and access failed.
-
Step 3: Create a JWT authorization policy
-
Log on to the ASM console. In the left-side navigation pane, choose .
-
On the Mesh Management page, click the name of the ASM instance. In the left-side navigation pane, choose . On the page that appears, click Create from YAML.
-
Set the Namespaces to foo. Enter the following YAML content for the authorization policy in the text box, then click Create.
This YAML configures the
httpbinservice to allow requests only when the decoded token’sissvalue plus/plus thesubvalue (i.e.,source.requestPrincipals) equalstesting@secure.istio.io/testing@secure.istio.io.apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: require-jwt namespace: foo spec: selector: matchLabels: app: httpbin action: ALLOW rules: - from: - source: requestPrincipals: ["testing@secure.istio.io/testing@secure.istio.io"] -
Parse the token.
This example uses the following token:
TOKEN='eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjQ2ODU5ODk3MDAsImZvbyI6ImJhciIsImlhdCI6MTUzMjM4OTcwMCwiaXNzIjoidGVzdGluZ0BzZWN1cmUuaXN0aW8uaW8iLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyJ9.CfNnxWP2tcnR9q0vxyxweaF3ovQYHYZl82hAUsn21bwQd9zP7c-LS9qd_vpdLG4Tn1A15NxfCjp5f7QNBUo-KC9PJqYpgGbaXhaGx7bEdFWjcwv3nZzvc7M__ZpaCERdwU7igUmJqYGBYQ51vr2njU9ZimyKkfDe3axcyiBZde7G6dabliUosJvvKOPcKIWPccCgefSj_GNfwIip3-SsFdlR7BtbVUcqR-yv-XOxJ3Uc1MI0tz3uMiiZcyPV7sNCU4KRnemRIMHVOfuvHsU60_GhGbiSFzgPTAa9WTltbnarTbxudb_YEOx12JiwYToeX0DCPb43W1tzIBxgm8NxUg'Run the following command to parse the token:
echo $TOKEN | cut -d '.' -f2 - | base64 --decode -Expected output:
{"exp":4685989700,"foo":"bar","iat":1532389700,"iss":"testing@secure.istio.io","sub":"testing@secure.istio.io"} -
Access the httpbin service from the sleep service.
-
Run the following command to enter the sleep pod and start a bash shell.
kubectl exec -it deploy/sleep -- sh -
Run the following command to send a request to the httpbin service with a valid Access Token in the request header.
Replace
your_valid_access_token_herewith an actual valid access token.TOKEN=your_valid_access_token_here curl -I -H "Authorization: Bearer $TOKEN" httpbin.foo.svc.cluster.local:8000Expected output:
HTTP/1.1 200 OK -
Run the following command to send a request to the httpbin service with an invalid Access Token in the request header.
Replace
your_invalid_access_token_herewith an actual invalid access token.INVALID_TOKEN=your_invalid_access_token_here curl -I -H "Authorization: Bearer $INVALID_TOKEN" httpbin.foo.svc.cluster.local:8000A response of
403 Forbiddenmeans the request was rejected by the authorization policy and access failed.
-
Step 4: Append to the JWT authorization policy
-
Log on to the ASM console. In the left-side navigation pane, choose .
-
On the Mesh Management page, click the name of the ASM instance. In the left-side navigation pane, choose .
-
On the AuthorizationPolicy page, click the require-jwt policy's View YAML.
-
In the Edit dialog box, add the following content, then click OK.
when: - key: request.auth.claims[groups] values: ["group1"]The complete YAML example is as follows. The YAML specifies that when you request the
httpbinservice, the request permission is set toALLOWonly if, after decoding the Token in the request header, the value ofgroupsincludes group1.apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: require-jwt namespace: foo spec: selector: matchLabels: app: httpbin action: ALLOW rules: - from: - source: requestPrincipals: ["testing@secure.istio.io/testing@secure.istio.io"] when: - key: request.auth.claims[groups] values: ["group1"] -
Parse the token.
This example uses the following token:
TOKEN_GROUP='eyJhbGciOiJSUzI1NiIsImtpZCI6IkRIRmJwb0lVcXJZOHQyenBBMnFYZkNtcjVWTzVaRXI0UnpIVV8tZW52dlEiLCJ0eXAiOiJKV1QifQ.eyJleHAiOjM1MzczOTExMDQsImdyb3VwcyI6WyJncm91cDEiLCJncm91cDIiXSwiaWF0IjoxNTM3MzkxMTA0LCJpc3MiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyIsInNjb3BlIjpbInNjb3BlMSIsInNjb3BlMiJdLCJzdWIiOiJ0ZXN0aW5nQHNlY3VyZS5pc3Rpby5pbyJ9.EdJnEZSH6X8hcyEii7c8H5lnhgjB5dwo07M5oheC8Xz8mOllyg--AHCFWHybM48reunF--oGaG6IXVngCEpVF0_P5DwsUoBgpPmK1JOaKN6_pe9sh0ZwTtdgK_RP01PuI7kUdbOTlkuUi2AO-qUyOm7Art2POzo36DLQlUXv8Ad7NBOqfQaKjE9ndaPWT7aexUsBHxmgiGbz1SyLH879f7uHYPbPKlpHU6P9S-DaKnGLaEchnoKnov7ajhrEhGXAQRukhDPKUHO9L30oPIr5IJllEQfHYtt6IZvlNUGeLUcif3wpry1R5tBXRicx2sXMQ7LyuDremDbcNy_iE76Upg'Run the following command to parse the token:
echo "$TOKEN_GROUP" | cut -d '.' -f2 - | base64 --decode - | jqExpected output:
{ "exp": 3537391104, "groups": [ "group1", "group2" ], "iat": 1537391104, "iss": "testing@secure.istio.io", "scope": [ "scope1", "scope2" ], "sub": "testing@secure.istio.io" } -
Access the httpbin service from the sleep service.
-
Run the following command to enter the sleep pod and start a bash shell.
kubectl exec -it deploy/sleep -- sh -
Run the following command to send a request to the httpbin service with a valid Access Token in the request header.
Replace
your_valid_access_token_herewith an actual valid access token.TOKEN=your_valid_access_token_here curl -I -H "Authorization: Bearer $TOKEN" httpbin.foo.svc.cluster.local:8000A response of
200 OKmeans the request passed the authorization policy and access succeeded. -
Run the following command to send a request to the httpbin service with an invalid Access Token in the request header.
Replace
your_invalid_access_token_herewith an actual invalid access token.INVALID_TOKEN=your_invalid_access_token_here curl -I -H "Authorization: Bearer $INVALID_TOKEN" httpbin.foo.svc.cluster.local:8000A response of
403 Forbiddenmeans the request was rejected by the authorization policy and access failed.
-
References
To learn about JWT algorithms supported by ASM, how to use JwksUri, and how to exclude specific paths from JWT authentication, see JWT FAQ.