Fix Strava OAuth popup detection via postMessage (cross-origin safe)

This commit is contained in:
Davide Scaini
2026-05-10 17:04:30 +02:00
parent 695dc9fdce
commit 5be58f4e1c
+32 -17
View File
@@ -821,25 +821,35 @@ try {
const popup = window.open(url, 'strava-auth', 'width=600,height=700,left=200,top=100'); const popup = window.open(url, 'strava-auth', 'width=600,height=700,left=200,top=100');
stravaStatus.textContent = 'Waiting for Strava authorisation…'; stravaStatus.textContent = 'Waiting for Strava authorisation…';
// Listen for the callback redirect closing the popup // postMessage listener — works cross-origin (callback may be on a different subdomain)
const poll = setInterval(() => { function onStravaMsg(e: MessageEvent) {
try { if (!e.data || e.data.stravaAuth === undefined) return;
if (popup && popup.location.href.includes('strava=connected')) { window.removeEventListener('message', onStravaMsg);
clearInterval(poll); clearInterval(closedPoll);
popup.close(); popup?.close();
stravaStatus.textContent = 'Connected!'; if (e.data.stravaAuth === 'connected') {
stravaStatus.style.color = '#4ade80'; stravaStatus.textContent = 'Connected!';
stravaConnect.style.display = 'none'; stravaStatus.style.color = '#4ade80';
stravaSync.style.display = ''; stravaConnect.style.display = 'none';
stravaLastSync.textContent = 'never'; stravaSync.style.display = '';
} else if (popup && popup.location.href.includes('strava=error')) { stravaLastSync.textContent = 'never';
clearInterval(poll); } else {
popup.close(); stravaStatus.textContent = 'Authorisation failed.';
stravaStatus.textContent = 'Authorisation failed.'; stravaStatus.style.color = '#f87171';
}
}
window.addEventListener('message', onStravaMsg);
// Fallback: if popup is closed without a message, clean up
const closedPoll = setInterval(() => {
if (popup && popup.closed) {
clearInterval(closedPoll);
window.removeEventListener('message', onStravaMsg);
if (stravaStatus.textContent === 'Waiting for Strava authorisation…') {
stravaStatus.textContent = 'Window closed — authorisation not completed.';
stravaStatus.style.color = '#f87171'; stravaStatus.style.color = '#f87171';
} }
} catch (_) {} }
if (popup && popup.closed) clearInterval(poll);
}, 500); }, 500);
} catch (e) { } catch (e) {
stravaStatus.textContent = 'Error: ' + e.message; stravaStatus.textContent = 'Error: ' + e.message;
@@ -1139,7 +1149,12 @@ try {
// Handle ?strava= param set by the callback redirect (popup scenario) // Handle ?strava= param set by the callback redirect (popup scenario)
const sp = new URLSearchParams(window.location.search); const sp = new URLSearchParams(window.location.search);
if (sp.has('strava')) { if (sp.has('strava')) {
const stravaVal = sp.get('strava');
history.replaceState(null, '', window.location.pathname); history.replaceState(null, '', window.location.pathname);
if (window.opener) {
window.opener.postMessage({ stravaAuth: stravaVal }, '*');
window.close();
}
} }
</script> </script>
)} )}