Page MenuHomePhabricator

API Portal: Discuss OAuth 2.0 scopes
Closed, ResolvedPublic

Description

Objectives
  • In the API Portal, present developers with an easily understandable set of scopes to choose from when creating clients
  • Tailor scopes so that when an app is requesting authorization from a user, the user feels like the scopes being requested are reasonable
  • In the API Portal, offer scopes that cover only the functionality provided by API Gateway APIs
  • If we need to change the set of offered scopes to account for new APIs added to the gateway, have this happen relatively infrequently so that we don't overwhelm developers with needing to recreate their clients
Background

In T249781, we mapped rights to the core REST API endpoints, but I now think that this was based on a mistaken interaction of the relationship between rights as used by the REST handlers and rights as applied to OAuth clients. What we're looking to determine here, is what to include on the API Portal's create client view.

Grant mapping

Grants that map to the functionality provided by the core REST and wikifeeds APIs (APIs for initial gateway launch):

  • basic (See question 1)
  • highvolume
  • editpage (See question 2)
  • editprotected
  • editmycssjs
  • editinterface (See question 3)
  • editsiteconfig
  • createeditmovepage
  • viewdeleted

Grants that do not map to functionality provided by those APIs and do not need to be offer via the Portal:

  • editmyoptions
  • uploadfile
  • uploadeditmovefile
  • patrol
  • rollback
  • blockusers
  • viewrestrictedlogs
  • delete
  • oversight
  • protect
  • viewmywatchlist
  • editmywatchlist
  • sendemail
  • createaccount
  • privateinfo
  • mergehistory
  • checkuser
  • shortenurls
  • globalblock
  • setglobalaccountstatus
  • oath
Questions
  1. Does the basic grant allow page editing?
  2. Because of the overlap, could we omit editpage in favor of createeditmovepage?
  3. Because of the overlap, could we omit editinterface in favor of editsiteconfig?
  4. How do grants correspond to the strings shown to users in authorization requests?
Grants to offer in the Portal (pending open questions)
  • basic
  • createeditmovepage
  • viewdeleted
  • editprotected
  • editmycssjs
  • highvolume
  • editsiteconfig

Related Objects

Event Timeline

Could you take a look at this when you have the chance?

I'd like to confirm I understand what we're talking about here.

My understanding of T249781 was that we would offer only two permission options when creating an OAuth2 client via the API Portal: "Read-only" and "Read/Write". This was intended as a convenience for the developer registering the OAuth2 client. However, because these are not actual grant types supported by the OAuth extension, the API Portal would map these two highly simplified options to actual MediaWiki grants. In other words, the "Read-only" and "Read/Write" would exist only on the API Portal's form for creating OAuth2 clients. Anywhere else you looked at an OAuth2 client (end user approving an application to access your account, developer/administrator browsing OAuth2 clients on meta, etc.) you would see a representation of the actual grants, rather than "Read-only" and "Read/Write".

Is the intention now to show a subset of the actual grants on the API Portal form for creating an OAuth2 client? (The full list of grants is indeed intimidating, no argument there.) Technically speaking, this seems like a straightforward change that really just affects the API Portal form (and related processing code).


Here are some unsolicited thoughts on the objectives from the task description. My commentary is shown in italics:

Objectives
  • In the API Portal, present developers with an easily understandable set of scopes to choose from when creating clients

Nothing we do with the real grants is going to be easily understandable to developers unfamiliar with MediaWiki. I'm not sure I understand what some of these things mean, and I work on MediaWiki full time. Presenting a subset helps, but I still wouldn't call it "easily understandable". I don't object to requiring developers to know what they're doing, but we should be clear that it does raise the bar a bit.

  • Tailor scopes so that when an app is requesting authorization from a user, the user feels like the scopes being requested are reasonable

Presenting more choices to the client developer allows them to more tightly tailor the scopes. If application developers actually use this properly, it should result in the user being presented with fewer choices. So this makes things better for end users at the expense of a little more effort by developers. That seems like a reasonable tradeoff. No objections here.

  • In the API Portal, offer scopes that cover only the functionality provided by API Gateway APIs

