Authentication & Security

Overview

Infinity Elements inherit authentication from the parent Infinity Desktop session and run in sandboxed iframes for security isolation. You access authenticated agent context through the Element API without additional login, and can retrieve JWT tokens for external API calls.

Authentication

Session Inheritance

Infinity Elements automatically inherit authentication from the parent Infinity Desktop session. No additional login required for framework APIs.

const api = new ElementAPI();

// Get authenticated user information
const userInfo = await api.getUserInfo();
console.log('Agent:', userInfo.displayName);

Session Inheritance

When your Element loads in the Infinity Agent Desktop, it automatically has access to the authenticated agent's session—no separate login required.

const api = new ElementAPI();

// Access authenticated user information
const userInfo = await api.getUserInfo();
console.log('Agent:', userInfo.displayName);
console.log('User ID:', userInfo.userId);
console.log('Email:', userInfo.email);
console.log('Queues:', userInfo.queues);

All Element API methods use this inherited session to access framework data and functionality.


JWT Tokens for External APIs

When your Element needs to call external systems or Avaya APIs outside the Element API, retrieve a JWT token:

// Get JWT token
const jwt = await api.getAvayaJwt({
  redirectUri: 'https://your-app.com/callback'
});

// Use for authenticated external requests
const response = await fetch('https://api.example.com/data', {
  headers: {
    Authorization: `Bearer ${jwt}`
  }
});

Token Management Features

Automatic Caching

  • Tokens cached in localStorage for instant retrieval
  • Auto-refresh when expired using refresh tokens
  • No repeated OAuth flows for same session

Cross-Iframe Coordination

  • Multiple Elements requesting tokens simultaneously → only ONE OAuth popup
  • All Elements receive the same token
  • Request deduplication prevents redundant authentication flows

Security

  • PKCE (Proof Key for Code Exchange) flow prevents authorization code interception
  • No client secret required (public client)
  • Origin validation on all token operations
  • Cross-iframe coordination with single OAuth popup
  • Token caching in localStorage
  • PKCE flow for enhanced security
  • Origin validation on all messages

Configuration Options

const jwt = await api.getAvayaJwt({
  authorizationEndpoint: 'https://keycloak.example.com/auth',
  tokenEndpoint: 'https://keycloak.example.com/token',
  clientId: 'my-client-id',
  redirectUri: 'https://myapp.com/callback',
  scopes: ['openid', 'profile', 'email'],
  forceRefresh: false  // Set true to force new token
});

Manual Token Refresh

try {
  const newJwt = await api.refreshToken({
    tokenEndpoint: 'https://keycloak.example.com/token',
    clientId: 'my-client-id',
    redirectUri: 'https://myapp.com/callback'
  });
} catch (error) {
  console.error('Token refresh failed:', error);
  // Re-authenticate if refresh token expired
}

Clear Cached Token

// Force re-authentication on next getAvayaJwt call
api.clearAvayaJwt();


Security Architecture

InfinityElements execute within sandboxed iframes to ensure system stability and security isolation from the host application.

Iframe Sandboxing

InfinityElements operate with carefully scoped permissions::

<iframe 
  sandbox="allow-scripts allow-popups allow-forms allow-popups-to-escape-sandbox"
  src="element.js">
</iframe>

Granted Permissions

PermissionPurpose
allow-scriptsEnable JavaScript execution
allow-popupsRequired for OAuth authentication popups
allow-formsAllow form submissions
allow-popups-to-escape-sandboxAllow OAuth popup navigation to external domains

Security Restrictions

  • ❌ No access to parent window's DOM or JavaScript context
  • ❌ Cannot navigate or redirect parent window
  • ❌ No access to cookies from the parent domain
  • ❌ Cannot execute arbitrary code in the host application context
  • ❌ Isolated localStorage and sessionStorage (scoped to iframe origin)
  • ❌ Cannot access other Elements' contexts
  • ✅ Communication only via postMessage API

This isolation ensures your Element cannot interfere with the Agent Desktop or other Elements, even if compromised.

Example: Security Boundary Enforcement

These operations are BLOCKED in sandboxed InfinityElements:

// ❌ BLOCKED: Cannot access parent location
try {
  const parentUrl = window.parent.location.href;
} catch (e) {
  // SecurityError: Blocked by cross-origin policy
}

// ✅ ALLOWED: Use Component API for authorized communications
const api = new ComponentAPI();
const userInfo = await api.getUserInfo(); // Authorized access

API Communication Security

All communication between your Element and the Agent Desktop uses secure postMessage:

Message Validation

// Framework validates every message
- Origin validation (messages only accepted from trusted origins)
- Request/response correlation via unique request IDs
- Structured message format with type checking
- Timeout handling (default: 5000ms, configurable)

Request Pattern

// Your code
const userInfo = await api.getUserInfo();

// What happens under the hood:
// 1. Generate unique request ID
// 2. Send postMessage to parent window
// 3. Parent validates origin and request
// 4. Parent processes request
// 5. Parent sends response via postMessage
// 6. Element API validates response and resolves Promise

Error Handling

The Element API provides structured error handling with detailed error codes:

try {
  await api.setAgentStatus(userId, 'Available');
} catch (error) {
  console.error('Error code:', error.code);
  console.error('Error message:', error.message);
  console.error('Details:', error.details);
}

Global Error Handler

Subscribe to all API errors:

api.onError((error) => {
  console.error('API Error:', error.code, error.message);
  // Log to monitoring service, display user notification, etc.
});

Common Error Codes

CodeDescription
TIMEOUTAPI request exceeded timeout
NO_ACTIVE_INTERACTIONNo interaction available
INVALID_PARAMSInvalid method parameters
UNAUTHORIZEDAuthentication required
NOT_FOUNDResource not found
POPUP_BLOCKEDOAuth popup was blocked

Try-Catch Pattern

try {  
const interaction = await api.getInteraction();  
console.log('Interaction ID:', interaction.interactionId);  
} catch (error) {  
if (error.message.includes('No active interaction')) {  
// Expected when agent has no current interaction  
console.log('Waiting for interaction...');  
} else {  
// Unexpected error  
console.error('Failed to get interaction:', error);  
}  
}  

Timeout Configuration

const api = new ComponentAPI({ componentId: 'my-component', timeout: 10000, // 10 seconds (default is 5000ms) debug: true // Enable debug logging}); 

Cleanup on Unmount

Always clean up subscriptions and resources:

useEffect(() => {  
const unsubscribe = api.onInteractionAccepted((id) => {  
// Handle event  
});

return () => {  
unsubscribe();  
api.destroy(); // Clean up all resources  
};  
}, \[]);

Best Practices

Authentication

Do:

  • Use getUserInfo() for agent context instead of storing credentials
  • Cache JWT tokens and reuse them across API calls
  • Handle token refresh failures gracefully
  • Clear tokens on logout or session end

Don't:

  • Store passwords or credentials in your Element
  • Make synchronous authentication calls
  • Ignore token expiration times
  • Share tokens between different Elements (framework handles this)

Security

Do:

  • Validate all user input before sending to external APIs
  • Use HTTPS for all external API calls
  • Implement proper error handling for failed requests
  • Use Content Security Policy (CSP) in your Element

Don't:

  • Expose JWT tokens in logs or error messages
  • Store sensitive data in localStorage without encryption
  • Trust data from external sources without validation
  • Bypass the Element API to access parent window

Resources

SDK Authentication README