Page MenuHomePhabricator

Add a way to lazy load OATHUser or provide a cheap "user has 2FA enabled" check
Closed, ResolvedPublic

Description

Per @Catrope's CR in https://gerrit.wikimedia.org/r/c/mediawiki/extensions/OATHAuth/+/1187077/1/src/Hook/HookHandler.php as a followup to T404252: OATHAuth loading more from the database than needed...

Note that if OATHRequiredForGroups is non-empty (as it is in production), this function call will lead to an oathUser lookup still happening for users who are in those groups. So this change won't completely eliminate oathUser lookups on random unrelated page views, but it will limit them to users who are members of sensitive groups. If we wanted to fix that, we'd probably need more lazy-loading in OATHUser, or a more efficient way of looking up whether the current user has 2FA enabled at all without loading the details of all their 2FA keys.

We should either add a way a lazy load to OATHUser, and/or a way to just check if the user has 2FA enabled (1 or more rows in oad_devices as of writing), rather than constructing a full OATHUser object, which, for example, when T145915: OATHAuth OTP shouldn't be stored in cleartext in the DB is deployed, could result in unnecessary decryption of data from the database when it's not required

Event Timeline

T406932: TypeError: MediaWiki\Extension\OATHAuth\Key\TOTPKey::__construct(): Argument #3 ($recoveryCodes) must be of type array, string given, called in /srv/mediawiki/php-1.45.0-wmf.22/extensions/OATHAuth/src/Key/TOTPKey.php on line 12 just reminded me of this. A user viewing the main page was getting fatals because of missing "schema" updates...

Obviously missing schema changes aren't exactly helpful. Neither are fatals, but...

	private function getDisabledGroups( User $user, array $groups ): array {
		$requiredGroups = $this->config->get( 'OATHRequiredForGroups' );
		// Bail early if:
		// * No configured restricted groups
		// * The user is not in any of the restricted groups
		$intersect = array_intersect( $groups, $requiredGroups );
		if ( !$requiredGroups || !$intersect ) {
			return [];
		}

		$oathUser = $this->userRepo->findByUser( $user );
		if ( !$oathUser->isTwoFactorAuthEnabled() ) {
			// Not enabled, strip the groups
			return $intersect;
		}

		return [];
	}

We were getting and loading their recovery tokens and stuff... just to see if they have 2FA enabled.

A little better if it's cached (in the same request), but still pretty wasteful overall.

Catrope added a subscriber: Mstyles.
Reedy triaged this task as Low priority.May 6 2026, 2:51 PM

Change #1285497 had a related patch set uploaded (by Reedy; author: Reedy):

[mediawiki/extensions/OATHAuth@master] OATHUserRepository: Add a 'cheap' way to check if a user has 2FA enabled

https://gerrit.wikimedia.org/r/1285497

Change #1285498 had a related patch set uploaded (by Reedy; author: Reedy):

[integration/config@master] zuul: Add OATHAuth as a dependancy for EmailAuth

https://gerrit.wikimedia.org/r/1285498

Change #1285498 merged by jenkins-bot:

[integration/config@master] zuul: Add OATHAuth as a dependancy for EmailAuth

https://gerrit.wikimedia.org/r/1285498

Change #1285497 merged by jenkins-bot:

[mediawiki/extensions/OATHAuth@master] OATHUserRepository: Add a 'cheap' way to check if a user has 2FA enabled

https://gerrit.wikimedia.org/r/1285497

Change #1293837 had a related patch set uploaded (by Reedy; author: Reedy):

[mediawiki/extensions/OATHAuth@master] OATHUserRepository: Fixup userHas2FAEnabled description

https://gerrit.wikimedia.org/r/1293837

Change #1293837 merged by jenkins-bot:

[mediawiki/extensions/OATHAuth@master] OATHUserRepository: Fixup userHas2FAEnabled description

https://gerrit.wikimedia.org/r/1293837

Change #1298936 had a related patch set uploaded (by Reedy; author: Reedy):

[mediawiki/extensions/OATHAuth@REL1_46] OATHUserRepository: Add a 'cheap' way to check if a user has 2FA enabled

https://gerrit.wikimedia.org/r/1298936

Change #1298937 had a related patch set uploaded (by Reedy; author: Reedy):

[mediawiki/extensions/OATHAuth@REL1_46] OATHUserRepository: Fixup userHas2FAEnabled description

https://gerrit.wikimedia.org/r/1298937

Change #1298936 merged by jenkins-bot:

[mediawiki/extensions/OATHAuth@REL1_46] OATHUserRepository: Add a 'cheap' way to check if a user has 2FA enabled

https://gerrit.wikimedia.org/r/1298936

Change #1298937 merged by jenkins-bot:

[mediawiki/extensions/OATHAuth@REL1_46] OATHUserRepository: Fixup userHas2FAEnabled description

https://gerrit.wikimedia.org/r/1298937

Change #1298942 had a related patch set uploaded (by Reedy; author: Reedy):

[mediawiki/extensions/OATHAuth@master] OATHUserRepository: Cache 2FA status in WANObjectCache

https://gerrit.wikimedia.org/r/1298942