gRPC JWT Authentication
The gateway validates signed JWTs on inbound gRPC requests from Webex Contact Center. This protects the BYOVA data plane and is separate from the Webex OAuth login used by the optional monitoring dashboard.
For dashboard authentication, see Authentication Quick Start and the Monitoring Interface documentation.
What the Gateway Validates
When validation is enabled, the gateway:
- Reads a token from the gRPC
authorizationmetadata entry. - Accepts
Bearer <JWT_TOKEN>and raw-token formats. - Allows only the Webex identity-broker issuers listed in
src/auth/jwt_validator.pybefore fetching signing keys. - Verifies the RS256 signature and expiration.
- Requires nonempty
aud,sub, andjticlaims. - Requires the datasource URL and schema claims to match the configured values.
- Caches identity-broker public keys for the configured duration.
With enforcement enabled, missing or invalid credentials are rejected before the RPC reaches the gateway service.
Configuration
Configure jwt_validation in config/config.yaml:
jwt_validation:
enabled: true
enforce_validation: true
datasource_url: "https://your-gateway.example.com:443"
datasource_schema_uuid: "5397013b-7920-4ffc-807c-e8a3e0a18f43"
cache_duration_minutes: 60
The gateway fails to start when validation is enabled and datasource_url is empty.
Datasource URL
datasource_url must exactly match the URL registered through the
Webex Data Sources API.
The runtime token contains that URL as a claim, and the validator performs a
character-for-character comparison.
These values are different:
https://gateway.example.com
https://gateway.example.com:443
Copy the registered value rather than reconstructing it. Use the same URL when a temporary development endpoint changes.
Automatic Registration and JWT Claim Alignment
The optional data_source lifecycle can discover or register the datasource before the
gRPC listener starts and renew its JWS before expiry. Leave its URL and schema empty to
inherit the JWT values:
jwt_validation:
enabled: true
enforce_validation: true
datasource_url: "https://your-gateway.example.com:443"
datasource_schema_uuid: "5397013b-7920-4ffc-807c-e8a3e0a18f43"
data_source:
enabled: true
fail_startup_on_error: true
url: ""
schema_id: ""
auth:
type: "oauth_refresh"
client_id_env: "WEBEX_BYODS_CLIENT_ID"
client_secret_env: "WEBEX_BYODS_CLIENT_SECRET"
refresh_token_env: "WEBEX_BYODS_REFRESH_TOKEN"
Set the named environment variables from an authorized Service App. With empty lifecycle URL and schema values, registration and validation share one source of truth. If both sections explicitly configure either value, startup rejects a mismatch.
The datasource token managed by this lifecycle is separate from each inbound request JWT: the lifecycle creates and renews the registration’s JWS, while the interceptor validates the signed JWT Webex sends with a gRPC request.
Datasource Schema UUID
The standard Voice Virtual Agent schema UUID used by this sample is:
5397013b-7920-4ffc-807c-e8a3e0a18f43
It corresponds to the Voice Virtual Agent schema in the Webex dataSourceSchemas repository. Change it only when intentionally targeting a different approved schema.
Supported Issuers
The current implementation accepts:
https://idbrokerbts.webex.com/idbhttps://idbrokerbts-eu.webex.com/idbhttps://idbroker.webex.com/idbhttps://idbroker-eu.webex.com/idbhttps://idbroker-b-us.webex.com/idbhttps://idbroker-ca.webex.com/idb
JWTValidator.VALID_ISSUERS in src/auth/jwt_validator.py is the source of truth for the
running code. Treat issuer additions as security-sensitive code changes.
Deployment Modes
Local-Only Development
For a local test that cannot receive a Webex token:
jwt_validation:
enabled: false
Do not expose that configuration to Webex or use it in production.
Validation Observation
For a controlled nonproduction rollout, validation can run without rejecting invalid tokens:
jwt_validation:
enabled: true
enforce_validation: false
datasource_url: "https://your-test-gateway.example.com:443"
This mode logs validation failures but permits the request. Protect access to the logs, and use this mode only for a time-bounded validation exercise.
Production
jwt_validation:
enabled: true
enforce_validation: true
datasource_url: "https://your-production-gateway.example.com:443"
datasource_schema_uuid: "5397013b-7920-4ffc-807c-e8a3e0a18f43"
cache_duration_minutes: 60
Production deployments should also enforce TLS, restrict network paths, monitor validation failures, and alert on identity-key refresh failures. See Security Configuration and Production Readiness.
Troubleshooting
Gateway Fails to Start
If validation is enabled, configure a nonempty datasource URL. The value must be the actual registered endpoint, not a placeholder.
Missing JWT Token
- Confirm that the data source is registered and active.
- Confirm that the request reaches the gateway through the expected Webex path.
- Check for an
authorizationmetadata value. - Verify that a proxy or load balancer preserves gRPC metadata.
Invalid Signature or Public-Key Fetch Failure
- Confirm outbound HTTPS access to the relevant Webex identity broker.
- Confirm system time is synchronized.
- Check the issuer and key-refresh logs.
- Do not add an issuer simply to bypass a validation failure.
Invalid Issuer
Compare the token issuer with JWTValidator.VALID_ISSUERS. The validator checks the issuer
before making a key request to prevent arbitrary key-fetch URLs.
Datasource Claims Validation Failed
- Copy the exact registered datasource URL into the configuration, or enable automatic lifecycle management so registration inherits the JWT URL and schema.
- Check whether the registered URL includes
:443or a trailing path. - Confirm the token schema UUID matches the configured Voice Virtual Agent schema.
Expired Token
Confirm system clock synchronization. If Webex continues to send expired tokens, preserve a tracking ID and timestamp and escalate through the appropriate Webex support channel.