Skip to main content
Connect Keycloak to authenticate end users with your Char widget. Create a Keycloak client, configure the realm, and set up Char for token validation.
Keycloak is an open-source identity and access management solution. This guide applies to self-hosted Keycloak instances and managed Keycloak services.

Prerequisites

  • A running Keycloak instance (version 18+ recommended)
  • Admin access to your Keycloak realm
  • Access to the Char dashboard

SDK References

Configuration Steps

1

Access Your Keycloak Admin Console

  1. Navigate to your Keycloak Admin Console (e.g., https://keycloak.yourcompany.com/admin)
  2. Sign in with admin credentials
  3. Select your realm from the dropdown (or create a new one)
The default realm is master, but it’s recommended to create a separate realm for your applications.
2

Create a Client

  1. Navigate to Clients in the left sidebar
  2. Click Create client
  3. Configure the client:
SettingValue
Client typeOpenID Connect
Client IDchar-ai-widget (or your preferred ID)
  1. Click Next
  2. Configure capability settings:
SettingValue
Client authenticationOff (public client)
AuthorizationOff
Standard flowEnabled
Direct access grantsEnabled (optional)
  1. Click Next
  2. Configure login settings:
SettingValue
Root URLYour application’s base URL
Valid redirect URIsYour callback URLs (e.g., https://yourapp.com/*)
Web originsYour application origins (e.g., https://yourapp.com)
  1. Click Save
3

Note Your Realm and Client ID

From your Keycloak Admin Console:
  1. Realm name: Visible in the top-left dropdown
  2. Client ID: The ID you configured when creating the client
  3. Keycloak URL: Your Keycloak server URL (e.g., https://keycloak.yourcompany.com)
Keycloak Client Settings

Find your realm and client settings in Keycloak

4

Configure Char

In the Char Dashboard:
  1. Navigate to SettingsIntegration
  2. Under SSO Configuration, select Custom OIDC as the provider
  3. Enter your configuration:
FieldValue
Client IDYour Keycloak Client ID
Issuer URLhttps://{keycloak-url}/realms/{realm-name}
  1. Click Test Connection to verify
  2. Click Save Changes

Configuration Reference

Char FieldKeycloak ValueExample
Provider TypeCustom OIDCcustom_oidc
Client IDClient IDchar-ai-widget
Issuer URLRealm issuer URLhttps://keycloak.yourcompany.com/realms/production
For Keycloak versions prior to 17, the issuer URL format is different: https://{keycloak-url}/auth/realms/{realm-name}. The /auth prefix was removed in Keycloak 17+.

Token Requirements

Char validates Keycloak tokens with these requirements:
ClaimRequirement
issMust match https://{keycloak-url}/realms/{realm}
audMust include your configured Client ID
subRequired - used as the user identifier (Keycloak user UUID)
expMust not be expired
azpAuthorized party (your Client ID)

Standard Keycloak ID Token Claims

ClaimDescription
subUnique user identifier (UUID)
preferred_usernameUser’s username
emailUser’s email address
email_verifiedWhether email is verified
nameUser’s full name
given_nameFirst name
family_nameLast name
realm_access.rolesRealm-level roles
resource_accessClient-specific roles

Example: Obtaining and Passing the Token

import Keycloak from 'keycloak-js';
import "@mcp-b/embedded-agent/web-component";

const keycloak = new Keycloak({
  url: 'https://keycloak.yourcompany.com',
  realm: 'production',
  clientId: 'char-ai-widget',
});

keycloak.init({ onLoad: 'check-sso' }).then((authenticated) => {
  if (authenticated) {
    const agent =
      document.querySelector("webmcp-agent") ?? document.createElement("webmcp-agent");

    if (!agent.isConnected) {
      document.body.appendChild(agent);
    }

    agent.setAttribute("auth-token", keycloak.idToken);
  }
});

// Handle token refresh
setInterval(() => {
  keycloak.updateToken(30).then((refreshed) => {
    if (refreshed) {
      console.log('Token refreshed');
    }
  });
}, 60000);

Keycloak Roles

Keycloak roles are included in tokens automatically:
// Realm roles are in realm_access.roles
// Client roles are in resource_access.{client-id}.roles

const keycloak = new Keycloak(/* config */);

// After initialization
if (keycloak.hasRealmRole('admin')) {
  console.log('User is an admin');
}

if (keycloak.hasResourceRole('editor', 'char-ai-widget')) {
  console.log('User has editor role for this client');
}

Configuring Audience

By default, Keycloak includes the client ID in the azp (authorized party) claim but may not include it in aud. To ensure the aud claim contains your client ID:

Option 1: Use a Client Scope

  1. Navigate to Client scopesCreate client scope
  2. Name it char-ai-audience
  3. Go to MappersCreate mapper
  4. Configure:
SettingValue
Mapper typeAudience
Namechar-ai-audience
Included Client AudienceYour client ID
Add to ID tokenOn
  1. Assign the scope to your client in ClientsYour clientClient scopes

Option 2: Protocol Mapper on Client

  1. Go to ClientsYour clientClient scopes
  2. Click on your client’s dedicated scope
  3. Add a mapper of type Audience
  4. Configure to include your client ID in the audience

Troubleshooting

The issuer URL doesn’t match:
  1. Check Keycloak version: Use /auth/realms/{realm} for versions < 17, /realms/{realm} for 17+
  2. Verify realm name: Realm names are case-sensitive
  3. Check URL: Ensure no trailing slash
  4. HTTPS: Use https:// for production
The token’s audience doesn’t include your client ID:
  • Configure an Audience mapper (see “Configuring Audience” section above)
  • Verify the Client ID matches exactly
  • Ensure you’re using the ID token, not the access token
Char couldn’t reach Keycloak’s JWKS endpoint:
  • JWKS endpoint: {issuer-url}/protocol/openid-connect/certs
  • Verify Keycloak is accessible from the internet
  • Check firewall rules and load balancer configuration
  • Use Test Connection in the dashboard
If you see CORS errors:
  • Verify Web origins in client settings includes your application origin
  • Use + as a special value to allow all redirect URI origins
  • Check your reverse proxy isn’t stripping CORS headers
If token refresh fails:
  • Ensure Standard flow is enabled on the client
  • Check refresh token validity in Realm settingsTokens
  • Verify the refresh token hasn’t expired (default: 30 minutes idle)

High Availability Setup

For production Keycloak deployments:
  • Use a load balancer in front of multiple Keycloak nodes
  • Configure sticky sessions or distributed caching
  • Set up database replication for the Keycloak database
  • The issuer URL should use your load balancer’s domain
// Example with load-balanced Keycloak
const keycloak = new Keycloak({
  url: 'https://auth.yourcompany.com', // Load balancer URL
  realm: 'production',
  clientId: 'char-ai-widget',
});

Security Best Practices

  • Enable HTTPS for all Keycloak endpoints
  • Configure brute force protection in realm settings
  • Set appropriate token lifetimes (shorter for sensitive applications)
  • Use client scopes to minimize token claims
  • Enable MFA for users with elevated privileges
  • Regularly update Keycloak to patch security vulnerabilities
  • Audit login events using Keycloak’s event logging
  • Configure password policies appropriate for your security requirements