Project

General

Profile

Actions

Feature #12900

closed

Two-factor authentication

Added by Boone Gorges almost 4 years ago. Updated over 3 years ago.

Status:
Resolved
Priority name:
Normal
Assignee:
Category name:
Security
Target version:
Start date:
2020-06-05
Due date:
% Done:

0%

Estimated time:
Deployment actions:

Description

Two-factor authentication makes logins more secure by ensuring that a stolen password is insufficient for account access. We should explore implementing it on the Commons.

2FA usually takes one of the following forms:
1. A dedicated 2FA physical token device
2. A 2FA smartphone app (Google Authenticator, Duo, etc)
3. SMS

These are ordered from most-secure to least-secure. 2 is probably a good compromise between ease-of-use and security, and there are ready-made tools for it. See eg https://wordpress.org/plugins/two-factor/, which is built by a number of noted security folks in the WordPress sphere.

Some considerations:
- We'd likely want to make 2FA optional but recommended.
- Introducing 2FA is likely to increase support request somewhat, especially if users lose access to their 2FA device. Before launch, we should have protocols and support boilerplate in place for resets.
- We'd need integration into registration as well as user settings. The existing plugins do this in the WP dashboard, but we may want to move it into the front-end to integrate with existing registration and password-reset tools.
- We'll need Help documentation.

Do others have thoughts about this project before we move forward with some technical discovery?

Ray, I'm tentatively assigning you to take the lead on implementation, though I'm happy to work together on it.


Files

bp-2fa.png (25 KB) bp-2fa.png Raymond Hoh, 2020-09-01 11:51 PM
bp-2fa-2.png (36.9 KB) bp-2fa-2.png Raymond Hoh, 2020-10-30 02:54 PM
bp-2fa-security-keys.gif (92.9 KB) bp-2fa-security-keys.gif Raymond Hoh, 2020-10-30 02:54 PM
Screen Shot 2020-11-03 at 9.15.07 AM.png (86.5 KB) Screen Shot 2020-11-03 at 9.15.07 AM.png Interface once a key has been added under My Settings Jeremy Felt, 2020-11-03 12:24 PM
Screen Shot 2020-11-03 at 9.17.11 AM.png (229 KB) Screen Shot 2020-11-03 at 9.17.11 AM.png Message on wp-login.php that did not appear to receive the key's signal Jeremy Felt, 2020-11-03 12:24 PM
Screen Shot 2020-11-03 at 9.23.04 AM.png (279 KB) Screen Shot 2020-11-03 at 9.23.04 AM.png Console errors on wp-login (that may not be related) Jeremy Felt, 2020-11-03 12:24 PM
enabled-primary-behavior.mov (8.85 MB) enabled-primary-behavior.mov Colin McDonald, 2020-11-24 12:24 PM
Actions #1

Updated by Luke Waltzer almost 4 years ago

If we proceed with this—and we should talk through whether this may be a solution to a problem that we don't have but are anticipating—perhaps the solution could allow one-time 2FA per device (or is time limited in some generous way). I access the Commons on a number of devices, and the login is often glitchy using my password manager (I haven't gotten around to opening a ticket on that yet, but will). Want to take extra care not to introduce any pain.

Also, heads up that CUNY CIS is moving towards 2FA for all CUNY-hosted services. Might make sense to align with their practices, once they're defined, to minimize confusion. Can you keep you posted on that conversation but you might also check with Lihua.

Actions #2

Updated by Boone Gorges almost 4 years ago

Thanks for the comments, Luke.

this may be a solution to a problem that we don't have but are anticipating

We've fielded two separate instances in the last three days of user accounts being compromised, very likely because of shared passwords breached on other sites. That's what's driving this conversation.

Also, heads up that CUNY CIS is moving towards 2FA for all CUNY-hosted services. Might make sense to align with their practices, once they're defined, to minimize confusion. Can you keep you posted on that conversation but you might also check with Lihua.

We're in conversation at a high level, but this is great to know. It's definitely worth investigating whether coordination is possible (and wise).

Actions #3

Updated by Raymond Hoh almost 4 years ago

If we are looking at single-sign on with CUNY and if their SSO will support 2FA, we should look at implementation in #4635 instead.

