-
Notifications
You must be signed in to change notification settings - Fork 54
Description
Problem
Users remain authenticated on connect.fireproof.direct after logging out locally, causing confusion and potential security concerns. The authentication persists across the domain boundary because:
- Clerk manages authentication on connect.fireproof.direct
- Local logout only clears Fireproof tokens, not the Clerk session
- No logout endpoint exists to clear the remote session
Proposed Solution
Implement a comprehensive cross-domain logout mechanism that clears both local and remote sessions.
Implementation Plan
1. Enhance TokenStrategie Interface
Add optional performLogout method to the TokenStrategie interface:
export interface TokenStrategie {
// ... existing methods
performLogout?(sthis: SuperThis, logger: Logger, opts: ToCloudOpts): Promise<boolean>;
}2. Implement performLogout in Strategy Classes
RedirectStrategy - Use popup-based logout with enhanced error handling:
async performLogout(sthis: SuperThis, logger: Logger, opts: ToCloudOpts): Promise<boolean> {
this.stop();
if (this.overlayNode) {
this.overlayNode.style.display = 'none';
}
const webCtx = opts.context.get(WebCtx) as WebToCloudCtx;
const logoutUrl = webCtx.dashboardURI.replace('/fp/cloud/api/token', '/fp/cloud/api/logout');
return new Promise((resolve) => {
let popup: Window | null = null;
try {
popup = window.open(logoutUrl, 'FireproofLogout', 'width=400,height=300,popup=yes');
if (!popup) {
console.warn('Popup blocked - logout may be incomplete');
resolve(false);
return;
}
} catch (error) {
console.error('Failed to open logout popup:', error);
resolve(false);
return;
}
const handleMessage = (event: MessageEvent) => {
if (event.data?.type === 'fireproof-logout-complete') {
cleanup();
resolve(true);
}
};
// Handle manual popup closure
const checkClosed = setInterval(() => {
if (popup?.closed) {
cleanup();
resolve(false);
}
}, 1000);
const cleanup = () => {
window.removeEventListener('message', handleMessage);
clearInterval(checkClosed);
popup?.close();
};
window.addEventListener('message', handleMessage);
// Timeout fallback
setTimeout(() => {
cleanup();
resolve(false);
}, 30000);
});
}IframeStrategy - Similar implementation using iframe communication
SimpleTokenStrategy - Basic implementation returning true
3. Create performCompleteLogout Helper
Add to WebCtxImpl for coordinating the full logout process:
async performCompleteLogout(strategy?: TokenStrategie): Promise<void> {
// Call strategy's performLogout if available
if (strategy?.performLogout) {
await strategy.performLogout(this.sthis, logger, this.opts);
}
// Clear local tokens
await this.resetToken();
// Notify listeners
this.onAction();
}4. Add Dashboard Logout Endpoint
Create /fp/cloud/api/logout endpoint that:
- Clears Clerk session cookies
- Posts completion message to parent window
- Returns appropriate CORS headers
5. Integration Points
Update existing disableSync() functionality to use the new logout mechanism when available.
Benefits
- Complete session cleanup across domains
- Consistent with existing popup-based auth flow
- Backward compatible (optional interface method)
- Proper error handling for popup blockers
- Clear user feedback on logout status
Questions to Address
- Should logout URL pattern (/token → /logout) be configurable?
- Should logout invalidate tokens for all apps or just current ledger?
- How to handle offline logout attempts?
- Token invalidation scope (ledger vs account level)?
Related Issues
- Misleading parameter naming in TokenStrategy.open() method for database name passing #1166 (Database name parameter in auth URLs)
- useDocument merge() calls without save() - clients expect automatic persistence #1188 (merge() without save() persistence)
- Implement cross-domain logout for Fireproof Cloud authentication #1208 (Original cross-domain logout issue)
Priority
High - This is a security and UX concern affecting all Fireproof Cloud users.