- Issue created by @cmlara
- Status changed to Needs work
11 months ago 6:20am 22 December 2023 - πΊπΈUnited States cmlara
3410444-event-sub-user-auth is a work in progress to start discussion. This branch provides an event subscriber to catch when bypass_tfa_auth_for_user is utilized and no token validation has occurred.
An alternative we might want to evaluate is if we can perform a check in hook_user_login(). Perhaps a combination of the two options might provide sufficient interlocking.
- πΊπΈUnited States cmlara
Updating title to better reflect that this is related to installing contrib modules leads to TFA accidentally being bypassed (as oppose to intentionally disabling/bypassing TFA)
Linking related core issue for adding better MFA support into the login process since in context its ultimately the adhoc nature that causes issues.
- πΊπΈUnited States cmlara
hook_user_login() is a no-go. It isn't always called after authentication. This can be seen with the http_basic authentication method. While we don't expect http_basic to have the same faults as the form its best not to leave it as a possibility.
I did find a AccountEvents::SET_USER event that is dispatched whenever AccountProxy::setAccount() is called. I am working on converting the solution in 3410444-event-sub-user-auth to to this new event. This event happens sooner which could allow us to depend more on core to handle responses. In the case of the form based we can destroy the exception before hook_user_login() is even called and throw an exception to end code execution. In the case of http_basic (and other similar methods) we could trigger before any code action could occur.
- πΊπΈUnited States cmlara
Looking at AccountEvents::SET_USER and I'm realizing that users being able to be set without going through TFA is inherently also the cause of issues such as π SA-CONTRIB-2023-030 and 2.x Active .
I've been investigate if we can use this for more than just protecting where the forms are modified and instead make it more holistic having the security system defend more generally.
AccountEvents::SET_USER is called:
From user_login_finalize() when starting a session for a user. This occurs when logging in through the forms, using password reset.
Hook_user_login() is called later from inside user_login_finalize().From the AccountSwticher Service (AccountSwitcher::switchTo):
Used when when opening up an impersonation (single request) to allow code to run as one user while not logging out of the first user.AuthenticationSubscriber::onKernelRequestAuthenticate():
This is done on every request. Prior to calling the subscriber obtains the current user from- Session based authentication grabs the UID from
$session->get('uid);
- http_basic authentication provider decodes the username/password before calling the UserAuth service. Auth methods validating passwords will follow similar methods
- Any other authentication provider that validates the information provided, without calling UserAuth
Those method calling the UserAuth service are easy to work with, we could set a flag and know the UserAuth was called and the request is inherently validated through TFA. That covers user_login_finalize() and onKernalRequestAUthenticate for http_basic and similar.
onKernelRequestAuthenticate() for session based authentication could be handled by setting a value iset n hook_user_login() to validate the value isn't changed outside of TFA knowledge (avoiding
$session->set('uid', SOME_UID);
)AccountSwitcher can be exmpeted with a decorator indicating that the request is part of a UserSwitch event. There could be an argument for denying these requests, perhaps that could be a followup for a feature where more discussion on the benefits/risk of doing so.
onKernelRequestAuthenticate() allowing user/password authentication (tokens) while blocking others is the complex one. This, after some deeper thought, can also be solved with a (dynamic) decorator on the methods that are permitted to bypass TFA (such as a token based auth method). This would require some manual configuration by site admins, however it can be limited to a simple configuration parameter and for many sites would require no action.
I have most of the code for this already built as POC, it just needs cleanup and finalized testing to be sure no scenarios are missed. Addtionaly it likely needs documentation improvements to go with it.
- Session based authentication grabs the UID from
- Merge request !75Issue #3410444 by cmlara: Require TFA validation for SET_USER event β (Merged) created by cmlara
- πΊπΈUnited States cmlara
Uploaded a first version of this so that I can step back for a few days and give it another look with a fresh set of eyes.
This includes some decent technical documentation, though I'm realizing as I type that I didn't document in an admin friendly section so will need work for that.
At the moment this will break one time login links. I consider that a proof that this is actually fixing our root level problem in TFA. We can fix the one time login links in π Use an EventSubscriber to process one time login links Needs work .
Looks like one of the tests runs well in my local lab but not in GitLab, will need to investigate options.
- Status changed to Needs review
9 months ago 6:23pm 17 February 2024 - πΊπΈUnited States cmlara
Did some cleanup, mostly around enabling strict types and using static data providers with some minor spelling/wording changes.
If i had to split this up into chunks to make it smaller it would look roughly like:
-- Add flag to complete session login.
src/Form/EntryForm.php
src/Form/TfaLoginForm.php
tests/src/Unit/Form/TfaEntryFormTest.php
tests/src/Unit/Form/TfaLoginFormTest.php
tests/src/Unit/TfaModuleTest.php
tfa.module-- Add flag on complete User.Auth login.
src/TfaUserAuth.php
tests/src/Unit/TfaUserAuthTest.php-- Add Auth Decorators
src/Authentication/Provider/TfaAuthDecorator.php
src/Authentication/Provider/TfaChallengeAuthDecorator.php
src/Compiler/TfaAuthDecoratorCompiler.php
src/TfaServiceProvider.php
tests/src/Unit/Authentication/TfaAuthDecoratorTest.php
tests/src/Unit/Authentication/TfaChallengeAuthDecoratorTest.php
tests/src/Unit/Compiler/TfaAuthDecoratorCompilerTest.php
tests/src/Unit/TfaServiceProviderTest.php-- Add flag for user.switcher
src/TfaAccountSwitcher.php
tests/src/Unit/TfaAccountSwitcherTest.php-- Enforce TFA completed.
docs/SUMMARY.md
docs/configuration/SUMMARY.md
docs/configuration/exempt-auth-provider.md
docs/development/SUMMARY.md
docs/technical/SUMMARY.md
docs/technical/set-user-protection.md
src/EventSubscriber/TfaUserSetSubscriber.php
src/Exceptions/TfaAccessDenied.php
tests/src/Unit/EventSubscriber/TfaUserSetSubscriberTest.php
tests/src/Functional/TfaTestBase.php - Status changed to Fixed
9 months ago 8:03am 27 February 2024 -
cmlara β
committed 01d74999 on 2.x
Issue #3410444 by cmlara: Require TFA validation for SET_USER event
-
cmlara β
committed 01d74999 on 2.x
Automatically closed - issue fixed for 2 weeks with no activity.