Otherwise, if we want to add 2FA at the WordPress level, the mentioned 2FA plugin looks good at a glance. We should do a custom BuddyPress integration on a user's "Settings" page. I think 2FA can be set up after initial registration. We shouldn't complicate the registration process with a 2FA step IMO.

Actions #4

Updated by Boone Gorges almost 4 years ago

SSO with a central CUNY system is a long way off, and may never happen. So I don't think we should hold off more immediate improvements in expectation of consolidating authentication.

Agreed with your point about registration. Let's see if other team members want to chime in before we begin implementing anything.

Actions #5

Updated by Colin McDonald over 3 years ago

From a few conversations in calls and emails, I think we should table work on this until we can all discuss as a wider group, hopefully during our first meeting of the new semester in a couple of weeks (schedule info to come soon). Perhaps we can still come up with a plan forward to work on for the fall.

Actions #6

Updated by Raymond Hoh over 3 years ago

I've integrated the Two Factor plugin into the BuddyPress user's settings page.

You can test out how the plugin works on cdev by visiting your "My Settings > General" page. Apart from the "Two-factor Authentication" heading and descriptive paragraph that follows, everything else is rendered from the Two Factor plugin.

I've attached a screenshot:

There are options to enable Email, Time Based One-Time Password (TOTP), FIDO U2F Security Keys and Backup Verification Codes for 2FA.

If you want to do basic testing, you can select the Email or Backup Verification Code options. For TOTP, you can use any TOTP authenticator app on your mobile device to scan the QR code. If you are using Android, I can recommend Aegis or andOTP. Let me know if anyone needs any other help here. I haven't tested the FIDO U2F option since I don't have access to a physical U2F USB security key. If anyone does have one, feel free to test.

I think there are a few things we can tweak from a usability perspective:
- The labels and descriptions the plugin uses can be a little jargony. For example, the FIDO U2F Security Keys description says "requires an HTTPS connection". This isn't really useful to the end-user. Also, the "Security Keys" section doesn't need to be displayed if it isn't enabled as a 2FA option.
- When entering in the authentication code for the TOTP option, you have to manually click on the "Submit" button. Pressing enter will not submit the code. Also, successfully saving the TOTP option does not automatically enable it. You have to manually enable TOTP and select it as your primary 2FA option afterwards.

I will probably create some pull requests upstream to the Two Factor plugin to address these issues.

Actions #7

Updated by Colin McDonald over 3 years ago

To follow up on Friday's group meeting, we decided to move ahead with this implementation of the Two Factor plugin. It would be nice though as Ray suggests to make the text and a few of the more technical elements as user-friendly as possible. Ray, do you want to keep us posted in the ticket here what you're able to adjust via pull requests to the plugin team, and then we can figure out what else we want to add on our end?

Actions #8

Updated by Raymond Hoh over 3 years ago

Just to update, I've made the changes I mentioned above.

This is what the 2FA screen looks like now when on your "My Settings" page:

Changes since last time:

  • Changed "FIDO U2F Security Keys" label to "Security Keys". The former is too jargony.
  • Changed "Backup Verification Codes (Single Use)" label to "Recovery Codes". "Recovery Codes" seems to be more in use on other sites which use 2FA like Github and Microsoft.
  • Added more descriptive text to the "Security Keys" and "Recovery Codes" sections.
  • Changed the BuddyPress "Settings > General" tab to "Settings > Security". I feel this is more descriptive of this page now. "General" is too broad.
  • "Security Keys" block only shows up if it is enabled. (Opened an upstream PR here .) (GIF)
  • Pressing the "Enter" key can submit the TOTP authentication code now. (Opened an upstream PR here .)
  • Clicking on the 2FA provider name will select it under the "Enabled" checkbox. (Opened an upstream PR here .)
  • Deselecting a 2FA provider will remove it as the primary 2FA option if it was previously selected. Also, if another 2FA provider was enabled during unchecking, that provider will be selected as the new primary 2FA option. This was done to address this problem.
  • Removed "You can find FIDO U2F Security Key devices for sale from here" link under the "Security Keys" section as that sounds like we're upselling something. The link just goes to a Google support article, which doesn't explain where you can buy a key without additional clicks anyway.

I also outlined a list of challenges I had while integrating the upstream two-factor plugin to BuddyPress. I mentioned this to the developers here.

