Authentication
The Web SDK provides a complete authentication system for micro-frontends running inside Qelos applications.
Overview
Authentication in the Web SDK works through a session-based system where each iframe instance receives a unique code that identifies the session. This code is used to authenticate and authorize the micro-frontend.
Session Code
The session code is automatically extracted from the URL parameters when your micro-frontend loads:
import { code } from '@qelos/web-sdk';
console.log('Current session code:', code);
// Output: Current session code: abc123xyzDefault Code
If your micro-frontend is loaded outside of a Qelos host (e.g., during development), the code defaults to 'default':
import { code } from '@qelos/web-sdk';
if (code === 'default') {
console.log('Running in standalone mode');
} else {
console.log('Running inside Qelos host');
}Authorization
authorize()
The authorize() function authenticates your micro-frontend session and retrieves user data:
import { authorize } from '@qelos/web-sdk';
const userData = await authorize();
console.log('User:', userData.user);
console.log('Workspace:', userData.workspace);
console.log('Tenant:', userData.tenant);Response Structure
interface AuthorizeResponse {
user: {
_id: string;
username: string;
email: string;
fullName: string;
firstName: string;
lastName: string;
roles: string[];
metadata: any;
};
workspace: {
_id: string;
name: string;
logo?: string;
labels: string[];
};
tenant: string;
token: string;
}Example: Complete Authorization Flow
import { authorize, code } from '@qelos/web-sdk';
async function initializeApp() {
try {
console.log('Authorizing with code:', code);
const data = await authorize();
// User is authenticated
console.log('Authenticated as:', data.user.fullName);
console.log('Workspace:', data.workspace.name);
// Store user data in your app state
return data;
} catch (error) {
console.error('Authorization failed:', error);
// Handle authorization failure
throw error;
}
}
// Call on app initialization
initializeApp();Re-Authorization
reAuthorize()
If the user's session expires or needs to be refreshed, you can trigger re-authorization:
import { reAuthorize } from '@qelos/web-sdk';
// Trigger re-authorization flow
reAuthorize();This will:
- Dispatch a re-authorization event to the host
- The host will handle the authentication
- Your micro-frontend will receive updated credentials
onReAuthorize()
Listen for re-authorization events to update your application state:
import { onReAuthorize } from '@qelos/web-sdk';
onReAuthorize((newData) => {
console.log('Re-authorized with new data:', newData);
// Update your application state
updateUserData(newData);
});Un-Authorization
unAuthorize()
Clean up the session when the user leaves or the micro-frontend unmounts:
import { unAuthorize } from '@qelos/web-sdk';
// Clean up session
await unAuthorize();The SDK automatically calls unAuthorize() when:
- The page is about to unload (
beforeunloadevent) - The host sends a
shutdownevent
Manual Cleanup
For single-page applications, you may want to manually clean up:
import { unAuthorize } from '@qelos/web-sdk';
// React example
useEffect(() => {
return () => {
// Cleanup on component unmount
unAuthorize();
};
}, []);// Vue example
onBeforeUnmount(() => {
unAuthorize();
});Token Management
The authorization token is included in the response from authorize():
const { token } = await authorize();
// Use the token for API requests
fetch('/api/data', {
headers: {
'Authorization': `Bearer ${token}`
}
});Token in URL
The token is also available as a URL parameter when your micro-frontend first loads:
const urlParams = new URLSearchParams(window.location.search);
const token = urlParams.get('token');Backend Integration
Your micro-frontend backend should implement the /api/authorize endpoint:
// Example Express.js endpoint
app.post('/api/authorize', async (req, res) => {
const { returnUrl, token } = req.body;
const code = req.headers.code;
try {
// Verify token with Qelos
const userData = await verifyWithQelos(token, code);
// Store session
await storeSession(code, userData);
res.json(userData);
} catch (error) {
res.status(401).json({ error: 'Unauthorized' });
}
});Un-Authorize Endpoint
Implement the cleanup endpoint:
app.post('/api/un-authorize', async (req, res) => {
const code = req.headers.code;
// Clean up session
await removeSession(code);
res.json({ success: true });
});Security Best Practices
- Always validate the token on your backend
- Use HTTPS for all communications
- Set appropriate CORS headers to restrict access
- Implement session timeouts to expire old sessions
- Clean up sessions when users leave
Error Handling
import { authorize } from '@qelos/web-sdk';
try {
const userData = await authorize();
// Success
} catch (error) {
if (error.status === 401) {
// Unauthorized - invalid token or code
console.error('Authentication failed');
} else if (error.status === 403) {
// Forbidden - user doesn't have access
console.error('Access denied');
} else {
// Other errors
console.error('Authorization error:', error);
}
}Complete Example
import { authorize, unAuthorize, onReAuthorize, code } from '@qelos/web-sdk';
class AuthService {
private userData: any = null;
async initialize() {
console.log('Initializing with code:', code);
// Initial authorization
this.userData = await authorize();
// Listen for re-authorization
onReAuthorize((newData) => {
this.userData = newData;
this.onUserDataChanged(newData);
});
// Cleanup on page unload
window.addEventListener('beforeunload', () => {
unAuthorize();
});
return this.userData;
}
getUser() {
return this.userData?.user;
}
getWorkspace() {
return this.userData?.workspace;
}
getToken() {
return this.userData?.token;
}
private onUserDataChanged(newData: any) {
// Notify your application of user data changes
console.log('User data updated:', newData);
}
}
// Usage
const authService = new AuthService();
await authService.initialize();