Okay

  • If we need to change the set of offered scopes to account for new APIs added to the gateway, have this happen relatively infrequently so that we don't overwhelm developers with needing to recreate their clients

We should avoid making existing APIs require new scopes. Doing so could force changed behavior on developers, and cause them to recreate their clients. On the other hand, offering new scopes because a new API needs them doesn't seem like a problem. The existing OAuth2 clients won't be affected, and should continue to function happily. If existing clients want to use the new APIs, then yeah, they may need to recreate their clients. But that's because they're adding new functionality, so that shouldn't be a big surprise. And it can happen at the pace determined by each individual application developer.

Final thought: as an implementation details, maybe we should have the set of offered scopes be in configuration rather than code. The Grant Permissions are in config anyway. To my knowledge, our production configuration related to these is stable. But as the behavior of these scopes is already in configuration anyway, it makes sense to me that our filtering should also be in configuration.


Now, I'll quit rambling about things you didn't ask about and answer your questions. :-)

Questions
  • Does the basic grant allow page editing?

My reading of https://meta.wikimedia.org/wiki/Special:ListGrants says "no". I haven't actually tried it to confirm.

  • Because of the overlap, could we omit editpage in favor of createeditmovepage?

Sure. That's in the same spirit as https://phabricator.wikimedia.org/T249781#6130902 . However, you lose a little granularity. What if someone's application doesn't require the additional rights conferred by createeditmovepage? By not offering editpage, we're encouraging them to violate the Principle of Least Privilege. In our initial plan, we decimated that principle by offering only two permission choices, and justified it as simplifying things for developers. (That is not a statement of judgement - I had no objection to that decision.) Now we're talking about abusing that principle only slightly, but we're still abusing it. Ultimately, we're limiting the choices available to application developers for the sake of simplicity. As the people doing the limiting, we have to strike the balance we think is correct. What makes me okay with all this is that developers who want to can always create finely-tuned clients on meta. So regardless of what we do or don't do here, we aren't taking away any functionality from developers.

  • Because of the overlap, could we omit editinterface in favor of editsiteconfig?

Sure. Same argument applies.

It looks to me like the keys used to select the string shown to the user are assembled from the array keys in Grant Permissions, as defined in https://gerrit.wikimedia.org/g/mediawiki/core/+/8c26ce9746bd57c8c7801c4c99b60cbb0cbc0703/includes/DefaultSettings.php#6234 and adjusted in production configuration.

I hope that helps.

Thanks, @BPirkle! I really appreciate your response! I understand that when a client is acting on behalf of a user (via the authorization code flow), the rights of the client are limited to the rights possessed by the user. However, I'm unsure about how that works when the client is not acting on behalf of a user (using the client credentials flow, for example).

  • If I register a client with the viewdeleted grant and use the client credentials flow, can that client view deleted pages?
  • If I register a client with the highvolume grant and use the client credentials flow, are edits made with that client marked as bot edits?
  • For a bot account in the bot group, does a corresponding client have to have the highvolume grant to be marked as a bot edit?

Thanks, @BPirkle! I really appreciate your response! I understand that when a client is acting on behalf of a user (via the authorization code flow), the rights of the client are limited to the rights possessed by the user. However, I'm unsure about how that works when the client is not acting on behalf of a user (using the client credentials flow, for example).

  • If I register a client with the viewdeleted grant and use the client credentials flow, can that client view deleted pages?

You used the word "pages", so I assume you're talking about endpoints under v1/page, like v1/page/{title}, v1/page/{title}/html, etc.

The answer is "no", but that doesn't have anything to do with it being client credentials. Hitting v1/page/{title} for a deleted page gives a 404 with content like:

{"messageTranslations":{"en":"The specified title (BDP424) does not exist"},"httpCode":404,"httpReason":"Not Found"}

Other /page REST API endpoints give similar behavior. I confirmed with an authorization_code client with all available grants created by my local wiki's Admin user (who has all available rights). Same behavior.

