OAuth/For Developers

This page explains how to develop applications that can integrate with a wiki running Extension:OAuth (an extension which turns MediaWiki into an OAuth server) to securely request permission to act on the user's behalf.

If you are developing a bot or similar application where the same consumer is always used with the same user account, you might prefer the simpler owner-only consumers.

OAuth in a nutshell
OAuth allows an application to request permission from a user to act through that user's wiki account, without knowing the user's password, and without being able to do everything the user could (e.g. the app might be able to edit articles but not delete them, so even users with extended permissions can safely use OAuth-enabled tools).

This happens via the OAuth 1.0a protocol, and has three components: OAuth is a widely used open standard (you can see it on sites like Google or Facebook or Github, e.g. when using accounts at those sites to log in elsewhere). It is not to be confused with OATH (a second-factor authentication protocol, commonly known as "type the six numbers you see on your mobile app", now enabled on Wikimedia sites) and OpenID Connect (an authentication protocol based on OAuth 2.0 - the OAuth MediaWiki extension does include a somewhat OpenID-like custom protocol for determining user identity though).
 * 1) The developer must register the application (often called "consumer" in the OAuth terminology) on the wiki, possibly go through some sort of review process, and will receive some credentials.
 * 2) When a user wants to use it, the application must initiate an authorization process. This will involve sending the user to a special page on the wiki, which will display an authorization dialog. If the user accepts, the application will receive another set of credentials (which are specific to that user, and can be revoked by the user at any time).
 * 3) When the application actually needs to make an action (API request) on the user's behalf, it can combine the credentials received in steps 1 and 2 to sign the request.

For a slightly larger nutshell, see these slides.

Registration
To register a new OAuth consumer, submit the form at. Try to give sufficient information about the application for admins and users to decide whether it can be trusted. URLs to places with more information (such as the application itself, the source code or on-wiki documentation) can be useful.

Besides the descriptive ones, the fields have the following meaning:
 * This consumer is for use only by : for owner-only consumers (which do not need to be reviewed or authorized but are only usable by yourself)

After registration, you'll receive the credentials needed to use OAuth. You will be able to use it immediately with your own user account (this is meant for testing); others will only be able to use it once it is approved by an administrator.
 * callback URL: the URL where the user return after authorization is checked against this. (This is an extra layer of security against an attacker trying to steal credentials during authorization.) If the "use as prefix" option is enabled, the URL must start with this (the check is dumb so make sure to add at least a  after the domain name), otherwise it must be an exact match.
 * Applicable project (for wiki farms only): you can limit the application to a single wiki or have it work everywhere.
 * Types of grants / Applicable grants: the permissions needed by your application (be conservative). The actual permissions will be an intersection of this and what perimssions the user has. At this time, the user must authorize all permissions together (T59505).
 * Allowed IP ranges: OAuth requests not matching this will be rejected. (This is an optional extra layer of security against an attacker stealing your application's credentials and trying to impersonate it.) One of the few settings that you'll be able to change later.
 * Public RSA key: public key used by your application for signing requests. You can just leave this empty (most applications do) to use a slightly simpler shared-secret mechanism instead. One of the few settings that you'll be able to change later.

If you have changed your mind, you can disable the application under.

Authorization
When registering the application, you receive two pieces of credentials: the application token (a public ID for the application) and the application secret (sort of like a password). To be able to identify a user or make API requests in their name, you need to get another set of credentials (these ones specific to that user): the access token and access secret. To get them, you need to go through the authorization process, which consists of three steps: The access token and secret is what you'll need to sign API requests. The request token and secret is not useful anymore and can be discarded. The access token will remain valid indefinitely, unless the user revokes it. (If you prefer not to store it, you can just repeat the authorization process at any time though.)
 * 1) Get a request token from the wiki by sending a GET request to , signed with the application key and secret, with the callback URL (where the user will be sent after a successful authorization) passed as the   query parameter (if you have set a constant URL at registration, the value of the parameter must be  ). If you are successful, the response will be a JSON object with   and   fields - the request token and request secret. (If not, it will have an   field.)
 * 2) Ask the user to authorize the application by sending them to , with the application token and request token passed as query parameters (  and  , respectively). The user will see an authorization dialog with some basic information about the application and the list of grants, and can decide to authorize or cancel.
 * 3) If the user did choose to authorize, they will be redirected to the callback URL you have given (at registration, or as an URL parameter in step 1). A query parameter called   will contain the verification code that you can use to exchange the request token and secret for the access token and secret. To do this, send a request to   which includes the   parameter you just received and is signed with the application token and secret and the request token and secret. The response will contain the access token/secret (in the same format as the request token/secret in step 1).

Applications which only need minimal privileges (have been registered as User identity verification only) can use  instead of   in step 2. This works the same way but the user will only see the authorization dialog if they have not authorized this application before; otherwise the authorization will silently succeed.

Chances are whatever language/framework you are using will have a library to support this procedure so you don't have to implement it manually - each step will be a single function call. See below for examples.

