User Authentication with JWT
This guide provides step-by-step instructions on integrating JWT (JSON Web Token) authentication with Tetrate Service Bridge (TSB). We will illustrate this process using a sample application deployed on TSB as a practical example. This scenario will help you understand how to configure JWT authentication with TSB and ensure secure user access to applications.
Prerequisites
Before you begin, ensure you have:
- Installed the TSB management plane.
- Onboarded a cluster.
- Completed the TSB usage quickstart, including deploying the Bookinfo application and configuring the Gateway to access Bookinfo.
Step 1: Generate JWT and JWKS for Testing
First, create a JWT token and corresponding JWKS (JSON Web Key Set) for testing authentication. You can use the following commands to generate a symmetric key (HS256) JWT and JWKS.
Generate a JWT Secret Key
# Generate a base64-encoded secret key
echo -n "secret-key-1" | base64
# Output: c2VjcmV0LWtleS0x
Create a JWKS Configuration
{
"keys": [
{
"alg": "HS256",
"k": "c2VjcmV0LWtleS0x",
"kid": "issuer1-key",
"kty": "oct"
}
]
}
Generate a JWT Token
You can use the jwt.io debugger or a JWT library to create a token: Header
{"alg": "HS256", "kid": "issuer1-key", "typ": "JWT"}
Payload:
{
"iss": "issuer1.example",
"sub": "user123",
"aud": "tetrateapp",
"exp": 1767225600,
"iat": 1672531200,
"group": "developers",
"team": "backend"
}
Secret: secret-key-1 (base64-encoded: c2VjcmV0LWtleS0x)
Save the generated JWT token for testing.
Step 2: Configure JWT Authentication
You can configure JWT authentication in TSB using 2 different approaches:
Option A: Configure JWT Authentication via SecuritySetting (Mesh-wide)
apiVersion: security.tsb.tetrate.io/v2
kind: SecuritySetting
metadata:
name: jwt-auth-settings
group: bookinfo-gw
workspace: bookinfo-ws
tenant: tetrate
spec:
authenticationSettings:
http:
jwt:
issuer: issuer1.example
audiences:
- tetrateapp
jwks: '{"keys":[{"alg":"HS256","k":"c2VjcmV0LWtleS0x","kid":"issuer1-key","kty":"oct"}]}'
outputClaimToHeaders:
- header: "x-jwt-claim-group"
claim: "group"
- header: "x-jwt-claim-team"
claim: "team"
With this configuration, all requests to services in the workspace must include a valid JWT token from the specified issuer.
Option B: Configure JWT Authentication via Gateway (Per-host)
Use this approach to configure JWT authentication at the gateway level for specific hosts:
apiVersion: gateway.tsb.tetrate.io/v2
kind: Gateway
metadata:
name: bookinfo-gw-ingress
group: bookinfo-gw
workspace: bookinfo-ws
tenant: tetrate
spec:
workloadSelector:
namespace: bookinfo
labels:
app: tsb-gateway-bookinfo
http:
- name: bookinfo
port: 8443
hostname: bookinfo.tetrate.com
tls:
mode: SIMPLE
secretName: bookinfo-certs
authentication:
rules:
jwt:
- issuer: issuer1.example
audiences:
- tetrateapp
jwks: '{"keys":[{"alg":"HS256","k":"c2VjcmV0LWtleS0x","kid":"issuer1-key","kty":"oct"}]}'
outputClaimToHeaders:
- header: "x-jwt-claim-group"
claim: "group"
- header: "x-jwt-claim-team"
claim: "team"
routing:
rules:
- route:
serviceDestination:
host: 'bookinfo/productpage.bookinfo.svc.cluster.local'
Step 3: Verify JWT Authentication
-
With an invalid token: Access your application at https://bookinfo.tetrate.com.
-
With a valid token: Access your application with the JWT token:
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" https://bookinfo.tetrate.com
You should receive a successful response.
- Verify claim headers: If you configured outputClaimToHeaders, check that the headers are passed to your backend service:
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" https://bookinfo.tetrate.com -v
Look for headers like x-jwt-claim-group: developers in the backend request.
Enabling enhanced request authentication
For stricter security posture avoiding cross authentication as well as enforcing non-empty jwt token at authentication layer, you can enable the feature flag ENABLE_ENHANCED_REQUEST_AUTHENTICATION.
Per-host authentication enforcement
Below is given an example of configuring per-host authentication enforcement at the gateway level. When different hosts at gateway have tokens issued from different issuers, you can configure per-host authentication to enforce the correct issuer for each host. Without this feature flag, the default behaviour was that any valid token issued from any of the issuers configured at the gateway level would be accepted for all hosts.
apiVersion: gateway.tsb.tetrate.io/v2
kind: Gateway
metadata:
name: httpbin-gw-ingress
group: httpbin-gw
workspace: httpbin-ws
tenant: tetrate
spec:
workloadSelector:
namespace: httpbin
labels:
app: tsb-gateway-httpbin
http:
- name: httpbin
port: 8443
hostname: 'httpbin.tetrate.com'
tls:
mode: SIMPLE
secretName: httpbin-certs
authentication:
jwt:
issuer: https://keycloak.example.com/auth/realms/tetrate
audiences:
- tetrateapp
jwks_uri: https://keycloak.example.com/auth/realms/tetrate/protocol/openid-connect/certs
routing:
rules:
- route:
serviceDestination:
host: 'httpbin/httpbin.httpbin.svc.cluster.local'
port: 8000
- name: httpbin2
port: 8443
hostname: 'httpbin2.tetrate.com'
tls:
mode: SIMPLE
secretName: httpbin-certs
authentication:
jwt:
issuer: https://keycloak.example.com/auth/realms/tetrate2
audiences:
- tetrateapp
jwks_uri: https://keycloak.example.com/auth/realms/tetrate/protocol/openid-connect/certs
routing:
rules:
- route:
serviceDestination:
host: 'httpbin/httpbin.httpbin.svc.cluster.local'
port: 8000
Enforcing non-empty JWT token at authentication layer
Below is given an example of configuring non-empty JWT token enforcement at the gateway host level. When this is configured, requests without JWT token will be rejected at the authentication layer itself. Without the feature flag, requests without JWT token would be rejected at the authorization layer if there are any authorization policies configured but would be allowed if there are no authorization policies configured.
apiVersion: gateway.tsb.tetrate.io/v2
kind: Gateway
metadata:
name: httpbin-gw-ingress
group: httpbin-gw
workspace: httpbin-ws
tenant: tetrate
spec:
workloadSelector:
namespace: httpbin
labels:
app: tsb-gateway-httpbin
http:
- name: httpbin
port: 8443
hostname: 'httpbin.tetrate.com'
tls:
mode: SIMPLE
secretName: httpbin-certs
authentication:
requireJwt: true
jwt:
issuer: https://keycloak.example.com/auth/realms/tetrate
audiences:
- tetrateapp
jwks_uri: https://keycloak.example.com/auth/realms/tetrate/protocol/openid-connect/certs
routing:
rules:
- route:
serviceDestination:
host: 'httpbin/httpbin.httpbin.svc.cluster.local'
port: 8000
SecuritySetting for mesh-wide auth and per-host auth override
Below is an example of configuring mesh-wise authentication using SecuritySetting resource along with per-host authentication override at the gateway level. When both mesh-wide authentication and per-host authentication are configured, the per-host authentication configuration takes precedence for that host.
As per below configuration, host httpbin.tetrate.com will accept only tokens issued from https://keycloak.example.com/auth/realms/tetrate issuer as per the gateway configuration while other hosts at the gateway will accept tokens issued from https://keycloak.example.com/auth/realms/tetrate issuer as per the SecuritySetting configuration because no other per-host authentication is configured for them.
apiVersion: security.tsb.tetrate.io/v2
kind: SecuritySetting
metadata:
name: defaults
group: t1
workspace: w1
tenant: tis+
organization: tis+
spec:
authentication:
jwt:
issuer: https://keycloak.example.com/auth/realms/tetrate
audiences:
- tetrateapp
jwks_uri: https://keycloak.example.com/auth/realms/tetrate/protocol/openid-connect/certs
apiVersion: gateway.tsb.tetrate.io/v2
kind: Gateway
metadata:
name: httpbin-gw-ingress
group: httpbin-gw
workspace: httpbin-ws
tenant: tetrate
spec:
workloadSelector:
namespace: httpbin
labels:
app: tsb-gateway-httpbin
http:
- name: httpbin
port: 8443
hostname: 'httpbin.tetrate.com'
tls:
mode: SIMPLE
secretName: httpbin-certs
routing:
rules:
- route:
serviceDestination:
host: 'httpbin/httpbin.httpbin.svc.cluster.local'
port: 8000
- name: httpbin2
port: 8443
hostname: 'httpbin2.tetrate.com'
tls:
mode: SIMPLE
secretName: httpbin-certs
authentication:
jwt:
issuer: https://keycloak.example.com/auth/realms/tetrate2
audiences:
- tetrateapp
jwks_uri: https://keycloak.example.com/auth/realms/tetrate/protocol/openid-connect/certs
routing:
rules:
- route:
serviceDestination:
host: 'httpbin/httpbin.httpbin.svc.cluster.local'
port: 8000
When host level authn settings override, these settings are applied on both gateway port(like 443) and 15443 for east-west traffic.