CBTC Authentication
👥 Audience: App Developers and Infrastructure Integrators setting up authentication for Canton Ledger API access.
⚠️ API Disclaimer: CBTC APIs are subject to change. Authentication flows may evolve as Canton's identity layer matures.
Overview: How Authentication Works for CBTC on Canton
All CBTC operations go through the Canton Ledger API, which requires a valid JWT (JSON Web Token) for every request. The JWT is issued by an OIDC (OpenID Connect) provider connected to your Canton participant node.
This guide covers two authentication options for developers building with CBTC and the Canton Network:
Keycloak (officially supported by BitSafe)
Auth0 (community example, not officially maintained) For deeper background on how Canton handles authentication and authorization at the platform level, see the Canton Authorization Documentation.
CBTC Authentication Flow: JWT and OIDC
Set Up Keycloak for CBTC Authentication (Officially Supported) ✅
Keycloak is the officially supported OIDC provider for CBTC integrations. BitSafe engineering provides support for Keycloak-based authentication.
Prerequisites
Keycloak instance running and accessible
A realm configured for your Canton participant
A client application registered in Keycloak
Step 1: Register a Client
In your Keycloak admin console:
Navigate to your realm → Clients → Create client
Set Client type to
OpenID ConnectSet Client ID (e.g.,
cbtc-minting-app)Enable Client authentication (for server-to-server flows)
Under Service account roles, enable as needed
Step 2: Configure Your Canton Participant
Your Canton participant must be configured to trust your OIDC provider. Participant configuration is complex and environment-specific. Refer to the official validator operator documentation:
Canton Validator Operator Guide →
Step 3: Obtain a Token
Client Credentials flow (for server-to-server / backend integrations):
Password grant flow (for user-facing / interactive applications):
Response (both flows):
Step 4: Use the Token
Include the token in all Canton Ledger API calls:
Token Refresh
Tokens expire (typically 5 minutes for Keycloak). Your application should:
Cache the token until near expiry
Request a new token before the current one expires
Retry failed requests with a fresh token if you receive a
401
Set Up Auth0 for CBTC Authentication (Community Example) ⚠️
💡 Auth0 compatibility. Both Keycloak and Auth0 follow the OAuth2/OIDC standard, so the login flow and token usage are identical. There is one known caveat: Auth0 requires an extra
audienceparameter in the token request. Thecbtc-libandcanton-liblibraries do not pass this parameter by default, so they won't work out of the box with Auth0. This is a straightforward fix on either the library side or the client side. See the workaround below. BitSafe engineering support covers Keycloak-based authentication only. For Auth0-specific configuration issues, refer to Auth0's documentation.
Prerequisites
Auth0 tenant and API configured
Application registered as Machine to Machine (for backend) or Single Page Application (for frontend)
Step 1: Create an Auth0 API
In the Auth0 dashboard:
Navigate to Applications → APIs → Create API
Set Name (e.g.,
Canton Ledger API)Set Identifier to your participant's Ledger API URL
Set Signing Algorithm to
RS256
Step 2: Register a Machine-to-Machine Application
Navigate to Applications → Create Application
Select Machine to Machine Applications
Authorise the application to call your Canton Ledger API
Note the Client ID and Client Secret
Step 3: Configure Your Canton Participant
Point your participant to Auth0's JWKS endpoint. Participant configuration is complex and environment-specific. Refer to the official validator operator documentation:
Canton Validator Operator Guide →
Step 4: Obtain a Token
⚠️ The
audienceparameter is required for Auth0. This is the key difference from Keycloak. Without it, Auth0 will return an opaque token that the Canton participant will reject. Setaudienceto your participant's Ledger API base URL. If using cbtc-lib / canton-lib: The Rust libraries'keycloak::login::passwordandkeycloak::login::client_credentialsfunctions do not pass anaudienceparameter. To use Auth0, you'll need to either:
Make the token request directly via HTTP (as shown above) instead of using the library helper
Patch the login functions to include the
audiencefield, which is a small change A library-level fix may be shipped in a future release ofcanton-lib.
Step 5: Use the Token
Same as Keycloak. Include the Bearer token in all API requests.
Wallet-Based Authentication for Canton dApps
For applications that use Canton-compatible wallets (Loop, Console/Zoro, Bron), authentication is handled by the wallet provider. Your application receives a JWT through the wallet's SDK or connect flow.
Supported wallets:
Loop Wallet
Console / Zoro Wallet
Bron Wallet
WalletConnect (for dApp integrations)
Node login (direct participant authentication) See the Integration Guides for wallet-specific connection patterns.
Troubleshooting
401 Unauthorized on every request
JWT not trusted by participant
Verify JWKS URL in participant config matches your OIDC provider
Token expires immediately
Clock skew between OIDC provider and participant
Sync system clocks (NTP)
CORS errors in browser
Ingress not configured for CORS
Add CORS annotations to your ingress — see Minting App Installation Guide
invalid_grant from OIDC provider
Client secret rotated or incorrect
Regenerate and update client secret
JWT Security Best Practices for Canton Applications
Never expose client secrets in frontend code. Use the Client Credentials flow only from backend services.
Rotate secrets regularly. Update client secrets in both your OIDC provider and your application config.
Use short-lived tokens. The default 5-minute expiry is appropriate for most use cases.
Restrict party access. Configure your JWT claims to limit which Canton parties a token can act as.
Last updated