I assume that's at least close to what we should be doing. Hitting that page's url in the wiki via the browser doesn't display content either, even for a user with all available rights. However, it does display a message that they page has been deleted. Maybe we could/should return something more helpful from the REST API endpoints? Generally, a 404 is the correct thing for deleted content, even if there's no guarantee whether the content is deleted temporarily or permanently. But in our case, it the content is soft deleted. Maybe rather than rest_nonexistant_title, we should return a different message string? Those are product-ish questions, so they should probably go to @eprodromou . Also, I did not check what the Action API does for this, but it might provide a reasonable pattern to follow.

BTW, I went for the bonus points on this question and also tried /revision/{id}/bare. Same results: 404 on revisions belonging to deleted pages for any client that I tried, regardless of rights, grants, or flows. That's what I expected, but it was good to experimentally confirm it.

Answers to your other two questions will be forthcoming. I thought this comment was already long enough. :-)

  • If I register a client with the highvolume grant and use the client credentials flow, are edits made with that client marked as bot edits?
  • For a bot account in the bot group, does a corresponding client have to have the highvolume grant to be marked as a bot edit?

I tried a variety of ways and was unable to get an edit marked as as a bot edit regardless of what I did. I then hacked my local just to make sure I wasn't missing something, and succeeded in getting an edit marked as a bot edit. I hacked two things:

  1. commented out the rights check in EditPage::attemptSave: https://gerrit.wikimedia.org/g/mediawiki/core/+/84cacf83828b0f26ed761b66b5c9f4220c47367e/includes/EditPage.php#1743
  1. pass the "bot" flag to the Action API along with the other request params in UpdateHandler: https://gerrit.wikimedia.org/g/mediawiki/core/+/84cacf83828b0f26ed761b66b5c9f4220c47367e/includes/Rest/Handler/UpdateHandler.php#115

I suspect that #1 might not have been necessary if I'd gone back and tried a different combination of user and OAuth client, but I have no proof of that. I didn't bother, because #2 would have made that fail.

Here's what I think is happening: we implemented the Core REST API's page create/update endpoints as wrappers around the associated Action API functionality. The Action API accepts a "bot" parameter indicating whether or not to flag an edit as a bot edit (see https://www.mediawiki.org/wiki/API:Edit). In the Core REST API code that wraps the Action API, we don't pass the bot parameter to the Action API. Therefore, nothing we do regarding flows, grants, etc. is going to get an edit via the Core REST API marked as a bot edit.

It is possible I'm wrong, and that someone more familiar with bot edits, EditPage, and the Action API would have a different answer. As usual in MediaWiki, there's a lot going on and many ways things can be altered/overridden. But that's what it looks like from my review.

Final thought: the fact that it was necessary for you to ask these questions, and that I had to do a bunch of command line to find out, illustrates the need for a testing sandbox. It would be nice if you could have easily tried all this yourself in a friendly interface and instead asked "why aren't things being marked as bot edits". We should build a testing sandbox sometime.

@BPirkle I don't have anything useful to add around your answers though they were extremely interesting and I'll raise this ticket with @EvanProdromou to see if we need to address the behaviour but I wanted to pitch:

https://patchdemo.wmflabs.org/ as a means to sandbox - it does not contain the extensions or wikis we are working on BUT I was hoping to ask that team if we can add them.

Thank you, @BPirkle! I really appreciate these thorough answers!

After reading Bill's responses and chatting with Evan, I propose changing the scopes to:

  • Read - basic
  • Read/write - basic, createeditmovepage, editprotected

This set of scopes covers only the functionality offered by the API Gateway endpoints and avoids a situation where an end user is asked to authorized "high volume editing" and other advanced permissions unnecessarily.

Change 630943 had a related patch set uploaded (by Alex Paskulin; owner: Alex Paskulin):
[mediawiki/extensions/WikimediaApiPortalOAuth@master] oauth: Change scopes to reflect API functionality

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

Change 630943 merged by jenkins-bot:
[mediawiki/extensions/WikimediaApiPortalOAuth@master] oauth: Change scopes to reflect API functionality

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