Page MenuHomePhabricator

Logging in at another wiki than WebAuth was set up fails
Open, Stalled, Needs TriagePublic

Description

I just noticed I can't login to any other wiki besides cswiki (where I set WebAuth up). The site says my token was not recognized.

Event Timeline

Urbanecm renamed this task from Logging in at another wiki than Authy was setuped fails to Logging in at another wiki than WebAuth was setuped fails.Feb 2 2020, 3:22 PM
Urbanecm updated the task description. (Show Details)
DannyS712 renamed this task from Logging in at another wiki than WebAuth was setuped fails to Logging in at another wiki than WebAuth was set up fails.Feb 2 2020, 4:15 PM

This is fun. Confirmed on beta...

I guess related to using $wgServer, as that obviously then won't work elsewhere...

	/**
	 * Authenticator constructor.
	 * @param OATHUserRepository $userRepo
	 * @param IModule $module
	 * @param OATHUser|null $oathUser
	 * @param IContextSource $context
	 * @param LoggerInterface $logger
	 * @param WebRequest $request
	 * @throws ConfigException
	 */
	protected function __construct( $userRepo, $module, $oathUser, $context, $logger, $request ) {
		$this->userRepo = $userRepo;
		$this->module = $module;
		$this->oathUser = $oathUser;
		$this->context = $context;
		$this->logger = $logger;
		$this->request = $request;

		// Get the domain of the wiki - used as issuer
		$server = $context->getConfig()->get( 'Server' );
		$serverBits = wfParseUrl( $server );
		if ( $serverBits !== false ) {
			$this->serverId = $serverBits['host'];
		}
	}

Looking at where it's used...

		$publicKeyCredentialRequestOptions = new PublicKeyCredentialRequestOptions(
			random_bytes( 32 ),
			static::CLIENT_ACTION_TIMEOUT,
			$this->serverId,
			$registeredPublicKeyCredentialDescriptors,
			PublicKeyCredentialRequestOptions::USER_VERIFICATION_REQUIREMENT_PREFERRED,
			$extensions
		);

and

		$rpEntity = new PublicKeyCredentialRpEntity( $rpName, $this->serverId );

https://www.w3.org/TR/webauthn/#dom-publickeycredentialrequestoptions-rpid

rpId, of type USVString
This OPTIONAL member specifies the relying party identifier claimed by the caller. If omitted, its value will be the CredentialsContainer object’s relevant settings object's origin's effective domain.

https://www.w3.org/TR/webauthn/#relying-party-identifier

Hello, i dont understand why $wgServer wouldn't work, could you explain? When user tries to authenticate it takes the $wgServer of the wiki request was made on, and later compares that to the domain from the request URL. Why would this be different, unless the request is not started on one wiki and completed on another. Thanks

If we dont specify the server id, it will fall back to $request->getUri()->getHost() which would come to the same value.

Hello, i dont understand why $wgServer wouldn't work, could you explain? When user tries to authenticate it takes the $wgServer of the wiki request was made on, and later compares that to the domain from the request URL. Why would this be different, unless the request is not started on one wiki and completed on another. Thanks

Is the value of $wgServer not used as part of generating publicKeyCredentialId/credentialPublicKey which end up in the database?

If not, it's slightly curious that $wgServer and $wgSitename are used in parts of the authentication/registration proxy... Then things don't work on a different wiki to the one that webauthn was enrolled in, as they are going to be different

If we dont specify the server id, it will fall back to $request->getUri()->getHost() which would come to the same value.

I didn't say to not specify it.


Anyway, the problem is fairly easy to replicate. As per the report, if you enable webauthn on one wiki, it won't let you login with another...

From what i remember, and from a quick search now, relying party is only used for "signing" the requests during registration/authentication processes, so that the server knows that it was the one that the request originated from. It should not be saved to the db.

Im not sure how I would replicate the multi-wiki setup to debug this on. Could you tell me more about how this setup works?

Im not sure how I would replicate the multi-wiki setup to debug this on. Could you tell me more about how this setup works?

Multiple wikis point at the same shared database table. Nothing fancy or complex. Same works fine for OATH, so t would seem something in Webauthn is varying on some sort of state/config

It certainly shouldn’t need CentralAuth or similar actually setting up, just the config to point to the same db/table for both wikis

Question depends where it varies. Enrolling then changing the url of the wiki may suffice if it’s something like that

Access to the servers of the beta cluster can be provided too

[...]
Im not sure how I would replicate the multi-wiki setup to debug this on. Could you tell me more about how this setup works?

Following https://www.mediawiki.org/wiki/Manual:Shared_database should work IMO.

Ah, ok, tought it was more complex :) Thank you guys, ill give it a shot

I have tested this and can confirm the issue. RP id (domain in this case) is baked into the credential so there is no way to use the same key on multiple domains currently.
What we could do is t make relying party id configurable, so that all wikis using the same DB could set the same key, and therfore use the same keys between each other.

I tried the solution i suggested before, and actually it wont work. Browser checks the RP id agains the current domain and wont allow any operations if the two dont match. I dont have an idea now on how to make this work.

What is the setup where you are using this. Are all wikis on mediawiki.org domain, with just different subdomains or on completely different domains. If they are all just different subdomains, we can use the configuration solution.

We have Webauthn enabled on WMF sites, as a production feature. You should be able to enable it at en.wikipedia.org and login at ca.wikimedia.org.