Making requests on the user's behalf
To take advantage of the authorization, requests have to be signed with the application token/secret and access token/secret. When that's successfully done, the wiki will treat the request as if it was made by the authorizing user. Only API requests can be made via OAuth, with one exception (see next section). Certain API modules which would not make sense with OAuth (such as login/logout) or would allow privilege escalation (such as the centralauthtoken API) are disabled.

Applications which need minimal privileges (have been registered as User identity verification only) cannot use the API at all.

Identifying the user
The OAuth extension includes a custom protocol (similar to OpenID Connect) for authenticating the user. To user this, send a signed OAuth request to ; the response will be a JWT (a signed JSON object) including the name and ID of the user and various key information (such as their user groups and whether they are blocked; also the email address if the application was registered with the right grant type). This is more secure than using the API (e.g. the userinfo module) for authentication, which could be subject to man-in-the-middle attacks; always use this if you need to identify a user! Also, make sure you properly validate the JWT (there are many libraries which can help with that).

Security benefits and trade-offs

 * Unlike password-based authentication, the protocol prevents any man-in-the-middle attack even if the wiki does not require HTTPS: all interactions between MediaWiki and the application are signed with either a shared secret (using HMAC-SHA1), or a public key (RSA). HTTPS is still required for certain steps though (for obtaining the shared secret in the second step of authorization when not using RSA, and during app registration).
 * Actions via OAuth happen under the user's name but will be tagged with the application's name as well so rogue applications can be identified. Wiki admins can revoke the application's permissions (and thus bar it from any further action) if needed.
 * The user can can revoke the permission of the application to use that specific user account if they don't like how it works or don't trust it anymore. Unlike a password change, this is not disruptive for the user.
 * Sufficiently flexible applications might allow users to circumvent IP blocks (since MediaWiki will see the IP of the application server, not that of the user). This can be handled the same way proxies are, by trusting XFF headers set by the application (see T159889 for some limitations).

Intended Users

 * Websites that want to take actions on MediaWiki on behalf of their users
 * Bots
 * Websites that want to use MediaWiki as an identity provider for authentication (using the extension's /identity method, which is not standard OAuth)
 * But not...
 * Desktop applications (the Consumer Secret needs to be secret!). Some alternatives are being considered. See past discussions:

Application Approval

 * Wiki administrators will verify that OAuth applications are written by reputable developers, and the developers are intending to use OAuth correctly.
 * See the draft guidelines for apps on meta
 * Application developers must apply to have their application (Consumer) approved at meta:Special:OAuthConsumerRegistration/propose
 * A user with the oauth-admin right must approve the application (currently users in the oauthadmin group)
 * Your MediaWiki user can authorize your app while waiting for approval, so as a developer, you can start integrating your app immediately, without waiting for approval (you'll just have to get approval before other users can authorize your app)

Browse approved and proposed applications

 * meta:Special:OAuthListConsumers

Attached Application Responsibility

 * Establish user's session
 * Special:OAuth/initiate - get a temporary (request) token
 * Redirect the user's browser to Special:Oauth/authorize?oauth_token= &oauth_consumer_key=
 * The user will be redirected back the the url you registered
 * Special:OAuth/token – get the authorized (access) token for this user
 * Set an Authorization: header when calling api.php with oauth_version, oauth_nonce, oauth_timestamp, oauth_consumer_key, oauth_token, oauth_signature_method, oauth_signature

Developing
OAuth is now available in your MediaWiki-Vagrant development environment. Add the oauth role, and your wiki will be able to authorize OAuth apps.

Avoid repetitive login prompts
If your application doesn't persist sessions on the user-end, you might be repetitively prompting them to go through the OAuth approval screen. There's a better way! Instead of hitting

as the redirect in the second leg of the handshake, you can hit

instead. This won't prompt the user to approve your application but instead just directly reach your callback url after a redirect.

Note: This only works when:
 * The user has already authorized your application at least once before.
 * If the application has not been authorized previously the normal dialog will be seen.
 * Your tool has access to either "Authentication only with access to real name and email address via Special:OAuth/identify, no API access." or "Authentication only, no API access." grants.

PHP demo cli client with pre-shared secret

 * OAuth Hello World – easy to understand demo application written in PHP

PHP demo cli client with RSA keys
Before Starting:

Golang demo cli client with HMAC
Before you begin:

Python
Libraries:
 * flask-mwoauth, a Flask blueprint to run OAuth against MediaWiki's Extension:OAuth (See tutorial: My first Flask OAuth tool)
 * MediaWiki-OAuth (mwoauth), on top of requests-oauthlib
 * Mediawiki backend for python-social-auth (Example tutorial: My first Django OAuth tool)

Ruby: OmniAuth strategy
For Ruby, you can use this MediaWiki strategy for OmniAuth (available under the MIT License): https://github.com/timwaters/omniauth-mediawiki also available as a gem: https://rubygems.org/gems/omniauth-mediawiki

Express
If you're using Express JS using OAuth is pretty straightforward thanks to the npm modules passport-mediawiki-oauth and oauth-fetch-json. The former will help you effortlessly add login via MediaWiki to your application whereas the latter will allow you to make authenticated requests to the API.

Weekipedia, A full scale React.js port of the Wikipedia mobile site uses both.