Another issue worth addressing in a future release is: https://github.com/WordPress/two-factor/issues/292. If a 2FA option is selected, the user should also set up some recovery codes. Otherwise, if the user loses access to their 2FA device, then it will not be possible to login without asking someone with admin access to reset their 2FA option for them. I don't think this is a dealbreaker for our first iteration of this, but it's something to keep in mind.


I've added Jeremy as a watcher as he mentioned on the last call that he has access to a USB security key. Jeremy, I'm about to email you with instructions to access our development site as well as some testing info.

Let me know if you are able to access the development site, as well as any questions or concerns about the 2FA flow. Thanks!

Actions #9

Updated by Jeremy Felt over 3 years ago

I just tested things out with a YubiKey and it looks like it almost works.

I was able to add the key to my profile. Doing so initiated a little browser hint in Firefox that indicated I should insert and tap my key.

After setting the key, I logged out, cleared my cookies and cache, and then logged in again. The first screen had me enter username/password as normal. The next screen asked me to tap my security key, but gave no indication that it was receiving a signal. The key is lighting up as if it's attempting to work, but the browser did not appear to be receiving it.

I have a couple console errors, but I'm not sure they're related. One is a CORS issue with Zendesk and the other I've seen before. Though "inputtools" is a little suspicious.

I've attached a few screenshots. Happy to continue testing as needed!

Actions #10

Updated by Raymond Hoh over 3 years ago

Thanks for testing, Jeremy!

Can I ask you to try the following suggestion? https://github.com/WordPress/two-factor/issues/211#issuecomment-460654063

PS: Try hold for about 3 seconds, not just tap.

If that works, I'll adjust the message to add this tidbit. Can you also test on a Chromium browser to see if the problem might be Firefox-related?

Also, thanks for the screenshot of the Security Keys table. I was able to fix up some of the styling to better match the 2FA page in the admin area.

Actions #11

Updated by Jeremy Felt over 3 years ago

No luck - I tried holding for >3 seconds in both Firefox and Chrome and there's no indication it's seeing anything.

I poked at the source of the page a bit and it seems like a couple things are missing:

The message about the key and `u2f_response` hidden input field is there as expected as part of the overall 2FA validation form the plugin provides: https://github.com/WordPress/two-factor/blob/736473edf5ff6d2fed18ba2406c772f30950343c/class-two-factor-core.php#L608-L620

Nothing about the plugin code makes it seem like those scripts are enqueued in any unusual way, so I'm not sure what would be stopping them.

Actions #12

Updated by Raymond Hoh over 3 years ago

Thanks for the debugging, Jeremy!

This gave me a clue. We use a customized login template, which uses the current theme's template. This setup involves removing all footer scripts from being enqueued, except for ones we manually enqueue ourselves:
https://github.com/cuny-academic-commons/cac/blob/07a1e37b850dc0147c7815c2a9b250e3f0ab6f1e/wp-content/mu-plugins/cac-login-template.php#L385-L388

This is done to stop unnecessary external assets that other plugins might add to the footer from being loaded. If you're interested about the code, check out #12108 for more info.

Anyway, I've just manually enqueued the fido-u2f-login script when we're on the U2F login page on cdev. Can you give it another try? Let me know if it works or not.

Actions #13

Updated by Jeremy Felt over 3 years ago

I think we're close. Your answer sounds correct, but I'm not sure it's working yet. :)

Still no luck with the key, but I don't see the fido-u2f-api or fido-u2f-login scripts enqueued yet. I'm not sure if something else funky happens when everything is unenqueued?

Actions #14

Updated by Raymond Hoh over 3 years ago

I think we're close. Your answer sounds correct, but I'm not sure it's working yet. :)

Found the bug. The two-factor plugin doesn't tell you which 2FA provider is currently running on the login page, so I tried to code a workaround by declaring a global flag during one of the strings that appears on the login page. The bug was I hooked into the wrong filter! The U2F script should now be properly enqueued.

Jeremy, can you try to login with your security key again on the development site when you have a moment? Thanks!

Actions #15

Updated by Jeremy Felt over 3 years ago

Hey, there we go! Works great in both Chrome and Firefox.

Actions #16

Updated by Colin McDonald over 3 years ago

Just passing on a bit of testing feedback from Anthony Wheeler: "The Recovery Codes take a few seconds to populate. I don’t really know if there’s anything that can be done about that, but my instinct was to start clicking other things around the page (like the Enable/Primary checkboxes, which were unresponsive while waiting for the codes) to make sure it was working."

