Skip to content

Authentication ​

The SDK supports multiple authentication strategies through a unified AuthenticationService. Choose the strategy that fits your security requirements.

Authentication Types ​

TypeUse CaseRequires Server
anonymousPublic access, demosNo
pre-authAPI keys, static tokens, server-provided tokensNo
pkceOAuth 2.0 browser flowNo
client-credentialsServer-to-serverYes

Anonymous Authentication (Default) ​

When no auth configuration is provided, the SDK automatically uses anonymous authentication:

typescript
// These are equivalent:
const agent = new AiAgent({
  id: "agent-id",
  endpoint: "https://your-endpoint.com"
  // No auth = anonymous session
});

const agent = new AiAgent({
  id: "agent-id",
  endpoint: "https://your-endpoint.com",
  auth: { type: "anonymous" }
});

Security Note

Anonymous authentication should only be used for public-facing agents. The agent configuration must allow anonymous access.

Pre-Auth Authentication ​

The most common authentication method. Use for API keys, static tokens, or server-provided JWTs.

To generate an access token, follow the instructions for Generating An Access Token using PKCE Flow.

Required scopes:

  • core.aiservices.read
  • knowledge.portalmgr.manage
  • core.customermgr.read (required for AI Agent for Customer Self Service only)
typescript
import { AiAgent } from "@egain/ai-agent-sdk";

const agent = new AiAgent({
  id: "agent-id",
  endpoint: "https://your-endpoint.com",
  auth: {
    type: "pre-auth",
    accessToken: "your-access-token"
  }
});

await agent.initialize();

Server-Provided Tokens ​

When your server manages authentication:

typescript
const agent = new AiAgent({
  id: "agent-id",
  endpoint: "https://your-endpoint.com",
  auth: {
    type: "pre-auth",
    accessToken: "token-from-your-server"
  }
});

With Token Refresh ​

Handle token expiration with a refresh function:

typescript
const agent = new AiAgent({
  id: "agent-id",
  endpoint: "https://your-endpoint.com",
  auth: {
    type: "pre-auth",
    accessToken: initialToken,
    refreshTokenFn: async () => {
      // Called when token is about to expire
      const response = await fetch("/api/refresh-token");
      const { token } = await response.json();
      return token;
    }
  }
});

Access token refresh window ​

Anonymous, pre-auth, and PKCE strategies all treat an access token as stale five minutes before its JWT exp (anonymous refetches the client-credentials token; PKCE refreshes via MSAL; pre-auth schedules tokenExpiring and uses refreshTokenFn when provided).

Pre-auth hosts can override the schedule with expiryBufferMs on the auth config. Integrators can reuse the same default:

typescript
import {
  ACCESS_TOKEN_REFRESH_BUFFER_MS,
  ACCESS_TOKEN_REFRESH_BUFFER_MINUTES,
} from "@egain/ai-agent-sdk";

Getting the Current Token ​

Retrieve the current access token for use in external API calls:

typescript
// Get the current access token
const token = await agent.getAccessToken();

if (token) {
  // Use the token for external API calls
  const response = await fetch('https://api.example.com/data', {
    headers: {
      Authorization: `Bearer ${token}`
    }
  });
}

Manual Token Updates ​

Update the token at runtime:

typescript
// Listen for token expiring event
agent.on("tokenExpiring", async (event) => {
  console.log("Token expiring:", event.payload.reason);
  
  // Fetch new token from your server
  const newToken = await fetchNewToken();
  
  // Update the agent's token
  await agent.updateAccessToken(newToken);
});

PKCE Authentication (OAuth 2.0) ​

For browser-based OAuth 2.0 with PKCE:

typescript
const agent = new AiAgent({
  id: "agent-id",
  endpoint: "https://your-endpoint.com",
  auth: {
    type: "pkce",
    config: {
      authorizationUrl: "https://auth.example.com/authorize",
      tokenUrl: "https://auth.example.com/token",
      clientId: "your-client-id",
      redirectUri: "https://your-app.com/callback",
      scope: "openid profile" // optional
    }
  }
});

PKCE Flow ​

  1. User initiates login
  2. SDK redirects to authorization URL with PKCE challenge
  3. User authenticates with identity provider
  4. Redirect back to your app with authorization code
  5. SDK exchanges code for tokens

CC / auto-built PKCE options (AiAgentConfig) ​

When you do not pass a full PKCEAuthConfig and the SDK builds PKCE settings from deployment info (typical contact center flows), these top-level AiAgent options apply:

OptionDescription
authScheme'popup' (default) opens a login popup; 'redirect' sends the full page to the IdP. Logout uses the same scheme.
initParams.scopesComma-separated scopes, used exactly as given: no defaults, no agent extraScopes, no platform augmentation. A host-supplied PKCEAuthConfig.scopes takes precedence over this.
agentDetails.extraScopesScopes configured on the agent (admin console → Settings → Advanced), returned by the agent details API. Only on the SDK-managed path (no host-supplied scopes): appended (deduplicated) after the defaults / platform addCustomAuthScopes list, for the anonymous client-credentials token and the PKCE config the SDK builds.

Scope resolution, first match wins:

  1. Host PKCEAuthConfig.scopes (authenticated agents) — used as-is; the config is never modified.
  2. initParams.scopes — used as-is. Also fills a host PKCEAuthConfig that has no scopes.
  3. SDK-managed: platform addCustomAuthScopes(defaults) result if the connector provides it, else the defaults for the agent's user type (knowledge.portalmgr.manage, core.aiservices.read, plus core.customermgr.read for customers); the agent's extraScopes are appended last.

