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
| Permission | Purpose |
|---|---|
allow-scripts | Enable JavaScript execution |
allow-popups | Required for OAuth authentication popups |
allow-forms | Allow form submissions |
allow-popups-to-escape-sandbox | Allow 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
| Code | Description |
|---|---|
TIMEOUT | API request exceeded timeout |
NO_ACTIVE_INTERACTION | No interaction available |
INVALID_PARAMS | Invalid method parameters |
UNAUTHORIZED | Authentication required |
NOT_FOUND | Resource not found |
POPUP_BLOCKED | OAuth 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
Updated 11 days ago
