OAuth

From Wikitech

OAuth is a protocol that lets applications impersonate users in limited ways, after getting permission from those users. The public Wikimedia wikis use OAuth (provided by mw:Extension:OAuth) to allow users to offload editing tasks to external applications (usually, but not always, applications on Toolforge).

For a description of how OAuth works, and how to develop applications that use it, see mw:OAuth/For Developers. For a user manual, see mw:Help:OAuth. This page is focusing on operations concerns. Owner-only OAuth consumers are not discussed here; for the most part those can be thought of as a special kind of password, much like bot passwords.

Concepts

There are three participants to an OAuth workflow: the OAuth server (the wiki where the OAuth extension is installed), the consumer (the application using OAuth) and the user. The application developer registers the consumer (this usually requires manual review by OAuth admins, stewards, or staff(?), which tends to be cursory), which includes listing the permissions ("grants") the application can use. Users approve the consumer through a dialog on metawiki. After that, the application can act in the name of the user, but only with the permissions which both the user and the application have.

Data

The OAuth MediaWiki extension uses two tables: oauth_registered_consumer which stores data about consumers (applications using OAuth, more or less; although one application can have several consumers, mainly as a way of versioning) and oauth_accepted_consumer which stores data about the authorizations users give to consumers. See DB schema in gitiles.

The main OAuth installation is on metawiki; consumers registered there might be able to access all public Wikimedia wikis (although this might be restricted by the consumer settings). Wikitech has its own OAuth server, which is used by Cloud team tooling, e.g. Striker. Private wikis might have their own OAuth server (currently only stewardwiki does).

Security

During registration, the consumer gets an id (a 32-bit hexa string which is the public identifier for that consumer) and a secret key - these are referred to as the application token and secret. During user approval, the application receives an id and secret from the user (the access token/secret). All four values are needed to impersonate the given user. The application secret must be kept secret (e.g. it cannot be distributed with a mobile app), although it is usually not immediately exploitable by itself (see below). The access secret must also be kept secret; storing it in a private Toolforge DB or as a cookie in the user's browser is not ideal but OK (given the lack of better options) as long as the application does not have particularly scary permissions.

As part of the consumer approval process, various security-related settings are approved (and cannot be changed later): what permissions can the application use (but only if the user it impersonates also has them), what wikis it can act on, what is the return URL to send users to when they approve the application (this limits how much a stolen application token + secret can be misused). The owner can also restrict the IP or range the application is allowed to make requests from (this one can be changed later).

We don't approve consumers with highly security-sensitive permissions (e.g. Javascript editing). We don't usually approve consumers with admin permissions (e.g. page deletion) but exceptions exist. We sometimes approve consumers with no limit on the return URL when they have very minimal privileges otherwise (these are used as examples in code tutorials).

See also Wikitech/OAuth on officewiki.

Management

Consumer management happens via https://meta.wikimedia.org/wiki/Special:OAuthManageConsumers/<consumer id> (that's also the best way to inspect settings, the other interfaces don't show everything). Users with approriate rights can browse existing consumers at m:Special:OAuthManageConsumers/approved without needing to know the specific consumer id.

In case of a data leak, or an application misbehaving, go to m:Special:OAuthManageConsumers and set the consumer to disabled (you need to be in the oauthadmin group, or steward or staff(?)). That should prevent any kind of abuse of credentials (reject all API requests made with those credentials), and prevent new users from granting permission to the application. The action can be undone. There's also a "disable and suppress" option in case the registration mechanism itself is abused, e.g. by putting private information in a consumer name.

If a single user is misbehaving and abusing an application, they can simply be blocked on the wiki by name; IP/range blocks don't work though, as the wiki will see the tool IP. Popular tools are expected to provide their own anti-abuse mechanisms - if they don't, and are repeatedly abused, just disable the tool and tell the owner to improve it.

The admin interface only allows disabling/reenabling; most consumer settings can't be changed (the developer needs to create a new consumer), the owner can reset the consumer secret or change what IP range the application is allowed to make requests from. Revoking permission from a specific user can only be done by that user, from their preferences. As always, it's best to avoid direct DB manipulation, but it should be reasonably safe if really needed for some reason (short of changing ids/keys).

Many things use OAuth; disabling it on the main cluster or wikitech is extremely disruptive. If you need to do that anyway, set $wmgUseOAuth = false in that wiki/cluster's config. Alternatively, you can set $wgMWOAuthReadOnly = true (will disallow any changes to OAuth consumers, but not using existing consumers) or $wgMWOauthDisabledApiModules[] = "ApiModuleClassName" (will prevent that API module from being used with any OAuth credentials).

Logging

Consumer state changes (proposal, approval, disabling etc) are logged in the (public) wiki log: m:Special:Log/mwoauthconsumer. They are also logged to the OAuth channel on Logstash. Authorizations (users giving permission to an application) are also logged to the OAuth channel. Authentication (ie. when an API request uses OAuth credentials) is logged to the session channel with the debug log level (which in practice means not logged).

Actions performed via OAuth have an OAuth CID: <id> change tag on them. Note this is the consumer ID, not the consumer key. You can find it via the links in m:Special:OAuthListConsumers, or in the database. To get a quick estimate of how important an OAuth tool is, you can look at the change_tag_def.ctd_count table field for that change tag to get the total number of times it was used on the given wiki.

Debugging

Show the contents of an OAuth 2 bearer token

$ mwscript shell.php metawiki
>>> $jwt = "..."
>>> Firebase\JWT\JWT::decode($jwt, new Firebase\JWT\Key($wgOAuth2PublicKey, 'RS256'))