Page MenuHomePhabricator

OAuth 2.0 non-confidential clients cannot use refresh tokens
Open, Needs TriagePublic

Description

MediaWiki-extensions-OAuth supports non-confidential clients, which can get an access token based on only their client ID. However, those clients can’t refresh the access tokens – they get a refresh token, but trying to use it will yield an authentication error. Since the access token has the same TTL as for confidential clients (14400 seconds), non-confidential clients effectively have to repeat the authorization flow every four hours if they want to continue making requests on behalf of a user.

This is a limitation inherited from the underlying league/oauth2-server package, where you can see the difference between auth code and refresh token handlers:

AuthCodeGrant.php
// Only validate the client if it is confidential
if ($client->isConfidential()) {
    $this->validateClient($request);
}
RefreshTokenGrant.php
// Validate request
$client = $this->validateClient($request);

It’s tracked upstream as issue #1073, but I thought it would be useful to have a task on Phabricator too. (Note that Extension:OAuth and mediawiki/vendor.git currently use a custom “9.0.0-alpha” version of the library, so even if the library implements this feature, switching to that release version might not be trivial depending on how much it diverges from the version we currently use.)

Event Timeline

Although MediaWiki still generates a secret key for non-confidential OAuth 2.0 consumers (idk why), and if you use that secret key, you can still successfully use the refresh token.

On the one hand, that means you’re using the non-confidential client exactly like a confidential one, which seems kind of pointless.

But on the other hand… I guess you could just treat the client secret of a non-confidential client as another piece of public information, and publish it together with the client ID?

There's some discussion here - the behavior of using refresh tokens with public clients is not super well-defined in the spec, but it's reasonable to expect the refresh_token grant to work without the (known to be insecure) client authentication in the case of public clients. But it's not something we'd want to fork upstream over, since clients can just use the client secret and everything will work fine, so this seems like a non-issue to me (other than maybe clarifying the documentation).