Page MenuHomePhabricator

Improve login workflow for Phacility instances
Closed, ResolvedPublic

Assigned To
Authored By
epriestley
Feb 4 2015, 2:35 PM
Referenced Files
F283133: Screen_Shot_2015-02-04_at_3.18.35_PM.png
Feb 5 2015, 12:11 AM
F283137: Screen_Shot_2015-02-04_at_3.30.08_PM.png
Feb 5 2015, 12:11 AM
F283180: Screen_Shot_2015-02-04_at_3.32.49_PM.png
Feb 5 2015, 12:11 AM
F283177: Screen_Shot_2015-02-04_at_4.02.54_PM.png
Feb 5 2015, 12:11 AM
F283148: Screen_Shot_2015-02-04_at_3.32.49_PM.png
Feb 5 2015, 12:11 AM
F283140: Screen_Shot_2015-02-04_at_3.18.35_PM.png
Feb 5 2015, 12:11 AM
F283142: Screen_Shot_2015-02-04_at_3.30.08_PM.png
Feb 5 2015, 12:11 AM

Description

To OAuth to a Phacility instance, you currently need to confirm through two separate dialogs. This is correct in the general case, but we could introduce something like a "trusted" flag to OAuthServer that would just grant users permissions without prompting.

  • The flag needs to be heavily locked down (probably CLI-only).
  • I need to make sure we can really get rid of the second dialog safely because of redirect/fragment attacks. I believe we can.
  • It would be nice to provide an IP whitelist for permitted clients. This would offer an additional barrier to an attacker escalating.

Event Timeline

epriestley raised the priority of this task from to Needs Triage.
epriestley updated the task description. (Show Details)
epriestley added a project: Phacility.
epriestley moved this task to Backlog on the Phacility board.
epriestley added a subscriber: epriestley.

The actual login screen on instances is silly, too. I think we can safely add a "default" sort of flag to providers to auto-select if there's only one oauth provider on an instance so you don't have to click the silly button.

I'm going to verify that doing this is safe from a security perspective, then hand it off to you.

Current workflow is three screens:

Screen One

Screen_Shot_2015-02-04_at_3.18.35_PM.png (619×1 px, 82 KB)

Screen Two

Screen_Shot_2015-02-04_at_3.30.08_PM.png (956×912 px, 133 KB)

Screen Three

Screen_Shot_2015-02-04_at_3.32.49_PM.png (956×912 px, 117 KB)


I think we should retain one of these screens the first time you login. Here's the attack I can perform if there is no user interaction at all required to log in:

  • I start an instance, evil.phacility.com.
  • I add you (my victim) to the instance.
  • I trick you into visiting a page which loads the login screen in a hidden iframe.
  • Since we've removed all the checks, the iframe redirects to admin.phacility.com, which authorizes you. admin.phacility.com redirects back to evil.phacility.com, which reads your data and shows you a login screen.
  • I export a backup of the data for my instance.
  • I can read your email (and a small amount of other personal information) out of the external_account table.

This seems bad enough to justify requiring a click to confirm that you want to join an instance. After initial approval, we can log you in directly in other cases, or we can just leave the screen. This is common in other OAuth implementations.


First of three parts is to remove this screen:

Screen_Shot_2015-02-04_at_3.18.35_PM.png (619×1 px, 82 KB)

Removing this screen (if we also remove the other screens, except make one of them one-time-only) allows an attacker to log a user into an instance, provided they are currently logged out but are logged in to admin.phacility.com, and already have an account on the instance. This does not seem meaningfully dangerous. It is possible it could disclose that the victim has an account (maybe: time the cost of making some request; try to log the user in; time the cost of making the request again; if it went up a lot because the logged-in version of the page is way more expensive, maybe that detects that they have an account). But this is a pretty targeted and generally useless-seeming attack. (It is also very rare for users to be logged in to the upstream but not to their instance.)

To remove this dialog, I think the cleanest approach is to add a checkbox to the Auth configuration, like:

  • Automatically login with this provider if it is the only available provider.

Then, on the login start page, check if there's exactly one provider with that flag set. If so, just redirect the user as though they had clicked the button.


Second part is this screen:

Screen_Shot_2015-02-04_at_3.30.08_PM.png (956×912 px, 133 KB)

I think we should keep this, but it would be nice to make it simpler:

  • We do not need an infinite-duration token and do not benefit from it. If the client doesn't request that scope (and we shouldn't), can we just hide the checkbox and always issue a temporary token?
  • If the user unchecks the user.whoami checkbox, nothing works anyway. We can just make this implicit in "allow ... access your Phabricator account data", since this is the minimal level of access that makes sense anyway. We also get this exception on uncheck, currently:

Screen_Shot_2015-02-04_at_4.02.54_PM.png (550×1 px, 130 KB)

So I think we should:

  • Don't prompt for inifinite tokens if the client didn't ask for them.
  • Make granting "user.whoami" implicit in granting any access at all.
  • Fix that exception, I guess.

Third part is this screen:

Screen_Shot_2015-02-04_at_3.32.49_PM.png (956×912 px, 117 KB)

This was added as part of D8517. Without it, attackers can steal OAuth tokens from a login provider by registering an OAuth server, then using it to redirect users from the login provider through their client and ultimately to their server.

This screen is safe to remove if we trust the server, and the servers we create are trustworthy. I think the simplest approach here is:

  • Add a "trusted" flag to OAuth servers.
  • Users can set it with bin/auth trust-oauth-server or similar (it should not be settable via the web UI).
  • We'll set it internally when we build the servers.
  • If an OAuth server has the flag set, it can safely just do the redirect on this screen instead of prompting the user.

That will leave us with one simple prompt confirming login to the instance, instead of three weird/complex screens. I think that's pretty reasonable.

If we want to refine things further, we can skip the prompt if: the OAuth server is trusted, and the user has already logged in before. But this won't make the first login experience any better, so I'm not sure it's worth it.

Let's start with that and see how it feels?

btrahan triaged this task as High priority.Feb 5 2015, 7:40 PM
epriestley added a commit: Restricted Diffusion Commit.Feb 7 2015, 3:18 PM