All auth changes - #7848
Merged
Merged
Conversation
This was referenced Dec 31, 2025
Closed
distantnative
force-pushed
the
v6/refact/auth
branch
from
January 2, 2026 21:02
4b26f5e to
5c6bc72
Compare
9 tasks
[Auth] refact: Login view for new auth architecture
distantnative
force-pushed
the
v6/refact/auth
branch
from
June 23, 2026 14:32
73cfcc2 to
7075664
Compare
distantnative
force-pushed
the
v6/refact/auth
branch
from
June 23, 2026 14:35
7075664 to
2f0c805
Compare
bastianallgeier
self-requested a review
June 30, 2026 14:51
bastianallgeier
approved these changes
Jun 30, 2026
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.
Description
This PR replaces the monolithic
Kirby\Cms\Authclass with a restructured newKirby\Authnamespace. The old class has grown into a 30ish-method mighty bag that handles rate limiting, CSRF, session/user resolution, basic-auth gating, password validation, challenge creation/verification, status assembly and impersonation all in one file. In the new namespace, these different responsibilities have been extracted into various classes.On top of the refactor, it introduces an extension for auth methods that mirrors our extension for custom auth challenges. It rebuilds the Panel login view (incl. more backend-driven), has a new Panel security drawer to manage all security-related settings for a user and adds the ability to switch between challenges mid-login.
New
Kirby\AuthnamespaceClass reference
AuthStatus, keeps the public API (authenticate(),verifyChallenge(),validatePassword(),user(),status(),impersonate(),logout(), …).Methodsenabled(),get(),has(),firstEnabled(),hasAnyUsingChallenges()). Static$methodsmap filled by plugins.Method(abstract)authenticate()returns aUser(done) or a pendingStatus(challenge required).PasswordMethodStatuswhen'2fa' => true).BasicAuthMethodisEnabled()gating (HTTPS, password method on, no 2FA).CodeMethodPasswordResetMethodCodeMethod; starts the password-reset challenge (always short-lived session).Challengescreate(),verify(),switch(),firstAvailable(),ensureNotTimeout(),ensureActiveChallenge().Challenge(abstract)EmailChallenge/TotpChallengeState(enum)Active/Impersonated/Pending/Inactive(replaces string status).StatusPendingpublic(→ frontend) and#[SensitiveParameter] secret(→ server).UserCsrfLimitsException\RateLimitException,ChallengeTimeoutException,LoginNotPermittedExceptionPermissionException; replace the olddetails['reason']string markers.Kirby\Exception\UserNotFoundExceptionNotFoundException; replaces inlineNotFoundException(key: 'user.notFound').Login flow in one breath:
Auth::authenticate($method, …)→Methods::get($method)->authenticate(). The method either logs the user in (returnsUser) or returns a pendingStatusafter askingAuth::createChallenge()→Challenges::create()to pick the first available challenge and store aPendingin the session. A later request callsAuth::verifyChallenge($input)→Challenges::verify(), which checks timeout/active-challenge, verifies the code, then logs the user in passwordless (or flagsresetPasswordfor the reset flow).Changelog
🎉 Features
::form(), which is what makes the login UI fully extensible end-to-end.✨ Enhancements
otpauth://setup-key link, and password confirmation.hashtag,email-unread🐛 Bug fixes
♻️ Refactored
Kirby\Cms\Authclass split into newKirby\Authnamespace:Kirby\Auth\Limits,Kirby\Auth\Csrf,Kirby\Auth\Methodsand individualKirby\Auth\Methodclasses,Kirby\Auth\User,Kirby\Auth\Challengesand individualKirby\Auth\Challengeclasses,Kirby\Auth\Pending,Kirby\Auth\Statusclass andKirby\Auth\StateenumKirby\Auth\Exception\RateLimitException,Kirby\Auth\Exception\LoginNotPermittedException,Kirby\Exception\UserNotFoundExceptionandKirby\Auth\Exception\ChallengeTimeoutExceptionLoginView.vueshell driven by the backend.Kirby\Cms\User::changeSecret()/Kirby\Cms\UserRules::changeSecret()generalise the old TOTP-specific secret writing.☠️ Deprecated
Kirby\Cms\Auth→ useKirby\Auth\Auth(kept working via alias).Kirby\Cms\Auth\Status→ useKirby\Auth\Status(old class kept as a stub).Auth::login2fa()→ useAuth::authenticate().Auth::enabledChallenges()→challenges()->enabled().Auth::isBlocked()/log()/logfile()/track()→ the equivalents on::limits(), e.g.$auth->limits()->isBlocked().Cms\System::loginMethods()→$kirby->auth()->methods()->enabled()UserActions::changeTotp()/UserRules::changeTotp()→changeSecret('totp', …).🚨 Breaking changes
Everywhere where
Kirby\Cms\Auth\Statusgot returned or expected as parameter,Kirby\Auth\Statusis now used.Removed .
Auth challenge classes have been redesigned. Existing custom auth challenges must be rewritten and have to adopt the new
Kirby\Auth\Challengebase class.Auth session format changed:
kirby.challenge.code→kirby.challenge.data. In-flight challenges across the Kirby upgrade won't verify.Kirby\Auth\Status:$auth->status()returnsKirby\Auth\Status,is(State),clone()removed.::validatePassword()returnsUser|null::verifyChallenge(mixed $input)returnsUser|nullUser::changeTotp()renamed toUser::changeSecret('totp', ...)Panel: TOTP enable/disable dialogs removed (
UserTotpEnableDialogController,UserTotpDisableDialogControllerand<k-totp-dialog>). UseUserTotpDrawerControllerand<k-user-totp-drawer>instead.Panel login route shape changed: multi-step
login/method/...andlogin/challenge/...Panel components removed/renamed:
k-login-form,k-login-code-formand the deprecated aliasesk-login/k-login-coderemoved.panel.plugins.loginextension point removed. Plugins that overrode the whole login form via this hook break and should provide a custom auth method (incl.::form()) instead.Kirby\Cms\Find::user()throwsUserNotFoundExceptionHousekeeping
Docs
Needs doc updates for:
Kirby\Authnamespace** + class reference / extension points (authMethods,authChallenges,Method::form(),Challenge::form()).For review team