The anonymous client-credentials token follows the same resolution, except that MSAL-qualified host PKCE scopes never apply to it.

PKCEAuthConfig extras ​

When you supply auth: { type: 'pkce', config: { ... } }, you can also use:

FieldDescription
localLoginWhen true, adds localLogin: 'true' to MSAL extra query parameters to force local login vs federated SSO
nextRouteRedirect-only return URL sent as OAuth state (hash stripped). Used after login and logout so auth-redirect.html can bounce back to the app. Popup omits state.

Custom client id from init params ​

Host apps can pass egclientid (and related variants supported by the SDK) inside initParams so the built PKCE config uses your Azure AD / app registration client id instead of the deployment default.

An agent can also carry its own client id (clientAppId, set in the admin console under Settings → Advanced and returned by the agent details API). The built PKCE config picks the client id in this order: initParams.egclientid → agentDetails.clientAppId → deployment intClientId (agent) / extClientId (customer) / clientId. The anonymous client-credentials token is not affected by clientAppId.

Domain hint ​

When deployment info includes a domain hint, the SDK passes it as MSAL domain_hint to steer the IdP login experience.

Logout ​

AiAgent.logout() signs the user out of the identity provider for PKCE. It takes no options — the SDK uses the same authScheme as login.

typescript
await agent.logout();
  1. Disconnects the chat WebSocket (skipGracefulDisconnect; errors ignored).
  2. Calls AuthenticationService.logout(), which delegates to the strategy when it implements logout(), then drops the cached access token.
SchemeWhat PKCE does
popuplogoutPopup. Omits OAuth state. postLogoutRedirectUri is redirectUri?logout=true so auth-redirect.html can close the popup. The promise resolves when the popup finishes.
redirectlogoutRedirect. state is hash-stripped nextRoute (else window.location.href) so auth-redirect.html can bounce back to the app. postLogoutRedirectUri is redirectUri as-is. The page navigates away; the promise does not settle.

idTokenHint is taken from the active MSAL account. end_session_endpoint is stored on authority metadata when PKCE config is built (OIDC discovery, or {authority}/oauth2/v2.0/logout when the metadata omits it). If MSAL throws, logout falls back to the access-token JWT logout claim, then that endpoint.

MSAL clears its own cache. Do not call clearCache / removeAccount before logout() — popup logout still needs the account and id token.

Anonymous, pre-auth, and client-credentials strategies have no IdP logout. AuthenticationService.logout() still clears the cached token and returns.

Host UI state (Pinia/Vuex, localStorage isAuthenticated, eGain session DELETE) is not part of AiAgent.logout(). Clear those yourself: before logout() on redirect (the page is leaving), after it returns on popup.

Client Credentials (Server-to-Server) ​

For backend services:

typescript
const agent = new AiAgent({
  id: "agent-id",
  endpoint: "https://your-endpoint.com",
  auth: {
    type: "client-credentials",
    config: {
      tokenUrl: "https://auth.example.com/token",
      clientId: "your-client-id",
      clientSecret: "your-client-secret"
    }
  }
});

Security Warning

Never expose client secrets in browser code. Use this strategy only in server-side applications.

Custom Authentication ​

Implement custom authentication by providing an AuthProvider:

typescript
import { AuthProvider, AiAgent } from "@egain/ai-agent-sdk";

class CustomAuth implements AuthProvider {
  async getToken(): Promise<string> {
    // Your custom token retrieval logic
    const response = await fetch("/api/custom-auth");
    const { token } = await response.json();
    return token;
  }
}

const agent = new AiAgent({
  id: "agent-id",
  endpoint: "https://your-endpoint.com",
  auth: new CustomAuth()
});

Full AuthStrategy Implementation ​

For complete control over the authentication lifecycle:

typescript
import { AuthStrategy } from "@egain/ai-agent-sdk";

class CustomAuthStrategy implements AuthStrategy {
  private token: string | null = null;

  async initialize(options?: { deploymentInfo?: any }): Promise<void> {
    // Setup, e.g., load cached tokens
    this.token = localStorage.getItem("auth_token");
  }

  async authenticate(): Promise<void> {
    // Perform authentication
    const response = await fetch("/api/authenticate");
    const { token } = await response.json();
    this.token = token;
  }

  async getToken(): Promise<string | null> {
    return this.token;
  }

  async cleanup(): Promise<void> {
    // Cleanup resources
    this.token = null;
  }

  // Optional on AuthStrategy. PKCE implements IdP logout via MSAL; omit if you have no IdP session.
  async logout(): Promise<void> {}
}

Best Practices ​

1. Never Hardcode Credentials ​

typescript
// ❌ Bad
auth: { type: "pre-auth", accessToken: "sk-abc123..." }

// ✅ Good
auth: { type: "pre-auth", accessToken: process.env.AI_AGENT_TOKEN }

2. Use Environment-Appropriate Strategies ​

typescript
const auth = typeof window !== "undefined"
  ? { type: "pkce", config: pkceConfig }  // Browser
  : { type: "client-credentials", config: ccConfig }; // Server

3. Handle Token Expiration ​

typescript
agent.on("tokenExpiring", async (event) => {
  try {
    const newToken = await refreshToken();
    await agent.updateAccessToken(newToken);
  } catch (error) {
    // Handle refresh failure (e.g., redirect to login)
    window.location.href = "/login";
  }
});

4. Secure Token Storage ​

typescript
// Browser: Use secure, httpOnly cookies managed by your server
// Node.js: Use environment variables or secret managers

API Reference ​

Released under the MIT License.