Embedded Communication
Besides the REST API available for the Standalone Apps, Embedded apps have additional way of communication with the MeWe host application using the postMessage API.
This enables secure, cross-origin communication which simplifies the authentication and provides additional functionalities for the developers in order to achieve better UX.
Overview
When your app is embedded within MeWe, it runs in an iframe and needs to communicate with the parent MeWe application. This communication is handled through the browser's postMessage API, which allows secure messaging between different origins.
Besides the AUTH types of messages which have a unique purpose, other messages follow a naming convention that indicates the direction of communication:
CLIENTprefix — Messages sent by your embedded app (the client)HOSTprefix — Messages sent by the MeWe application (the host)
CLIENT_*HOST_*postMessageThe embedded communication protocol supports various message types for different purposes:
Authentication Messages
CLIENT_HANDSHAKE_REQUEST— Sent by your embedded app to initiate authenticationHOST_HANDSHAKE_RESPONSE— Sent by MeWe in response, containing the authentication token
Display Management Messages
CLIENT_DISPLAY_REQUEST— Request display information from MeWeHOST_DISPLAY_RESPONSE— Receive display information including dimensions and stateCLIENT_DISPLAY_UPDATE— Request to update the app's display dimensions
Lifecycle Messages
HOST_APP_PAUSED— Notifies your app that it has been pausedHOST_APP_RESUMED— Notifies your app that it has been resumedHOST_APP_CLOSED— Notifies your app that it has been closedHOST_APP_MINIMIZED— Notifies your app that it has been minimizedHOST_APP_MAXIMIZED— Notifies your app that it has been maximized
CLIENT_HANDSHAKE_REQUEST
The CLIENT_HANDSHAKE_REQUEST message is sent by your embedded app to request loginRequestToken from the MeWe host application.
When to Send
Send this message during your app's initialization, typically when:
- Your app detects it's running inside MeWe (e.g., via URL parameters)
- You need to obtain a
loginRequestTokenfor authentication - Your app first loads or when authentication is required
Message Format
window.parent.postMessage({ type: 'CLIENT_HANDSHAKE_REQUEST' }, '*');
Message Properties
stringMust be exactly "CLIENT_HANDSHAKE_REQUEST". This identifies the message type to the MeWe host application.
Example Implementation
// Send the handshake request
function requestAuthentication() {
window.parent.postMessage({ type: 'CLIENT_HANDSHAKE_REQUEST' }, '*');
}
// Call during app initialization
requestAuthentication();
The origin parameter ('*') allows the message to be received by any origin. In production, you may want to restrict this to MeWe's specific origin for additional security.
HOST_HANDSHAKE_RESPONSE
The HOST_HANDSHAKE_RESPONSE message is sent by MeWe in response to your CLIENT_HANDSHAKE_REQUEST request. It contains the loginRequestToken needed to authenticate your app.
When You Receive It
You'll receive this message after sending CLIENT_HANDSHAKE_REQUEST. MeWe will respond with the authentication token once the user has approved your app's permissions (which happens before the app launches for embedded apps).
Message Format
{
type: 'HOST_HANDSHAKE_RESPONSE',
loginRequestToken: 'string'
}
Message Properties
stringAlways "HOST_HANDSHAKE_RESPONSE". Identifies this as the response message from MeWe.
stringThe authentication token that you'll exchange for an apiToken using the /api/dev/token endpoint.
Example Implementation
// Set up message listener
function setupMessageListener() {
window.addEventListener('message', (event) => {
const { type, loginRequestToken } = event.data;
if (type === 'HOST_HANDSHAKE_RESPONSE' && loginRequestToken) {
// Remove the listener once we receive the token
window.removeEventListener('message', setupMessageListener);
// Use the loginRequestToken to get an apiToken
exchangeTokenForApiToken(loginRequestToken);
}
});
}
// Start listening for messages
setupMessageListener();
CLIENT_DISPLAY_REQUEST
The CLIENT_DISPLAY_REQUEST message is sent by your embedded app to request display information from the MeWe host application. This includes the app's dimensions, available space, and current state.
When to Send
Send this message when you need to:
- Get the current dimensions of your app
- Determine the available viewport space for your content
- Check if the app is minimized or paused
- Adjust your UI layout based on available space
Message Format
window.parent.postMessage({ type: 'CLIENT_DISPLAY_REQUEST' }, '*');
Message Properties
stringMust be exactly "CLIENT_DISPLAY_REQUEST". This identifies the message type to the MeWe host application.
Example Implementation
function requestDisplayInfo() {
window.parent.postMessage({ type: 'CLIENT_DISPLAY_REQUEST' }, '*');
}
// Request display info when needed
requestDisplayInfo();
HOST_DISPLAY_RESPONSE
The HOST_DISPLAY_RESPONSE message is sent by MeWe in response to your CLIENT_DISPLAY_REQUEST. It contains detailed information about the app's display dimensions and current state.
When You Receive It
You'll receive this message after sending CLIENT_DISPLAY_REQUEST. Use this information to adjust your app's layout and understand the available space.
Message Format
{
type: 'HOST_DISPLAY_RESPONSE',
width: 400,
height: 600,
availableWidth: 368,
viewportHeight: 568,
isMinimized: false,
isPaused: false
}
Message Properties
stringAlways "HOST_DISPLAY_RESPONSE". Identifies this as the response message from MeWe.
numberThe current width of the app in pixels.
numberThe current height of the app in pixels.
numberThe available width for your content (usually same as viewport width but might account for space reserved by MeWe for app controls or spacing around the Embedded app).
numberThe available viewport height for your content (usually same as viewport height but might account for space reserved by MeWe for app controls or spacing around the Embedded app).
booleanIndicates whether the app is currently minimized.
booleanIndicates whether the app is currently paused (e.g., showing a close confirmation dialog).
Example Implementation
window.addEventListener('message', (event) => {
const { type, width, height, availableWidth, viewportHeight, isMinimized, isPaused } = event.data;
if (type === 'HOST_DISPLAY_RESPONSE') {
// Adjust your layout based on available space
updateLayout({
appWidth: width,
appHeight: height,
contentWidth: availableWidth,
contentHeight: viewportHeight,
minimized: isMinimized,
paused: isPaused
});
}
});
CLIENT_DISPLAY_UPDATE
The CLIENT_DISPLAY_UPDATE message is sent by your embedded app to request a change in the app's display dimensions.
When to Send
Send this message when you need to:
- Resize the app to better fit your content
- Adjust the app size based on user interactions
- Optimize the display for different content types
Message Format
window.parent.postMessage(
{
type: 'CLIENT_DISPLAY_UPDATE',
width: 500, // Optional
height: 700 // Optional
},
'*'
);
Message Properties
stringMust be exactly "CLIENT_DISPLAY_UPDATE". This identifies the message type to the MeWe host application.
numberThe desired width in pixels. Must be at least 80px. If not provided, the current width is maintained.
numberThe desired height in pixels. Must be at least 80px. If not provided, the current height is maintained.
Example Implementation
function resizeApp(newWidth, newHeight) {
window.parent.postMessage({
type: 'CLIENT_DISPLAY_UPDATE',
width: newWidth,
height: newHeight
}, '*');
}
// Resize to fit content
resizeApp(600, 800);
The minimum dimensions are enforced by MeWe (80px × 80px). Values below this minimum will be automatically adjusted.
HOST_APP_PAUSED
The HOST_APP_PAUSED message is sent by MeWe to notify your embedded app that it has been paused. This typically occurs when the app needs to be temporarily suspended, such as when a close confirmation dialog is shown.
When You Receive It
You'll receive this message when:
- The user triggers a close action and a confirmation dialog is displayed
- The app needs to be temporarily suspended for system reasons
- The host application needs to pause your app's activity
Message Format
{
type: 'HOST_APP_PAUSED'
}
Message Properties
stringAlways "HOST_APP_PAUSED". Identifies this as a lifecycle event from MeWe.
Example Implementation
window.addEventListener('message', (event) => {
const { type } = event.data;
if (type === 'HOST_APP_PAUSED') {
// Pause animations, timers, or other active processes
pauseAnimations();
clearTimers();
// Save state if needed
saveCurrentState();
}
});
HOST_APP_RESUMED
The HOST_APP_RESUMED message is sent by MeWe to notify your embedded app that it has been resumed after being paused.
When You Receive It
You'll receive this message when:
- The user cancels the close confirmation dialog
- The app is resumed after being paused
- The host application allows your app to continue activity
Message Format
{
type: 'HOST_APP_RESUMED'
}
Message Properties
stringAlways "HOST_APP_RESUMED". Identifies this as a lifecycle event from MeWe.
Example Implementation
window.addEventListener('message', (event) => {
const { type } = event.data;
if (type === 'HOST_APP_RESUMED') {
// Resume animations, timers, or other active processes
resumeAnimations();
restartTimers();
// Restore state if needed
restoreState();
}
});
HOST_APP_CLOSED
The HOST_APP_CLOSED message is sent by MeWe to notify your embedded app that it has been closed by the user.
When You Receive It
You'll receive this message when:
- The user confirms closing the app
- The app is being terminated
- Cleanup is needed before the app is removed
Message Format
{
type: 'HOST_APP_CLOSED'
}
Message Properties
stringAlways "HOST_APP_CLOSED". Identifies this as a lifecycle event from MeWe.
Example Implementation
window.addEventListener('message', (event) => {
const { type } = event.data;
if (type === 'HOST_APP_CLOSED') {
// Perform cleanup tasks
cleanup();
// Save any final state
saveFinalState();
// Stop all timers and listeners
stopAllTimers();
window.removeEventListener('message', messageHandler);
}
});
HOST_APP_MINIMIZED
The HOST_APP_MINIMIZED message is sent by MeWe to notify your embedded app that it has been minimized.
When You Receive It
You'll receive this message when:
- The user minimizes the app
- The app is collapsed to save screen space
Message Format
{
type: 'HOST_APP_MINIMIZED'
}
Message Properties
stringAlways "HOST_APP_MINIMIZED". Identifies this as a lifecycle event from MeWe.
Example Implementation
window.addEventListener('message', (event) => {
const { type } = event.data;
if (type === 'HOST_APP_MINIMIZED') {
// Optionally pause non-essential operations
pauseNonEssentialOperations();
// Update UI to reflect minimized state
updateUIForMinimized();
}
});
HOST_APP_MAXIMIZED
The HOST_APP_MAXIMIZED message is sent by MeWe to notify your embedded app that it has been maximized or restored from minimized state.
When You Receive It
You'll receive this message when:
- The user maximizes the app
- The app is restored from minimized state
Message Format
{
type: 'HOST_APP_MAXIMIZED'
}
Message Properties
stringAlways "HOST_APP_MAXIMIZED". Identifies this as a lifecycle event from MeWe.
Example Implementation
window.addEventListener('message', (event) => {
const { type } = event.data;
if (type === 'HOST_APP_MAXIMIZED') {
// Resume any paused operations
resumeOperations();
// Update UI to reflect maximized state
updateUIForMaximized();
// Optionally request updated display info
window.parent.postMessage({ type: 'CLIENT_DISPLAY_REQUEST' }, '*');
}
});
Complete Authentication Flow
Here's a complete example showing how to use both authentication messages together:
async function authenticateEmbeddedApp() {
return new Promise((resolve, reject) => {
// Set up message listener first
const handler = (event) => {
const { type, loginRequestToken } = event.data;
if (type === 'HOST_HANDSHAKE_RESPONSE' && loginRequestToken) {
window.removeEventListener('message', handler);
resolve({ loginRequestToken });
}
};
window.addEventListener('message', handler);
// Send the handshake request
window.parent.postMessage({ type: 'CLIENT_HANDSHAKE_REQUEST' }, '*');
// Optional: Set a timeout to handle cases where no response is received
setTimeout(() => {
window.removeEventListener('message', handler);
reject(new Error('Authentication timeout'));
}, 10000); // 10 second timeout
});
}
// Usage
try {
const { loginRequestToken } = await authenticateEmbeddedApp();
// Exchange loginRequestToken for apiToken
const response = await fetch('MEWE_HOST/api/dev/token?loginRequestToken=' + loginRequestToken, {
headers: {
'X-App-Id': 'YOUR_APP_ID'
}
});
const { apiToken } = await response.json();
// Use apiToken for authenticated API requests
} catch (error) {
console.error('Authentication failed:', error);
}
Security Considerations
-
Origin Validation: Always validate the origin of incoming messages when possible:
window.addEventListener('message', (event) => { // Validate origin in production if (event.origin !== 'https://mewe.com') { return; } // Process message... }); -
Message Type Validation: Always check the message type before processing:
if (event.data.type !== 'HOST_HANDSHAKE_RESPONSE') { return; // Ignore unexpected message types } -
Token Security: Never expose your
loginRequestTokenorapiTokenin client-side code logs or error messages.
Related Documentation
- Learn more about the complete authentication flow in the Authentication guide
- See how to use the
apiTokenin API Communication