Skip to main content

Advanced Features

Session Management

Checking Session Status

// Check if session is active
if (sdk.hasActiveSession()) {
console.log('Session is active');
}

// Get current session data
const session = sdk.getSession();
if (session) {
console.log('User ID:', session.userId);
console.log('Expires at:', new Date(session.expiresAt * 1000));
console.log('Time remaining:', session.getRemainingSeconds(), 'seconds');
}

Manually Ending a Session

// End session early
await sdk.endSession('manual');

// With reason
await sdk.endSession('user_requested');

Extending a Session

Request more time (requires backend support):

try {
await sdk.extendSession(30); // Request 30 more minutes
console.log('Session extended successfully');
} catch (error) {
console.error('Failed to extend:', error);
showError('Could not extend session. Please try again.');
}

Pausing/Resuming Timer (UI Only)

// Pause timer (visual only, session still expires)
sdk.pauseTimer();

// Resume timer
sdk.resumeTimer();

// Check if paused
if (sdk.isTimerPaused()) {
console.log('Timer is paused');
}
note

Pausing only affects the UI display. The actual session expiration continues server-side.


Multi-Tab Coordination

The SDK automatically coordinates sessions across browser tabs:

  • Master tab election — first tab becomes master
  • Automatic timer synchronization — all tabs stay in sync
  • Shared session state via BroadcastChannel API
  • Seamless master failover if the active tab closes

No configuration needed — works out of the box.

Listening for multi-tab events:

window.addEventListener('marketplace-session-sync', (event) => {
console.log('[MultiTab] Session synced:', event.detail);
});

Fallback: Modern browsers use BroadcastChannel. Older browsers fall back to localStorage events.


Heartbeat System

Periodic server communication for time synchronization:

const sdk = new MarketplaceSDK({
// ... other options
heartbeat: {
enabled: true,
intervalSeconds: 30,
endpoint: 'https://api.example.com/sessions/heartbeat',
},
});

Backend Heartbeat Handler

@app.route('/sessions/heartbeat', methods=['POST'])
def session_heartbeat():
data = request.json
session_id = data['sessionId']
client_time = data['timestamp']

# Validate session still active
session = get_session(session_id)
if not session or session.is_expired():
return jsonify({'error': 'Session expired'}), 410

# Return server time for sync
server_time = int(time.time())
update_session_heartbeat(session_id, server_time)

return jsonify({
'serverTime': server_time,
'expiresAt': session.expires_at,
'remainingSeconds': session.get_remaining_seconds()
})

Failure Handling

  • 3 heartbeat failures triggers automatic stop (by design — prevents spam)
  • Session continues without heartbeat after failure
  • Heartbeat does not resume automatically after network recovery

Visibility API Integration

Auto-pause when tab is hidden (battery-friendly):

const sdk = new MarketplaceSDK({
// ... other options
pauseWhenHidden: true,
});

The SDK automatically:

  • Pauses the timer when the tab is hidden
  • Resumes when the tab becomes visible again
  • Syncs time with server on resume

Backend JWT Validation

Alternative to JWKS for sensitive applications:

const sdk = new MarketplaceSDK({
// ... other options
validateJWTBackend: true,
validationEndpoint: 'https://api.example.com/validate-jwt',
});

Backend Validation Endpoint

@app.route('/validate-jwt', methods=['POST'])
def validate_jwt():
jwt_token = request.json['jwt']

try:
response = requests.post(
'https://api.generalwisdom.com/validate-session',
headers={'Authorization': f'Bearer {jwt_token}'}
)

if response.status_code == 200:
claims = response.json()
return jsonify({'valid': True, 'claims': claims})
else:
return jsonify({'valid': False, 'error': 'Invalid JWT'}), 401

except Exception as e:
return jsonify({'valid': False, 'error': str(e)}), 500

Security Best Practices

JWT Validation

Do:

  • Always validate JWT signature (SDK does this automatically)
  • Check expiration time
  • Verify issuer matches marketplace
  • Validate applicationId matches your app
  • Use JWKS for signature verification (production)

Do not:

  • Skip JWT validation
  • Trust client-side validation only
  • Store JWT in localStorage without encryption
  • Share JWT across origins

Token Storage

Do:

  • Use httpOnly cookies for sensitive tokens (if possible)
  • Use chrome.storage for extensions (browser-encrypted)
  • Clear tokens immediately on session end
  • Set appropriate expiration times

Do not:

  • Store sensitive data in localStorage without encryption
  • Keep tokens after session ends
  • Share tokens between users/sessions

HTTPS Requirements

Production applications must have:

  • HTTPS for all API endpoints
  • Valid SSL certificate
  • Secure WebSocket connections (wss://)
  • HSTS headers enabled

Rate Limiting

Protect your backend endpoints:

from flask_limiter import Limiter

limiter = Limiter(app, key_func=lambda: request.headers.get('X-Session-ID'))

@app.route('/auth/marketplace', methods=['POST'])
@limiter.limit("10 per minute")
def marketplace_auth():
# ... auth logic

Secrets Management

Do:

  • Use environment variables for secrets
  • Use AWS Secrets Manager / Azure Key Vault
  • Rotate secrets regularly
  • Never commit secrets to git

Do not:

  • Hard-code API keys in source code
  • Commit .env files
  • Share secrets in plain text

Input Validation

onSessionStart: async (context: SessionStartContext) => {
if (context.email && !isValidEmail(context.email)) {
throw new Error('Invalid email format');
}

if (!isValidUUID(context.userId)) {
throw new Error('Invalid user ID format');
}

const sanitizedEmail = sanitize(context.email);
// ... rest of logic
},

Deployment Checklist

  • Replace test JWKS URL with production
  • Update applicationId to registered value
  • Enable HTTPS for all endpoints
  • Configure proper CORS headers
  • Set up secrets management
  • Enable rate limiting on auth endpoints
  • Configure logging and monitoring
  • Test JWT validation with production keys
  • Test session extension flow
  • Test multi-tab coordination
  • Set proper CSP headers
  • Enable HSTS
  • Configure marketplace redirect URL
  • Test error handling and fallbacks
  • Load test auth endpoints
  • Set up alerts for auth failures

Monitoring

Track key metrics:

onSessionStart: async (context) => {
analytics.track('marketplace_session_start', {
userId: context.userId,
sessionId: context.sessionId,
durationMinutes: context.durationMinutes,
});
},

onSessionEnd: async (context) => {
analytics.track('marketplace_session_end', {
userId: context.userId,
sessionId: context.sessionId,
reason: context.reason,
actualDuration: context.actualDurationMinutes,
});
},

Monitor errors:

onSessionStart: async (context) => {
try {
await authenticateUser(context);
} catch (error) {
errorTracker.captureException(error, {
extra: {
userId: context.userId,
sessionId: context.sessionId,
},
});
throw error;
}
},