diff --git a/public/js/accountBoundary.js b/public/js/accountBoundary.js index ab42fe74..c1ea5fd4 100644 --- a/public/js/accountBoundary.js +++ b/public/js/accountBoundary.js @@ -14,8 +14,14 @@ function recoverSignIn() { signInRequired = true; freeze(); + // Say what happened, not only that something did. This fires when the page + // is bound to one account and the session belongs to another — switching + // accounts on a shared device is the ordinary cause, and it reads as a + // failure when the message does not name it. document.querySelector('#account-recovery p').textContent = - 'Your saved credentials no longer match this session. Sign in again in a fresh page.'; + 'This page was opened for a different account than the one now signed in. ' + + 'That is a safeguard, not an error: nothing is lost, and no data from either ' + + 'account has been mixed. Start a fresh session to continue.'; document.querySelector('#account-recovery button').textContent = 'Sign in again'; } function read() { diff --git a/public/js/auth.js b/public/js/auth.js index 0ae1d303..f6b9a470 100644 --- a/public/js/auth.js +++ b/public/js/auth.js @@ -191,9 +191,21 @@ document.addEventListener('DOMContentLoaded', function() { } catch (e) {} var ssoButton = document.getElementById('btn-sso'); if (ssoButton) ssoButton.addEventListener('click', async function(e) { - if (!e.isTrusted || authenticationPending || boundary.blocked()) { e.preventDefault(); return; } + // A frozen realm cannot start a login, and silently doing nothing reads as + // "SSO is broken" — it is the account boundary holding, not a failure. Say + // so, and point at the one control that clears it. + if (boundary.blocked()) { + e.preventDefault(); + showToast('This page is locked to a different account. Tap "Sign in again" to start a fresh session, then use SSO.', 'error'); + return; + } + if (!e.isTrusted || authenticationPending) { e.preventDefault(); return; } boundary.capture(); // Detect a replaced sibling session before capturing credentials. - if (boundary.blocked()) { e.preventDefault(); return; } + if (boundary.blocked()) { + e.preventDefault(); + showToast('This page is locked to a different account. Tap "Sign in again" to start a fresh session, then use SSO.', 'error'); + return; + } // No owner marker can also mean bootstrap failed with an old cookie still // valid. Every SSO start must prove cookie absence before issuing intent. e.preventDefault();