OIDC: option to send the login page straight to the provider - #19
Merged
Conversation
Closes #17. Consumes the LOGIN_PAGE_REDIRECT seam from fogproject#1175. For an install where every account lives at the identity provider, FOG's username and password box is a dead end -- it cannot accept those credentials, so the only thing to do on that page is click past it. `opAutoRedirect`, per provider, sends an anonymous visitor straight to the provider instead. It is also the most dangerous setting in this plugin, and most of what is below is containment rather than feature. ## Off by default, in every place a default can be stated An appended ALTER (existing installs), createSql() (fresh ones), and the create page. An install that upgraded into this switched on would find its login form replaced by a redirect nobody asked for, and the only URL that still shows the form is one nobody has been told about. ## Two flagged providers refuse and render the form The login page cannot redirect to both. Silently picking one -- lowest id, first row, whatever -- hides a misconfiguration on the single page an admin is least able to debug, while sending everybody to a provider half of them may not have an account at. Refusing is a working login for everyone and visibly not what was asked for. The complaint names both providers in the error log and NOT on the page. This code runs for a visitor who has not signed in, and "this server has two misconfigured identity providers" is not something to tell one. ## Two loops that had to be closed first Both used to land on management/index.php, which is precisely the page this feature redirects: - A refused sign-in. `_fail()` now returns to management/login.php, so a provider that is down produces one error message rather than an infinite redirect -- and the flash message is attached to a page that stays put instead of one that immediately hops again. - Logging out with automatic redirect on but single logout off. Core's default landing spot would bounce the person who just signed out back to a provider whose SSO session is still alive and sign them silently back in. "Log out" that leaves you logged in is worse than no logout at all, so the USER_LOGGING_OUT listener falls back to management/login.php -- only as a fallback, so a real provider-logout URL still wins. ## The escape hatch Core's, and pinned there: index.php offers LOGIN_PAGE_REDIRECT only when FOG_LOCAL_LOGIN is undefined, so management/login.php never reaches this plugin's listener at all. Nothing here can change that, which is the whole reason it lives in core -- a plugin that is misconfigured, half-installed or throwing cannot take the page down with it, because it is not asked anything. The management page prints that URL next to the checkbox. Not decoration: an admin who ticks this box without knowing login.php exists has one expired certificate between themselves and being locked out of their own server, and at that point the URL is not something they could guess. ## Verification tests/oidc-auto-redirect.test.php, 20 checks, 21/21 mutations caught -- including the default flipping to on, a step inserted rather than appended, several flagged providers being silently resolved to one, the ambiguity reaching the page instead of the log, a relative start URL (which core's seam drops, so the setting would silently do nothing), both loop regressions, and the fallback overriding a real provider logout. One of those mutations survived the first draft and is worth recording: the escape-hatch assertion searched the whole page for the URL, and the page prints it twice -- so removing it from the autoRedirect label, which is the only place an admin reads it, still passed. Now scoped to that label. sh tests/run-all.sh -> 6 passed, 0 failed. Not exercised end to end against the lab Keycloak yet. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017aBSWrDArXHTpKWkkN27LR
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #17. Consumes the
LOGIN_PAGE_REDIRECTseam fromFOGProject/fogproject#1175, and depends on #18 (single logout) for its schema
ordering.
The ask
For an install where every account lives at the identity provider, FOG's
username and password box is a dead end — it cannot accept those credentials, so
the only thing to do on that page is click past it.
opAutoRedirect, perprovider, sends an anonymous visitor straight to the provider instead.
It is also the most dangerous setting in this plugin, and most of what follows is
containment rather than feature.
Off by default, everywhere a default can be stated
The appended ALTER (existing installs),
createSql()(fresh ones), and thecreate page. An install that upgraded into this switched on would find its login
form replaced by a redirect nobody asked for — and the only URL that still shows
the form is one nobody has been told about yet.
Two flagged providers refuse and render the form
As argued in the issue. The login page cannot redirect to both, and silently
picking one — lowest id, first row, whatever — hides a misconfiguration on the
single page an admin is least able to debug, while sending everybody to a
provider half of them may not have an account at. Refusing is a working login for
everyone and visibly not what was asked for.
The complaint names both providers in the error log and not on the page. This
code runs for a visitor who has not signed in, and "this server has two
misconfigured identity providers" is not something to tell one.
Two loops that had to be closed first
Both previously landed on
management/index.php— precisely the page thisfeature redirects:
_fail())index.php→ straight back out; infinite loop if the provider is down, unreadable flash if notlogin.php— one error message on a page that stays putindex.php→ provider → SSO session still alive → silently signed back inlogin.php— a fallback only, so a real provider-logout URL still wins"Log out" that leaves you logged in is worse than no logout at all.
The escape hatch
Core's, and pinned there.
index.phpoffersLOGIN_PAGE_REDIRECTonly whenFOG_LOCAL_LOGINis undefined, somanagement/login.phpnever reaches thisplugin's listener at all. Nothing here can change that — which is the whole
reason it lives in core: a plugin that is misconfigured, half-installed or
throwing cannot take that page down with it, because it is not asked anything.
The management page prints that URL next to the checkbox. Not decoration: an
admin who ticks this box without knowing
login.phpexists has one expiredcertificate between themselves and being locked out of their own server, and at
that point the URL is not something they could guess.
Verification
tests/oidc-auto-redirect.test.php— 20 checks, 21/21 mutations caught:default flipping to on, a step inserted rather than appended, several flagged
providers silently resolved to one, the ambiguity reaching the page instead of
the log, a relative start URL (core's seam drops it, so the setting would
silently do nothing at all), both loop regressions, and the fallback overriding a
real provider logout.
One mutation survived the first draft and is worth recording: the escape-hatch
assertion searched the whole page for the URL, and the page prints it twice —
so removing it from the
autoRedirectlabel, the only place an admin reads it,still passed. Now scoped to that label.
sh tests/run-all.sh→ 6 passed, 0 failed.Not yet exercised end to end against the lab Keycloak, same as #18.
Follow-up
User docs for both settings — and for
management/login.php— belong inFOGProject/fog-docsand are worth writing now that the pair is complete.🤖 Generated with Claude Code
https://claude.ai/code/session_017aBSWrDArXHTpKWkkN27LR