fireproof-storage / fireproof-storage/fireproof
Implement cross-domain logout for Fireproof Cloud authentication
- Dominant language
- TypeScript
- Stars
- 973
- Forks
- 58
- PR merge metrics
- No merged PRs in 30d
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:
1. Clerk manages authentication on connect.fireproof.direct
2. Local logout only clears Fireproof tokens, not the Clerk session
3. 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:
```typescript
export interface TokenStrategie {
// ... existing methods
performLogout?(sthis: SuperThis, logger: Logger, opts: ToCloudOpts): Promise;
}
```
#### 2. Implement performLogout in Strategy Classes
**RedirectStrategy** - Use popup-based logout with enhanced error handling:
```typescript
async performLogout(sthis: SuperThis, logger: Logger, opts: ToCloudOpts): Promise {
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:
```typescript
async performCompleteLogout(strategy?: TokenStrategie): Promise {
// 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
1. Should logout URL pattern (/token → /logout) be configurable?
2. Should logout invalidate tokens for all apps or just current ledger?
3. How to handle offline logout attempts?
4. Token invalidation scope (ledger vs account level)?
## Related Issues
- #1166 (Database name parameter in auth URLs)
- #1188 (merge() without save() persistence)
- #1208 (Original cross-domain logout issue)
## Priority
High - This is a security and UX concern affecting all Fireproof Cloud users.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.