Page MenuHomePhabricator

Provide "authenticate" endpoint for regular users
Closed, DeclinedPublic

Description

MediaWiki currently provides only "authorize" endpoint, but this means that users have to confirm the application again and again. By providing "authenticate" endpoint, users could just "sign in" and get immediately redirected back, without having to confirm anything, if all permissions are still same, and user has not revoked the application.

See Twitter documentation for more information: https://dev.twitter.com/docs/api/1/get/oauth/authenticate


Version: unspecified
Severity: normal

Details

Reference
bz69232

Event Timeline

bzimport raised the priority of this task from to Medium.Nov 22 2014, 3:42 AM
bzimport set Reference to bz69232.
bzimport added a subscriber: Unknown Object (MLST).

Is anyone from OAuth extension at Wikimania 2014? I am here, we could discuss this in person here.

I think Brad and Aaron are both there. I'm not.

I forgot to comment on this one, but I'm solidly maybe on this. Silent redirects make me a little nervous since they've been used, along with other vulnerabilities, to silently exploit the other vulnerability. Requiring a user click makes another vulnerability much harder to exploit.. but I can definitely see the use in several scenarios.

At the least, I've been thinking about setting up an alternate endpoint for Consumers that are only meant for login, and the text would say something more like "Login to XXX" instead of asking for authorization.

(In reply to Chris Steipp from comment #2)

I forgot to comment on this one, but I'm solidly maybe on this. Silent
redirects make me a little nervous since they've been used, along with other
vulnerabilities, to silently exploit the other vulnerability. Requiring a
user click makes another vulnerability much harder to exploit.. but I can
definitely see the use in several scenarios.

The use of this in conjunction with other vulnerabilities doesn't make it inherently dangerous. When oauth is only being used for login to a connected application I don't see where the danger lies. When the oauth authorization includes some elevated privileges then I can see the worry, however, couldn't the authenticate endpoint provide a session without any access beyond the granting of a login?

The reason I ask is because we are using oauth for phabricator login and it's really not at all convenient or user friendly to ask for authorization each time.

b5bedd8 added the endpoint, but only for authonly/authonlyprivate grants. It would be a trivial change to relax that. Given that @csteipp was ambivalent on this, it should probably be your call, @dpatrick.

See also T91801: Support a more user friendly "re-authentication" flow for returning users which proposes a slightly more cautious approach: do require users to click through again but make the dialog simpler and make it mention they already authorized this consumer in the past.

This seems like a good idea to me... If I need to make changes in phabricator to use the new endpoint then I'd gladly do so.

Perhaps the automatic redirect could be validated against a URL whitelist in order to reduce the possibility for abuse...

I still don't understand what abuses are here? I mean, the rest f the world uses OAuth with "authentication". Why they do not have to worry about this type of abuse, or what is a difference in trade-offs and threat models?

I think it would be really great if Wikimedia OAuth could be equally used as other OAuths. A really global and trusted OAuth service to compete with closed ones like Facebook and Google.

Can you explain how precisely would the attack work? To my understanding of OAuth, attacker cannot just redirect to "authenticate" endpoint to get the user to be logged in. They have to have app key as well. And the main way they can have that is if they are running inside the app's JS namespace. But if they run there (and can continue running after redirect back) then we have bigger issues anyway and the can effectively do whatever the app can do anyway. And if the app is used to use OAuth, then users are used to click through anyway. So attacker can just go through dialog to authenticate the user.

I think it is really dangerous to believe that just because we show a dialog that protects users. Users become habituated to such dialogs. In fact they might become less secure if we are popping them all the time and not just when something is different (app wants to ask for more permissions than last time, app tries to redirect to a different callback location prefix).

I would propose that we have "authentication" endpoint, and then we prompt only if permissions or callback location prefix changes, or if for example 120 days passed from last prompt. If everything is the same, then we do not prompt the user. By requiring that callback prefix is the same (minus query strings) we can really limit any abuses only to apps themselves, or anything which hacked apps themselves, which is then more or less then already problematic.

This seems like a good idea to me... If I need to make changes in phabricator to use the new endpoint then I'd gladly do so.

Phabricator probably uses the authonly grant, so just replace authorize with authenticate in the URL and it should work.

I think it is really dangerous to believe that just because we show a dialog that protects users. Users become habituated to such dialogs. In fact they might become less secure if we are popping them all the time and not just when something is different (app wants to ask for more permissions than last time, app tries to redirect to a different callback location prefix).

Agreed.

I would propose that we have "authentication" endpoint, and then we prompt only if permissions or callback location prefix changes, or if for example 120 days passed from last prompt. If everything is the same, then we do not prompt the user. By requiring that callback prefix is the same (minus query strings) we can really limit any abuses only to apps themselves, or anything which hacked apps themselves, which is then more or less then already problematic.

I like this proposal, I think this would address the concerns raised by @csteipp.

Eww. That would mean we have to keep track of when the consumer was last used, which would mean DB writes on all API requests. It wouldn't have much security impact either, gaining access to users who did use the service in the last 120 days is still plenty. (IMO the popups don't have much security impact in the first place; it is not hard to social engineer someone into re-authorizing a service that they did authorize in the past.)

