diff --git a/frontend/src/components/actions/Account.test.tsx b/frontend/src/components/actions/Account.test.tsx index 7ae6588..7cf5b74 100644 --- a/frontend/src/components/actions/Account.test.tsx +++ b/frontend/src/components/actions/Account.test.tsx @@ -128,6 +128,22 @@ describe('useAuthSession Go Loose bootstrap', () => { expect(location.assign).not.toHaveBeenCalled() }) + it('falls back to password sign-in when the tenant has no client credentials', async () => { + // A 503 is what a configured tenant without Go Loose credentials returns. It is + // just as unusable as a 404, and treating it as "available" left the sign-in + // button leading to an error page with no way in. + const location = setHost('nmbs.guess-dev.urpi.be') + vi.stubGlobal( + 'fetch', + vi.fn(() => json({ error: 'Go Loose login is not configured for tenant "nmbs"' }, 503)), + ) + + renderProbe() + + await waitFor(() => expect(screen.getByText('false|false')).toBeInTheDocument()) + expect(location.assign).not.toHaveBeenCalled() + }) + it('falls back to password sign-in when the API reports no Go Loose login', async () => { const location = setHost('nmbs.guess-dev.urpi.be') vi.stubGlobal( diff --git a/frontend/src/components/actions/Account.tsx b/frontend/src/components/actions/Account.tsx index 63e685c..f080801 100644 --- a/frontend/src/components/actions/Account.tsx +++ b/frontend/src/components/actions/Account.tsx @@ -68,17 +68,25 @@ export function useAuthSession() { redirect: 'manual', }) if (cancelled) return - if (response.status === 404) { - // Go Loose login is not configured for this host: sign in with a password. + if (response.ok) { + // An existing Go Loose session. This is also the single sign-on case: + // having signed in anywhere in the family, the person lands here + // already authenticated. + setSsoAvailable(true) + authStorage.save(await response.json()) + setAuthenticated(true) + setSessionExpired(false) + return + } + if (response.status === 404 || response.status === 503) { + // Either Go Loose login is not set up for this host at all (404), or the + // host is a known tenant whose client credentials have not been supplied + // (503). Neither can produce a sign-in, so offering the button would + // dead-end on an error page instead of letting the person in. setSsoAvailable(false) return } setSsoAvailable(true) - if (response.ok) { - authStorage.save(await response.json()) - setAuthenticated(true) - setSessionExpired(false) - } } catch { // An unreachable API leaves ssoAvailable null, which keeps the single // sign-on button on screen: it is the only way in on such a host anyway.