@spektra-cloudevents/zoho-asap-widget
v2.1.0
Published
Standalone Angular library for Zoho Desk ASAP widget with JWT token authentication and session management
Maintainers
Readme
Zoho Desk ASAP Widget - Standalone Angular Library
A completely standalone Angular library (10+) that wraps the Zoho Desk ASAP 2.0 widget. This library handles everything internally: authentication, session management, and storage clearing. Your app only needs to pass a JWT token - no Zoho-specific code required.
🎯 Key Features
- ✅ Truly Standalone: Accepts JWT token, handles authentication internally
- ✅ Zero Zoho Dependencies in App: No AsapService, no additional authentication code needed
- ✅ Multi-User Safe: Automatically detects user changes and clears sessions
- ✅ Smart Token Refresh: Distinguishes token refresh (same user) from user switch (different user)
- ✅ Automatic Session Management: Clears localStorage, sessionStorage, and cookies on logout
- ✅ Prefill Support: Automatic form prefilling with dynamic values
- ✅ Angular 10-18+ Compatible: Works with all modern Angular versions
- ✅ Production Ready: Clean code, no console logs, robust error handling
📦 Installation
npm install @cloudlabs/zoho-asap-widgetImport the module in your app:
import { ZohoAsapWidgetModule } from '@cloudlabs/zoho-asap-widget';
@NgModule({
imports: [ZohoAsapWidgetModule],
// ...
})
export class AppModule { }🚀 Basic Usage
Prerequisites: Your app must have a JWT token for authenticating users with Zoho Desk ASAP.
<!-- Simply pass your JWT token to the widget -->
<zoho-asap-widget
*ngIf="jwtToken"
[appId]="'YOUR_ZOHO_APP_ID'"
[orgId]="'YOUR_ZOHO_ORG_ID'"
[jwtToken]="jwtToken"
[enabled]="true">
</zoho-asap-widget>That's it! The widget handles:
- User authentication with Zoho
- Session management
- Storage cleanup on logout
- User switching detection
With Form Prefill
<zoho-asap-widget
*ngIf="jwtToken"
[appId]="'YOUR_ZOHO_APP_ID'"
[orgId]="'YOUR_ZOHO_ORG_ID'"
[jwtToken]="jwtToken"
[enabled]="true"
[prefillFields]="prefillData"
[departmentId]="'YOUR_DEPT_ID'"
[layoutId]="'YOUR_LAYOUT_ID'">
</zoho-asap-widget>Where prefillData is an object in your component:
prefillData: any = {
subject: 'Support Request', // Standard Zoho field
cf_event_request_id: 'MS012345678910', // Custom field
};Dynamic prefill example:
// Set subject dynamically with user name
this.prefillData.subject = `Support Request from ${this.userDisplayName}`;
// Update prefill based on user context
if (isPremiumUser) {
this.prefillData = {
subject: `Priority Support - ${userName}`,
cf_priority: 'High',
cf_user_type: 'Premium'
};
}🔧 Component Inputs
interface ZohoAsapWidgetInputs {
// Required
appId: string; // Zoho ASAP application ID
orgId: string; // Zoho organization ID
jwtToken: string; // JWT token for Zoho authentication
// Optional
enabled?: boolean; // Enable/disable widget (default: true)
nonce?: string; // Security nonce for script loading
// Prefill (optional)
prefillFields?: { // Object with field names and values
[fieldName: string]: any; // e.g., { cf_event_request_id: '12345', cf_priority: 'High' }
};
departmentId?: string; // Department ID (required for prefill)
layoutId?: string; // Form layout ID (required for prefill)
}🔐 How It Works
Architecture
┌─────────────────┐
│ Your App │
│ (JWT Token) │
└────────┬────────┘
│ JWT Token
▼
┌─────────────────┐
│ Zoho Widget │ ──► Authenticate with JWT
│ (Library) │
└────────┬────────┘
│
▼ Login with JWT
┌─────────────────┐
│ Zoho Desk │
│ ASAP API │
└─────────────────┘Flow
- App authenticates user and obtains JWT token
- App passes JWT token to widget via
[jwtToken]input - Widget handles everything:
- Logs into Zoho Desk ASAP with JWT token
- Manages session lifecycle
- On logout: Widget clears all Zoho storage/cookies automatically
🧠 Smart User Detection
The widget intelligently handles two scenarios:
Scenario 1: Same User, Token Refresh
// User's JWT token expires and gets refreshed
// Old: [email protected]
// New: [email protected]
// Widget: Extracts user identity (email/oid)
// → Same user detected
// → Updates JWT without logout
// → User keeps their session stateScenario 2: Different User Login
// User A logs out, User B logs in
// Old: [email protected]...
// New: [email protected]...
// Widget: Extracts user identity
// → Different user detected
// → Fully logs out User A
// → Clears all storage/cookies
// → Logs in User B with clean sessionThis prevents unnecessary session disruption while ensuring complete isolation between users.
## 🧹 Session Management (Automatic)
The widget handles **everything automatically** when component lifecycle changes:
```typescript
// When widget is destroyed (*ngIf becomes false):
// - Detects ngOnDestroy
// - Calls Zoho logout
// - Clears ALL Zoho storage (localStorage, sessionStorage, cookies)
// - Waits for logout confirmation event
// When widget is created fresh (*ngIf becomes true):
// - Clears any residual Zoho storage (safety check)
// - Loads Zoho script
// - Logs into Zoho with JWT token
// - Establishes fresh sessionYour app just controls the *ngIf condition - widget does the rest!
🔄 Multi-User Scenarios
Perfect for applications where users switch accounts:
// User A logged in
this.jwtToken = '[email protected]...';
// Widget: Logs in User A
// User A logs out
this.jwtToken = null;
// Widget: Detects token removal, logs out, clears all Zoho data
// User B logs in (component recreated)
this.jwtToken = '[email protected]...';
// Widget: Fresh component → clears storage → new session
// User B sees ONLY their data, never User A's📝 Form Prefilling
To prefill ticket fields when opening the widget, pass an object with field names and values:
<zoho-asap-widget
[appId]="'202588000344171472'"
[orgId]="'649984843'"
[jwtToken]="jwtToken"
[prefillFields]="{
subject: 'Technical Support Request', // Standard field
description: 'Issue details here', // Standard field
cf_event_request_id: 'EVENT-12345', // Custom field
cf_priority: 'High', // Custom field
cf_category: 'Technical Issue', // Custom field
cf_user_email: userEmail, // Custom field with dynamic value
cf_location: 'Building A' // Custom field
}"
[departmentId]="'202588000019741045'"
[layoutId]="'202588000019743298'">
</zoho-asap-widget>Field Types:
Standard Zoho Fields (no prefix needed):
subject- Ticket subject/titledescription- Ticket description/bodyemail- Contact emailphone- Contact phone
Custom Fields (require cf_ prefix):
cf_event_request_id- Your custom event ID fieldcf_priority- Your custom priority fieldcf_category- Your custom category fieldcf_*- Any other custom field you've created
Requirements:
prefillFields: Object where keys are field names (standard or custom)departmentId: Zoho department ID (required for prefill)layoutId: Zoho form layout ID (required for prefill)
How to find field API names:
- Go to Zoho Desk > Setup > Channels > ASAP
- Click on your department's form layout
- Standard fields: Use lowercase names (
subject,description,email) - Custom fields: Will have API names like
cf_event_request_id,cf_priority
Dynamic prefill with user context:
// Construct prefill data with user information
prefillData = {
subject: `Support Request from ${userName}`,
email: userEmail,
cf_event_request_id: ticketId,
cf_user_type: userType,
cf_priority: priority
};
// Update specific fields dynamically
this.prefillData.cf_event_request_id = newTicketId;
this.prefillData.subject = `Updated Request - ${newTicketId}`;
// Widget automatically reloads when prefillFields object reference changes
this.prefillData = { ...this.prefillData };The widget automatically:
- Configures prefill before loading the Zoho script
- Reapplies prefill after user login
- Reloads widget when
prefillFieldsobject changes
Important: What Your App Needs vs. Doesn't Need
✅ Your App Needs to Provide
JWT Token - For Zoho Desk ASAP authentication
- Get this from your authentication service/backend
- Pass it to the widget:
[jwtToken]="yourToken"
Zoho Configuration - Your Zoho Desk ASAP credentials
appId: From Zoho Desk ASAP setuporgId: Your Zoho organization ID
Optional: Prefill Data - Custom field values for ticket forms
prefillFields: Object with field names and valuesdepartmentId&layoutId: Required if using prefill
❌ Your App Does NOT Need
- ~~Any Zoho-specific services or logic~~
- ~~Additional authentication code (widget handles JWT authentication)~~
- ~~Session management code~~
- ~~Storage/cookie clearing logic~~
- ~~Logout/login event handlers~~
- ~~User switching detection~~
- ~~Import anything except
ZohoAsapWidgetModule~~
Summary: Just provide the JWT token and Zoho config - the widget handles all authentication and session management internally!
🏗️ Building & Publishing
# Build the library for production
ng build zoho-asap-widget --configuration production
# Navigate to dist folder
cd dist/zoho-asap-widget
# Publish to npm (one-time login: npm login)
npm publish --access public
# For updates, increment version first:
# npm version patch # 1.0.0 -> 1.0.1
# npm version minor # 1.0.0 -> 1.1.0
# npm version major # 1.0.0 -> 2.0.0🐛 Troubleshooting
Widget shows old user's data after login
- Cause: Browser cache not cleared
- Solution: Widget now clears storage on
ngOnInit()automatically - Manual fix: Clear browser cache (Ctrl+Shift+Delete → All time)
Widget not loading
- Check:
appIdandorgIdare correct - Check: JWT token is valid (not null/undefined)
- Check: Network connectivity to Zoho services
Token refresh causes logout
- Cause: Should not happen - widget detects same user
- Debug: Check console for user identity extraction logs
- Verify: JWT payload has
oid,sub, oremailclaim
🔗 Resources
📄 License
MIT