Change 571520 had a related patch set uploaded (by ItSpiderman; owner: ItSpiderman):
[mediawiki/extensions/WebAuthn@master] Make relying party data configurable

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

From what i discovered until now, that is not possible, limitation built in webauthn standard. You get an attestation in the key for the specific relying party with whom the key was registered.

Hmm, can we make one wiki our primary authentificator, and somehow make all keys registered there, and also authenticated? It would mean user will get redirected somewhere, but at least it would work.

[...]
Im not sure how I would replicate the multi-wiki setup to debug this on. Could you tell me more about how this setup works?

Following https://www.mediawiki.org/wiki/Manual:Shared_database should work IMO.

I doubt it.

Just setting $wgOATHAuthDatabase would be enough (and put the oathauth_users table into that database) - as long as the two wikis both point at the same database. In theory, it could be in the local database for one, and a remote one for another

From what i discovered until now, that is not possible, limitation built in webauthn standard. You get an attestation in the key for the specific relying party with whom the key was registered.

So your patch above doesn't work then? (ignoring the test failures)

Hmm, can we make one wiki our primary authentificator, and somehow make all keys registered there, and also authenticated? It would mean user will get redirected somewhere, but at least it would work.

It'd be quite a change of the workflow... But we could use login.wikimedia.org, as it's kinda what it exists for. Redirect to there for the 2FA parts, and then send them back. It does add complexity, as it would be needed for enrolling, disabling and also authing.

Which potentially becomes a bigger problem on mobile apps...

Non SUL wikis don't need this obviously, as they have their own 2FA table

I need to have a look how many people have enabled it... But it might be worth disabling the extension on SUL wikis in production for now as it can break the expected workflow, even if the workaround is trivial enough

The patch above will let you manually configure the relying party name and id (domain). It can be set to the root part of the domain, to make WebAuthn work for multiple sub-domains, while without it, it can be used on one specific subdomain only. So, it does add some functionality, but still not as much as you would need.

Also, beware, that all single-domain-specific keys (all keys that are registered so far), cannot be used anymore if configuration related to the RP is changed. This would require all users to re-register their keys.

Also, beware, that all single-domain-specific keys (all keys that are registered so far), cannot be used anymore if configuration related to the RP is changed. This would require all users to re-register their keys.

So they're going to have to un-register them first... Or have them forcibly removed after the config change to go with the patch is deployed...

Change 571520 merged by jenkins-bot:
[mediawiki/extensions/WebAuthn@master] Make relying party data configurable

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

Also, beware, that all single-domain-specific keys (all keys that are registered so far), cannot be used anymore if configuration related to the RP is changed. This would require all users to re-register their keys.

So they're going to have to un-register them first... Or have them forcibly removed after the config change to go with the patch is deployed...

And while that might help some wiki where every wiki is a subdomain of the same domain... I don't think there's much benefit rolling this config out for Wikimedia wikis as it solves some of the problem, but causes a problem of having to force users to re-register... Then a second time for T248339: Decide how to deal with WebAuthn login/registration flow on Wikimedia wikis in future... I'd rather we just have to force that once to get over the breaking change, rather than once for a half fix, and then again for a proper fix

This is a limitation of the current standard, see upstream discussion at https://github.com/w3c/webauthn/issues/1372. The existing solutions are redirecting to a central domain for webauthn auth or loading a page with webauthn auth from a central domain in an iframe.

Just adding some more relevant terms to this task so it can be found more easily via search – this limitation of two-factor authentication is mentioned in the current WikimediaMessages version of the wikimedia-webauthn-ui-login-prompt message on the login page, which states (since T248367):

Please note that you will need to login to the same wiki where you originally registered your verification device

This is a limitation of the current standard, see upstream discussion at https://github.com/w3c/webauthn/issues/1372.

This is a core security feature of WebAuthn - credentials are origin-bound (or registrable-domain-bound) so e.g. a phishing website set up on a typosquatter domain cannot get them (unlike say TOTP where such phishing is a standard attack technique).

Redirecting to the central login domain for WebAuthn authentication would add some complexity to the extension, but not too much I think (e.g. store challenge in shared store under a random token, store that token in local session, redirect to central wiki with token in URL, update shared store on successful authentication, redirect back). AuthManager can already handle such redirects. The extension would have to expose a bunch of hooks to CentralAuth, or duplicate some configuration (such as the central wiki and the central store).

Iframes are a little more elegant (in that the user doesn't see an unfamiliar website in the URL bar) but loginwiki would have to allow iframing which has some security implications (probably all browsers that support webauthn also support the frame-ancestors CSP directive so it could be limited to the wiki farm, but even so an XSS attack could probably make use of it), iframes require javascript, and this is not supported out of the box by MediaWiki so either we'd have to extend AuthManager or do the authentication flow outside it.

Wrt existing keys, I imagine same-wiki-only keys and loginwiki-keys would have to be different authentication types in WebAuthn, with a migration process that sends notification to people to create a new key and delete the old one.

We'll have to do something very similar for the password for in CentralAuth, for T348388: Use central login wiki for login (SUL3). Maybe there should be a proxy mechanism for MediaWiki login that works globally, not on the level of the individual authentication providers.

during testing for T358771 we discovered that login also fails when logging in on the same wiki using a new device.

this is due to tokens missing the correct $credentialTransports / $credentialDescriptor (e.g. "hybrid" ) -- see the ticket for the root cause.