fix(oauth): only ask for the account chooser on an explicit login click

The login page now sends `user_initiated=true` when someone clicks a
provider button, and the backend applies the provider's `extra_params`
only for those requests.

Someone whose browser holds a single Google session whose email is
already registered under a different login type hits
"an user with the email associated to this login exists but with a
different login type" and, with no account chooser, has no way to offer
a different account. The chooser belongs on that click.

It does not belong on the `auto_login_provider` redirect, whose whole
purpose is to sign a public-app or approval-page visitor in without
interaction.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0196aV8v36ukoQcD7L2scvmH
This commit is contained in:
Guilhem Lemouel
2026-09-03 19:28:46 +02:00
co-authored by Claude Opus 5
parent 3c5a4f2801
commit 6858d1fb30
2 changed files with 14 additions and 5 deletions
+1 -1
View File
@@ -1 +1 @@
6db6307b4507d793628eedce88bbd7c9a66ddd56
e11dbe96407f2831cfb71ecadad94e38113eb61f
+13 -4
View File
@@ -400,7 +400,7 @@
if (!redirectSaml()) autoRedirecting = false
} else if (logins?.some((l) => l.type === autoLogin)) {
autoRedirecting = true
if (!storeRedirect(autoLogin)) {
if (!storeRedirect(autoLogin, false)) {
autoRedirecting = false
sendUserToast('Popup blocked — please click the sign-in button to continue.', true)
}
@@ -534,12 +534,19 @@
}
}
function storeRedirect(provider: string): boolean {
// `userInitiated` tells the backend the user picked this provider themselves, which is
// what makes Google and Microsoft show their account chooser. Auto-login passes false
// so its redirect stays a silent bounce.
function storeRedirect(provider: string, userInitiated: boolean): boolean {
// The kitchen sink renders real provider buttons; clicking one must not leave the page.
if (previewConfig) return true
markLoginMethodPending({ kind: 'oauth', provider })
persistRd()
let url = base + '/api/oauth/login/' + provider + (popup ? '?close=true' : '')
const params = new URLSearchParams()
if (popup) params.set('close', 'true')
if (userInitiated) params.set('user_initiated', 'true')
const query = params.toString()
let url = base + '/api/oauth/login/' + provider + (query ? '?' + query : '')
console.log('storeRedirect', popup, url)
if (popup) {
@@ -677,7 +684,9 @@
unifiedSize="lg"
startIcon={entry.icon ? { icon: entry.icon, classes: 'h-4' } : undefined}
onClick={() =>
entry.method.kind === 'saml' ? redirectSaml() : storeRedirect(entry.method.provider)}
entry.method.kind === 'saml'
? redirectSaml()
: storeRedirect(entry.method.provider, true)}
>
Continue with {entry.displayName}
</Button>