m3api-oauth2 is an extension package for m3api, making it easy to make requests authenticated via OAuth 2.0.
Propose an OAuth 2.0 client on Special:OAuthConsumerRegistration/propose/oauth2,
load its credentials (e.g. from the process envirnoment) into an OAuthClient
instance,
and attach that to an m3api session in the request options:
import Session from 'm3api/node.js';
import { OAuthClient, initOAuthSession, completeOAuthSession } from 'm3api-oauth2';
const session = new Session( 'en.wikipedia.org', {}, {
userAgent: 'm3api-oauth2-README-example',
'm3api-oauth2/client': new OAuthClient(
process.env.OAUTH_CLIENT_ID,
process.env.OAUTH_CLIENT_SECRET,
),
} );
Initialize the m3api session as an OAuth session, and generate the authorization URL for the user:
console.log( await initOAuthSession( session ) );
Send the user to that URL (e.g. via a redirect from your application). When they choose to authorize your app, they will be redirected back to you; use that URL to finish setting up the OAuth session:
await completeOAuthSession( session, callbackUrl );
(The callbackUrl
should look like the URL you registered the OAuth client with,
plus a ?code
parameter generated by MediaWiki.)
Now you should be able to make requests using the OAuth session:
console.log( await session.request( {
action: 'query',
meta: 'userinfo',
} ) );
This example assumes that you can keep the original session
instance alive,
which may be true for a CLI utility, but probably not a web-based application.
You can serialize the OAuth session and store the result in the user session,
saved in some kind of session store:
const serialization = serializeOAuthSession( session );
// store serialization (or JSON.stringify( serialization )) somewhere
// ...next request...
// get serialization from somewhere (possibly via JSON.parse())
deserializeOAuthSession( session, serialization );
Note that you shouldn’t make the serialization directly available to the user (e.g., you shouldn’t put it directly in a cookie), since that would allow the user to extract the access token and impersonate your application. Use a session store instead, e.g. based on Redis if you’re on Wikimedia Toolforge.
MediaWiki also supports non-confidential clients, i.e. clients that are unable to keep a client secret, such as in-browser apps or mobile apps. Whether a client is confidential or not is specified when the client is registered.
MediaWiki still generates a client secret for non-confidential clients, and as far as this library is concerned, you can use the client with or without its client secret:
const client = new OAuthClient( clientId, clientSecret );
// or:
const client = new OAuthClient( clientId );
// both support:
const session = new Session( 'en.wikipedia.org', {}, {
'm3api-oauth2/client': client,
} );
Whether a non-confidential client should be used with or without its secret is currently up for discussion in T323867; note that without a client secret, the session currently cannot be refreshed (T323855), so in that case you would need to go through the authorization flow again after ca. four hours.
There are several different kinds of “session” relevant to this package; the documentation tries to use the following terms consistently:
- m3api session
-
An instance of the m3api
Session
class. Can be used to make API requests. - OAuth session
-
An m3api session that has been enhanced by this package. Any requests it makes (using the usual m3api methods,
request()
etc.) are authenticated using OAuth. A non-OAuth m3api session is transformed into an OAuth session using eitherinitOAuthSession()
(from scratch) ordeserializeOAuthSession()
(based on an existing serialization). - user session
-
Some kind of data store associated with the user of your application, usually provided by the web framework you use (e.g. express-session). You would use this to store the serialization of the session (
serializeOAuthSession()
), as well as any other data you like.
m3api-oauth2 is not compatible with all platforms supported by m3api;
specifically, it additionally requires support for dynamic imports,
which most browsers supported a handful of releases later than the static imports required by m3api.
It also requires the Web Crypto API methods crypto.getRandomValues()
and crypto.subtle.digest()
,
but they are available in all m3api-supported platforms.
Published under the ISC License. By contributing to this software, you agree to publish your contribution under the same license.