Page MenuHomePhabricator

Store client hint mapping rows for login events
Closed, ResolvedPublic3 Estimated Story Points

Description

We should collect Client Hints data when users log in. This will allows CheckUsers to match this data against other accounts as part of a CheckUser investigation.

We currently send client hint header data when a POST request is made to login. We should remove the headers sent on this page, as the data that is sent is not collected. This will be replaced with a use of the JavaScript API.

Acceptance criteria
  • When a user fails to log in, CheckUser creates rows in cu_useragent_clienthints_map if the browser supports Client Hints
  • When a user logs in, CheckUser creates rows in cu_useragent_clienthints_map if the browser supports Client Hints

Event Timeline

Change #1087526 had a related patch set uploaded (by Dreamy Jazz; author: Dreamy Jazz):

[mediawiki/extensions/CheckUser@master] [Very WIP] Collect Client Hints data on login attempts

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

Change #1087934 had a related patch set uploaded (by Dreamy Jazz; author: Dreamy Jazz):

[mediawiki/extensions/CheckUser@master] Support private log events in Client Hints REST API endpoint

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

Change #1087934 merged by jenkins-bot:

[mediawiki/extensions/CheckUser@master] Support private log events in Client Hints REST API endpoint

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

Change #1087526 merged by jenkins-bot:

[mediawiki/extensions/CheckUser@master] Collect Client Hints data on failed login attempts

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

There is some additional complication for logins that are successful, as we need to call the API on the page loaded after the login has occurred. In most cases, that is the page specified in the 'return to' part of the URL. Plus, for MediaWiki-extensions-CentralAuth installations there may be some level of redirecting around to sign-in to other wiki farms.

Maybe putting the ID somewhere in the session variables could work, so that it's persisted through redirects and can be sent once the user is finished with the login process.

There is some additional complication for logins that are successful, as we need to call the API on the page loaded after the login has occurred. In most cases, that is the page specified in the 'return to' part of the URL. Plus, for MediaWiki-extensions-CentralAuth installations there may be some level of redirecting around to sign-in to other wiki farms.

Maybe putting the ID somewhere in the session variables could work, so that it's persisted through redirects and can be sent once the user is finished with the login process.

My suggesion is that we rework CheckUserClientHintsSpecialPages to allow for a list of enabled methods, and change "Userlogin": "js" to "Userlogin": [ "js", "header" ]. That would prompt the user's browser to send client hints data on POST requests when it visits Special:Userlogin. Then, we need to work out how to get the private event ID recorded in the client hints table:

  • We could implement the onUserLoginComplete hook or the onAuthManagerLoginAuthenticateAudit hook, and list the clienthints handler after the CheckUserPrivateEvents handler. That would ensure that the row is created before our handler runs.
  • We could subscribe to the onCheckUserInsertPrivateEventRow hook in CheckUser in the clienthints handler

While mixing header and JS API usage is not ideal in some regards, using the header for obtaining client hints seems like the much simpler and more robust option here.

If we really want to use the JS API, then we need to probably do something like set a property on the user's session (e.g. wgCheckUserPrivateEventLoginId), and in BeforePageDisplay check if this property is set and export it to the client side, and then have our client hints JS code make a POST request using the ID. The REST handler would then also be responsible for clearing the wgCheckUserPrivateEventLoginId in the user's session.

There is some additional complication for logins that are successful, as we need to call the API on the page loaded after the login has occurred. In most cases, that is the page specified in the 'return to' part of the URL. Plus, for MediaWiki-extensions-CentralAuth installations there may be some level of redirecting around to sign-in to other wiki farms.

Maybe putting the ID somewhere in the session variables could work, so that it's persisted through redirects and can be sent once the user is finished with the login process.

My suggesion is that we rework CheckUserClientHintsSpecialPages to allow for a list of enabled methods, and change "Userlogin": "js" to "Userlogin": [ "js", "header" ]. That would prompt the user's browser to send client hints data on POST requests when it visits Special:Userlogin. Then, we need to work out how to get the private event ID recorded in the client hints table:

  • We could implement the onUserLoginComplete hook or the onAuthManagerLoginAuthenticateAudit hook, and list the clienthints handler after the CheckUserPrivateEvents handler. That would ensure that the row is created before our handler runs.
  • We could subscribe to the onCheckUserInsertPrivateEventRow hook in CheckUser in the clienthints handler

While mixing header and JS API usage is not ideal in some regards, using the header for obtaining client hints seems like the much simpler and more robust option here.

If we really want to use the JS API, then we need to probably do something like set a property on the user's session (e.g. wgCheckUserPrivateEventLoginId), and in BeforePageDisplay check if this property is set and export it to the client side, and then have our client hints JS code make a POST request using the ID. The REST handler would then also be responsible for clearing the wgCheckUserPrivateEventLoginId in the user's session.

Thanks for the thoughts. I'll proceed with the header idea for just a successful login. I think I can place the code in CheckUserInsert like we have for setting the private event ID for the failed login attempts.

Change #1090902 had a related patch set uploaded (by Dreamy Jazz; author: Dreamy Jazz):

[mediawiki/extensions/CheckUser@master] [Very WIP] Collect client hints data for successful logins

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

Change #1091587 had a related patch set uploaded (by Kosta Harlan; author: Kosta Harlan):

[mediawiki/extensions/CheckUser@master] client hints: Add selenium test for logins

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

This is ready for QA. Please see the acceptance criteria for what to review.

Change #1090902 merged by jenkins-bot:

[mediawiki/extensions/CheckUser@master] Collect client hints data for successful logins

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

Change #1091587 merged by jenkins-bot:

[mediawiki/extensions/CheckUser@master] client hints: Add selenium test for logins

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

dom_walden subscribed.

I see client hints being stored for both failed and successfully logins.

Test environment: local docker CheckUser 2.5 (1d4e003) 07:23, 18 November 2024.