ZTF Set Up and Integration¶
This appendix outlines the technical details for integrating VIA's Zero Trust Fabric (ZTF) with existing applications. It highlights the use of Keycloak for authenticating users and WalletConnect for facilitating blockchain-based transactions. It offers practical guidance and configurations necessary for developers and administrators to successfully implement and deploy ZTF components within their enterprise environments.
Setup and Configuration of Keycloak into Your Application Using Helm Charts¶
This section explains how to set up and configure the ZTF Keycloak integration for an application using Helm charts. It details the necessary files and clarifies how these changes enable authentication.
These instructions are tailored for integrating with VIA's Keycloak ZTF, which has a specific realm and authentication flow that are not supported by standard Keycloak out of the box. This guide is intended for a fresh installation of ZTF and does not cover the process of importing existing users.
1. How Helm Chart Changes Enable Keycloak Integration¶
What’s Happening Behind the Scenes¶
When you configure the following variables in your Helm chart:
keycloak.urlkeycloak.realmkeycloak.clientId
Your Helm templates inject these values as environment variables or configuration entries into the Kubernetes manifests for your application. Here’s why this works:
- Dynamic Configuration: Helm uses template expressions (e.g.,
{{ .Values.keycloak.url }}) that get replaced with values from your values.yaml or command-line overrides during deployment. This means you can swap authentication providers or credentials without changing your application code—just update your chart values. - Standard OIDC/OAuth2 Integration: Most modern applications use OpenID Connect (OIDC) or OAuth2 for authentication. These protocols require your app to know:
- Where to send authentication requests (
KEYCLOAK_URL, usually something likehttps://<keycloak-host>/auth) - Which realm (user domain) to target (
KEYCLOAK_REALM) - Which client ID to identify itself to Keycloak
(KEYCLOAK_CLIENT_ID) - Environment Variables: Applications typically read these settings from environment variables or config files injected at runtime. By setting these via the deployment manifest, your app is configured to communicate with Keycloak as an identity provider.
In summary: These Helm chart changes "wire up" your app to Keycloak at runtime, so authentication requests and token verifications are correctly routed and secured.
2. Relevant Files and Their Roles¶
a. deployment.yaml¶
This template injects the Keycloak config as environment variables into your application pods.
Example snippet:
Why this matters: When your app starts, it reads these environment variables to know how to talk to Keycloak for authentication.
b. values.yaml¶
Holds the default or environment-specific Keycloak settings:
Why this matters: This enables flexible, environment-specific configuration—update these values to point to any Keycloak-compatible provider, including ZTF.
3. Application Flow After Integration¶
- Startup: App reads Keycloak variables from its environment.
- User Authentication: When a user tries to log in, the app redirects them to Keycloak using the configured URL, realm, and client ID.
- Token Verification: App validates tokens with Keycloak using the provided settings.
- Switching Providers: To point to ZTF or another Keycloak instance, just update the values (no code changes required).
4. Switching to ZTF Authentication¶
To switch to ZTF, update these values (in values.yaml or via helm upgrade --set ...):
- Keycloak Client ID
- Keycloak Realm
- Keycloak URL
Your application will now use ZTF’s Keycloak instance for authentication.
5. Summary¶
- Helm charts inject Keycloak configuration into your app at deploy-time.
- These variables tell your app where and how to authenticate.
- This method separates configuration from code, improving flexibility and security.
Switching to ZTF or other Keycloak-compatible providers is as simple as updating Helm values.
WalletConnectService Usage & Session Recovery Guide¶
For applications that use blockchain Web3 actions, ZTF allows for wallet-to-dApp communication through WalletConnect. The WalletConnectService is an Angular injectable service that simplifies the management of WalletConnect sessions, handling the full session lifecycle from initialization and connection to state monitoring and recovery.
Core Concepts¶
- Session is the persistent connection state between the DApp and the wallet.
- Pairing is the handshake process that connects a DApp to a wallet.
- Session Recovery ensures that a user can seamlessly restore a previous, valid session after reloading the app or returning later.
Key Methods¶
1. Initialization¶
Purpose:
- Initialize WalletConnect, possibly with previously stored session data.
How it works:
- Clears any existing session data.
- Stores new WalletConnect session info if provided.
- Calls
initializeSignClient()to set up the client and restore pairing/session if possible.
Example:
2. Sign Client Initialization & Event Binding¶
Method:
Purpose:
- Instantiates the WalletConnect client.
- Binds to session/pairing events for real-time updates.
- Handles retries and resets on errors.
How it works:
- Calls
init()to start the client with app-specific metadata. - Binds event handlers for session requests, updates, deletions, etc.
- On error, attempts to reset and reinitialize the client.
- Calls
checkState()to restore session or pairing if available.
3. Session Recovery¶
Method:
Purpose: Restores previous pairing or session if possible; otherwise, starts a new connection.
How it works:
- Gets the last known pairing and session from the sign client’s storage.
- If pairing/session found and not expired, attempts to ping the wallet.
- If session expired or not available, sets state to inactive and triggers a new connection if needed.
Example:
4. Connecting to a Wallet¶
Method:
Purpose: Initiates a new wallet connection or reconnects if required.
Example:
5. Sending Requests/Transactions¶
Method: sendTransaction(request, vscTransaction, apiCall, action)
Purpose: Sends a transaction/request to the wallet via WalletConnect.
Example:
6. Disconnecting¶
Method:
Example:
Detailed Session Recovery Flow¶
- App Initialization
- Call
initialize()at app startup with optional stored session info. - Sign Client Setup
initializeSignClient()sets up the client, event handlers, and attempts to restore session/pairing.- Session/Pairing Check
checkState()inspects persisted pairing/session from storage.- If session exists and is not expired, it pings the wallet to verify connection.
- If session is invalid/expired, triggers reconnection flow.
- Event Handling
- The service listens for WalletConnect events (session request, update, etc.) and updates state accordingly.
- Recovery on Error
- On error (e.g., storage corruption, expired session),
resetConnection()is called to clear state and storage, then the workflow can start anew.
Example: Angular Integration¶
Best Practices for Other Apps¶
- Always call initialize() on app startup to recover sessions if available.
- Subscribe to state and error observables to react to connection changes.
- Handle errors gracefully; if session recovery fails, prompt the user to reconnect.
- Use provided observables for reactive UI updates (e.g., wallet address, connection state).
- Bind to WalletConnect events to handle approvals, rejections, and requests in real-time.
Summary Table: Session Management Methods¶
| Method | Purpose | Typical Usage |
|---|---|---|
| initialize() | Startup/init, session recovery | On app/component init |
| connect(renew?: boolean) | Start (new) connection with wallet | User clicks “Connect Wallet” |
| sendTransaction(...) | Send signed request/transaction | User initiates blockchain action |
| disconnect() | Disconnect and clear session | User clicks “Disconnect” |
| resetConnection() | Internal: force-clears state and storage | On error/expired session |
| state$, walletAddress | Observables for UI binding | Template/UI status display |
Use this service as a reference template for managing WalletConnect sessions in any Angular application. Adjust the injected dependencies, event handling, and request structure as needed to fit your app’s requirements.
Secure User Logout from App, Keycloak, and WalletConnect¶
When building applications that use ZTF and integrate wallets (e.g., WalletConnect), a secure logout must do the following:
- End the app session by clearing local state and tokens.
- Disconnect any wallet sessions, such as those from WalletConnect.
- Log out from the identity provider (Keycloak), which terminates the global browser session.
- Redirect the user to a safe post-logout location.
This pattern is adaptable for any frontend, backend, or gateway framework.
Why Is a Complete Logout Important?¶
Logging out of your application alone isn't enough because the user's session with the identity provider will remain unless it's explicitly closed. This can allow logins to persist.
A proper logout process should do the following:
- End the local application session by clearing tokens or cookies.
- Disconnect any wallet sessions.
- Redirect the user to the logout endpoint of the IdPprovider (like Keycloak or another OpenID Connect provider) to end the IdP session.
Generalized Flow¶
When a user logs out, the following generalized flow should occur:
- User Action: The user clicks "Logout."
- Confirmation: A confirmation dialog appears. If confirmed by the user, the logout process continues.
- Local Cleanup: The wallet session is disconnected, and any local data, caches, or cookies are cleared.
- Redirect to Logout Endpoint: The user is redirected to the
/logoutendpoint of the application's backend or gateway. - Backend/Gateway Process: The
/logoutendpoint extracts the ID token (if available) and redirects the user to Keycloak's logout endpoint withid_token_hintandpost_logout_redirect_uriparameters in theredirect. - Global Logout: Keycloak processes the logout request, ending the global session.
- Final Redirect: The user is redirected back to the application after the global logout is complete.
Security and UX Tips¶
- Always clear wallet and application sessions before a logout.
- Use HTTPS for all flows.
- Use confirmation dialogs to prevent accidental logouts.
- Only allow safe domains in
post_logout_redirect_urito prevent open redirect attacks. - Store tokens in
HttpOnlysecure cookies where possible. - Always test the logout flow to ensure both the application and sessions terminate correctly.
Example (Abstracted Pseudocode)¶
Backend or Gateway /logout:
- Extract ID token from cookie/session
- Redirect to:
Adapting to Other Frameworks¶
This logout pattern can be applied to any web application, regardless of the framework being used (e.g., React, Vue, or Angular). The specific code for disconnecting the wallet will vary depending on the particular integration. The /logout endpoint can be implemented in a backend, such as with Node.js, Python, or Java, or within a gateway or proxy.
For Single-Page Applications (SPAs), it is best to manage the logout process through a backend or gateway for enhanced security. This same pattern works with other OpenID Connect (OIDC) providers like Auth0, Okta, and Azure AD. However, the logout endpoint and its parameters will need to be updated to align with their specific documentation.
Summary Checklist¶
- Add a logout button with confirmation.
- Disconnect the WalletConnect, or an equivalent, session.
- Clear the application session and local state.
- Redirect to the
/logoutbackend or gateway route. - The backend or gateway redirects to Keycloak with the appropriate parameters.
- The user is redirected back to the application after a global logout.