Ray, maybe you're familiar with this? I tested myself and it did take a second or two to see the codes. Maybe there's a way to add some sort of loading wheel or interstitial?

Actions #17

Updated by Colin McDonald over 3 years ago

A couple more things from testing - can we make it a bit more clear that this is all optional? Maybe just by making the top header "Two-Factor Authentication (Optional)"?

Also, we're noticing some odd behavior/interplay between the Enabled and Primary check and radio buttons. See the attached screencast.

If I select something as Primary, should it automatically check the Enabled box? Also, it seems like unchecking something as Enabled can sometimes change what's been designated as Primary, when the two choices don't seem to be related. Or perhaps I'm missing something there.

Actions #18

Updated by Raymond Hoh over 3 years ago

I tested myself and it did take a second or two to see the codes. Maybe there's a way to add some sort of loading wheel or interstitial?

Done. I've added a spinner to the "Generate New Recovery Codes" button when it is clicked:

A couple more things from testing - can we make it a bit more clear that this is all optional? Maybe just by making the top header "Two-Factor Authentication (Optional)"?

I think adding the word "Optional" implies that 2FA isn't needed. While that is technically true, I'd prefer that we do not use the word so prominently for the heading.

Perhaps we can modify the description below the heading to:

Two-factor authentication adds an optional, additional layer of security to your account by requiring more than your password to log in.

If we think that using "(Optional)" in the header is better, then I'll make the change though.

If I select something as Primary, should it automatically check the Enabled box?

Yes, it should. I didn't sufficiently test the "Primary" column. I was mostly testing with clicking on the 2FA name itself. This should now be fixed on cdev.

Also, we're noticing some odd behavior/interplay between the Enabled and Primary check and radio buttons. See the attached screencast.

Thanks for the screencast, Colin. Most of this should be solved with the fix to select the Enabled box when clicking on a Primary option.

About the Recovery Codes option, I tried to make an exemption so it will not automatically be selected as Primary because this option really shouldn't be a selectable, primary option (see https://github.com/WordPress/two-factor/issues/292). With that being said, most of the wonkiness should be gone now. Latest changes are up on cdev. Let me know if anyone else encounters any problems with the selection.


I've also added a documentation draft on the Help site: https://help.commons.gc.cuny.edu/?page_id=9429&preview=true. Feel free to make any changes.

Once the article is live, the page should be added to the personalize-menu so it shows up in the sidebar.

Actions #19

Updated by Raymond Hoh over 3 years ago

  • Status changed from New to In Progress
  • Target version changed from Future release to 1.18.0
Actions #20

Updated by Colin McDonald over 3 years ago

Thanks for this, Ray. The spinner on recovery codes looks good to me in cdev, and I'm fine with changing the description line to include "optional" as you did rather than the heading. Good point there on the prominence.

On checkbox/radiobox selection stuff, it's working fine for me now to select a new option as Primary and then see the Enabled box also checked automatically. But when I just check Enabled for a new option, it's also selecting that as primary automatically. So if for example I have Email as Enabled and Primary but then check Security Keys as Enabled, it makes it also Primary when maybe I still want Email to be Primary. Does that make sense, or should I screencast again?

Thanks too on the documentation, I'll let you know if we need anything else there.

Actions #21

Updated by Raymond Hoh over 3 years ago

So if for example I have Email as Enabled and Primary but then check Security Keys as Enabled, it makes it also Primary when maybe I still want Email to be Primary.

Good catch, Colin. This should be fixed on cdev. Enabling another provider should no longer check the new provider as Primary if there is already a Primary provider selected.

Actions #22

Updated by Colin McDonald over 3 years ago

Thanks Ray, this is all looking/working great now!

Actions #23

Updated by Raymond Hoh over 3 years ago

  • Status changed from In Progress to Staged for Production Release

I've added the two-factor plugin and the companion bp-two-factor plugin to the codebase: https://github.com/cuny-academic-commons/cac/compare/323c222...185e877

Boone, both plugins should be network-activated. I've also updated the ACTION_REQUIRED wiki entry noting this.

Actions #24

Updated by Boone Gorges over 3 years ago

  • Status changed from Staged for Production Release to Resolved
Actions

Also available in: Atom PDF