You do not have to update database on all API requests, only on calls to authenticate and related OAuth calls (or are you calling OAuth calls API requests)? In any way, I do not mind having no expiration time, this is just if somebody really wants some dialogs. I am for less of them anyway. :-)

Also, this can be implemented more efficiently. When you issue a token you remember when you did that. And you revoke it after 120 days, which then prompts the dialog to get it anyway.

You do not have to update database on all API requests, only on calls to authenticate and related OAuth calls (or are you calling OAuth calls API requests)?

Oh OK, you said last prompt, not last time using that consumer to authenticate an API request. That wouldn't be too bad.
I would still prefer just getting rid of manual reauthentications though.

Also, this can be implemented more efficiently. When you issue a token you remember when you did that. And you revoke it after 120 days, which then prompts the dialog to get it anyway.

That would limit how long the OAuth application can act in your name. We currently don't have a time limit for that. I don't know if adding one would be desirable (although all the OAuth apps I can think of are interactive and so wouldn't be affected).

I would still prefer just getting rid of manual reauthentications though.

I would agree. Until there are a change in permissions asked or something. But, because maybe not everyone agree with that I am pointing out that there are also some middle points we can do between showing dialog every time and occasionally.

We currently don't have a time limit for that.

Hm, all API providers I know about (Facebook, Twitter) do expire their OAuth tokens at some point (you even get expiration time).

But I do not really care about that. We can also have unlimited time. Or very long time.

Is this something a community contribution could help with?

The task as it is written is a duplicate of T88757: Add way for OAuth apps to only authenticate (no other valid rights) IMO (which has been resolved in 2015). For OAuth 1 it is limited to consumers which only have one of the authentication-only grants, for OAuth 2 I don't think that's the case. We could probably lift the restriction for OAuth 1.

That said I feed the authentication endpoint is something of an anti-pattern. Most apps should just store the access token in a cookie, and do an API request to verify if it's still valid, instead of redirecting the user, which is slower and more error-prone. That was discouraged in the past because all Toolforge tools shared the same origin, but they don't anymore, so I'm not sure there is a good reason to regularly send the user to reauthenticate.

Hm, all API providers I know about (Facebook, Twitter) do expire their OAuth tokens at some point (you even get expiration time).

Maybe we should, too. But that should happen via access token expiration (which is a standard OAuth thing, and already supported, just configured off for OAuth 1 on Wikimedia wikis), not some custom mechanism.

Since I opened that issue I learned more about OIDC and I think there is no need really for authenticate endpoint anymore. authorize and access_token endpoints currently are good enough. I think what throw me off is that (at least at the time, I have not checked recently) is that it looked like there is no way to get automatically redirected back to the app if user is still signed-in into the Mediawiki instance AND has already authorized the app. Other OIDC providers just redirect back. But Mediawiki (at the time at least) always showed the authorization dialog every time. So one click sign-in flow was less fluid than one would like to have.

So maybe the question of this issue is: does Mediawiki ODIC implementation supports prompt and max_age parameters? With them you can control what happens if user is or is not signed-in into the Mediawiki instance. For example, with prompt=login you request that user has to login no matter what. While prompt=none requires no dialog to be shown with error returned to the app if user is not signed-in and access token cannot be issued to the app without user interaction.

Ideally, unless promp=login or prompt=select_account or prompt=consent is specified, the Mediawiki ODIC implementation should redirect automatically back to the client if user is signed-in into the Mediawiki instance and app has already been authorized.

That said I feed the authentication endpoint is something of an anti-pattern. Most apps should just store the access token in a cookie, and do an API request to verify if it's still valid, instead of redirecting the user, which is slower and more error-prone.

I agree. When opening this issue I had the issue that every time user clicked "sign-in with Wikipedia" button, they had to confirm once more to authorize the app. So one extra click. I assumed that the issue is lack of authenticate endpoint, but now I know that this is just question of how OIDC provider is configured. Do you know if this has changed for Wikipedia?

The OAuth extension doesn't support any OIDC parameters (see T254063: OAuth extension should support OpenID Connect). I agree that would be a good way forward.

I agree. Let's close this issue then and track OIDC parameters in the issue you referenced.