Giggle IPOS widgets use a secure token-based authentication system that leverages PostMessage communication and JWT (JSON Web Tokens). This architecture ensures that widgets can access platform resources while maintaining strict security boundaries.
Implementing Authentication in Your Widget
1. Notify Portal When Ready
Your widget must signal when it's fully loaded and ready to receive authentication:
2. Listen for Authentication Token
Set up an event listener to receive the JWT token:
3. Use the Token for API Requests
Include the JWT token in all API requests to the Giggle platform:
Security Best Practices
Origin Validation
Always validate the origin of PostMessage communications:
Token Storage
Choose appropriate token storage based on security requirements:
Storage Method
Security Level
Persistence
Considerations
JavaScript variable
High
Session only
Lost on page refresh
sessionStorage
Medium
Tab session
Cleared when tab closes
localStorage
Low
Persistent
Vulnerable to XSS attacks
Secure HttpOnly Cookie
Highest
Configurable
Not accessible via JavaScript
For most widgets, sessionStorage provides a good balance of security and usability.
Permission Minimalism (Coming Soon)
Note: Granular permission controls are currently under development and will be available in an upcoming release.
In the future, you'll be able to request only the specific permissions your widget needs:
Currently, widgets receive a standard set of permissions based on the token issued by the platform. When the permission system launches, you'll be able to define and request specific access scopes for your widget.
Secure Communication
Always use HTTPS for your widget URLs and API endpoints:
Content Security Policy (CSP)
Implement a strong CSP on your widget to prevent XSS attacks:
Token Handling
Token Expiration
JWT tokens have an expiration time (typically 1 hour). When a token expires, your widget will receive 401 responses from API calls. Your widget should handle this gracefully:
Error Handling
Implement robust error handling for authentication issues:
Common Security Issues and Solutions
Issue
Prevention
Cross-site Scripting (XSS)
Sanitize user inputs, implement CSP, avoid rendering HTML from untrusted sources
Cross-site Request Forgery (CSRF)
Validate origin of PostMessage events, use anti-CSRF tokens for API calls
Information Leakage
Don't expose sensitive data in logs or DOM, minimize permission scope
Token Exposure
Never expose tokens in URLs, client-side code, or repository
Iframe Clickjacking
Set appropriate X-Frame-Options or frame-ancestors CSP directives
By following these security practices, your widget will integrate safely and securely with the Giggle IPOS platform, protecting both your users and intellectual property assets.
// Send ready event when your widget has initialized
window.parent.postMessage({ type: "WIDGET_READY" }, "*");
window.addEventListener("message", (event) => {
// Always validate the origin of incoming messages
const trustedOrigins = [
"https://app.giggle.pro",
"https://giggle.pro",
"https://app-dev.ggltest.com", //test env
"https://app.ggltest.com" //test env
];
if (!trustedOrigins.includes(event.origin)) {
console.warn("Message received from untrusted origin:", event.origin);
return;
}
// Handle access token
if (event.data && event.data.type === "access_token") {
const accessToken = event.data.access_token;
// Store the token securely (avoid localStorage for sensitive tokens)
sessionStorage.setItem("widget_token", accessToken);
// Initialize your widget with the token
initializeWidget(accessToken);
}
});
async function fetchIpData() {
const token = sessionStorage.getItem("widget_token");
if (!token) {
console.error("No authentication token available");
return;
}
try {
const response = await fetch("https://api.giggle.pro/v1/ip/metadata", {
method: "GET",
headers: {
"Authorization": `Bearer ${token}`,
"Content-Type": "application/json"
}
});
if (!response.ok) {
throw new Error(`API error: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error("Failed to fetch IP data:", error);
}
}
// Bad - No origin check
window.addEventListener("message", (event) => {
// VULNERABLE: Accepts messages from any origin
const token = event.data.access_token;
});
// Good - Strict origin validation
window.addEventListener("message", (event) => {
if (event.origin !== "https://app.giggle.pro") {
return; // Reject messages from untrusted origins
}
// Process the message safely
});
// COMING SOON: Declare permissions during widget registration
{
"permissions": [
"ip.metadata.read", // Can read basic IP information
"community.comments.read" // Can read community comments
]
}
async function handleApiResponse(response) {
if (response.status === 401) {
// Token is expired or invalid
console.log("Authentication error - user may need to reload the page");
// Display appropriate message to the user
showAuthenticationError("Your session has expired. Please refresh the page to continue.");
return null;
}
// Process valid response...
return await response.json();
}
async function makeAuthenticatedRequest(url, options = {}) {
const token = sessionStorage.getItem("widget_token");
if (!token) {
showNoAuthMessage("Please ensure you're logged in to use this feature.");
return null;
}
try {
const response = await fetch(url, {
...options,
headers: {
...options.headers,
"Authorization": `Bearer ${token}`
}
});
return handleApiResponse(response);
} catch (error) {
console.error("API request failed:", error);
showErrorMessage("Unable to communicate with the server. Please try again later.");
return null;
}
}