Page MenuHomePhabricator

API UsageException when saving a collection to a page
Closed, ResolvedPublic

Description

From [[WP:VPT]]: http://en.wikipedia.org/w/index.php?diff=455038876

Unexpected non-MediaWiki exception encountered, of type "UsageException"
badtoken: Invalid token

#0 /usr/local/apache/common-local/php-1.18/includes/api/ApiBase.php(1205): ApiBase->dieUsage('Invalid token', 'badtoken')
#1 /usr/local/apache/common-local/php-1.18/includes/api/ApiMain.php(590): ApiBase->dieUsageMsg('sessionfailure')
#2 /usr/local/apache/common-local/php-1.18/includes/api/ApiMain.php(678): ApiMain->setupModule()
#3 /usr/local/apache/common-local/php-1.18/includes/api/ApiMain.php(340): ApiMain->executeAction()
#4 /usr/local/apache/common-local/php-1.18/extensions/Collection/Collection.body.php(867): ApiMain->execute()
#5 /usr/local/apache/common-local/php-1.18/extensions/Collection/Collection.body.php(225): SpecialCollection->saveCollection(Object(Title), false)
#6 /usr/local/apache/common-local/php-1.18/includes/SpecialPageFactory.php(460): SpecialCollection->execute(NULL)
#7 /usr/local/apache/common-local/php-1.18/includes/Wiki.php(224): SpecialPageFactory::executePath(Object(Title), Object(RequestContext))
#8 /usr/local/apache/common-local/php-1.18/includes/Wiki.php(624): MediaWiki->performRequest()
#9 /usr/local/apache/common-local/php-1.18/includes/Wiki.php(531): MediaWiki->main()
#10 /usr/local/apache/common-local/php-1.18/index.php(57): MediaWiki->run()
#11 /usr/local/apache/common-local/live-1.5/index.php(3): require('/usr/local/apac...')
#12 {main}


Version: unspecified
Severity: blocker
OS: Mac OS X 10.7
Platform: Macintosh

Details

Reference
bz31613
TitleReferenceAuthorSource BranchDest Branch
Avoid InvalidArgumentException on workboards when "Other Assignee" custom field undefinedrepos/phabricator/phabricator!4aklapperaklapper/T336135wmf/stable
Customize query in GitLab

Event Timeline

bzimport raised the priority of this task from to Unbreak Now!.Nov 21 2014, 11:52 PM
bzimport set Reference to bz31613.
bzimport added a subscriber: Unknown Object (MLST).

Diff seems unrelated. Try http://en.wikipedia.org/w/index.php?title=Wikipedia:Village_pump_%28technical%29&oldid=455088498#Error_when_attempting_to_create_new_book

Relevant code:

$req = new FauxRequest( array(
'action' => 'edit',
'title' => $title->getPrefixedText(),
'text' => $articleText,
'token' => $wgUser->editToken(),
), true );
$api = new ApiMain( $req, true );

jamesmikedupont wrote:

This affects me as well.

  • Bug 31953 has been marked as a duplicate of this bug. ***

As far as I can see, there is a logical problem in $wgUser->matchEditToken(). (includes/User.php L3228)

public function matchEditToken( $val, $salt = '', $request = null ) {

$sessionToken = $this->editToken( $salt, $request );
    if ( $val != $sessionToken ) {
        wfDebug( "User::matchEditToken: broken session data\n" \
    );
}
return $val == $sessionToken;

}

The token ($val) has to be inserted in the request, but $sessionToken is hashed with the request. Therefore, the token inserted in the request can NEVER match the original $wgUser->editToken().

It's not hashed with the entire request. $request is just passed through so that getEditToken() can do $token = $request->getSessionData( 'wsEditToken' ); (line 3194)

It's very unlikely that there is a logic error in matchEditToken(), or there'd be a heck of a lot more things breaking.

Bumping priority since it was seen in Bug 31821

You are right Roan. This is not the problem.

After digging a little deeper I found that the $request parameter that is handed to matchEditToken() is the FauxRequest. This FauxRequest does not contain 'wsEditToken' and so getEditToken() generates a new token with every call.

I don't know what would be the right way to fix this. It works if I set $request = null in matchEditToken() but this seems like short-circuiting the check.

I cannot commit files from the includes directory, but this patch might fix the problem:

Index: includes/User.php

  • includes/User.php (revision 100951)

+++ includes/User.php (working copy)
@@ -3184,7 +3184,7 @@

    • @return String The new edit token */ public function getEditToken( $salt = '', $request = null ) {
  • if ( $request == null ) {

+ if ( $request == null || get_class($request) == 'FauxRequest') {

			$request = $this->getRequest();
		}

What exactly is passing a FauxRequest to editToken()?

The FauxRequest is created in /extensions/Collection/Collection.body.php(867).

The FauxRequest is passed on from ApiMain->setupModule() (in ApiMain.php:591):
if ( !$this->getUser()->matchEditToken( $moduleParams['token'], $salt, $this->getRequest() ) ) {

The problem is that $this->getRequest() does retrieve the FauxRequest not $wgRequest.

Hmph, this kind of sucks. I guess we could either change ApiMain to obtain the session data from $wgRequest instead of the provided request, or require that the caller provide the session data in the FauxRequest. The latter is something you can easily do in Collection by using

new FauxRequest( array( your parameters here ), true, $_SESSION )

ApiMain is extracting query and session data from the request data it's provided in it's context and using that to secure the edit action. Collection is providing faux request data and saying there's no session data.

Looks to me like the correct way to do this is definitely for Collection to provide the session data to the api, or to use a proper internal api for editing instead of using the web use intended api.

Integrating $_SESSION as Roan suggested is no problem.

@daniel: The collection extension currently implements the API as described in http://www.mediawiki.org/wiki/API:Calling_internally
If there is a new/better way to create new pages from an extension, the documentation should be updated.

(In reply to comment #13)

Integrating $_SESSION as Roan suggested is no problem.

@daniel: The collection extension currently implements the API as described in
http://www.mediawiki.org/wiki/API:Calling_internally
If there is a new/better way to create new pages from an extension, the
documentation should be updated.

That's just a documentation page on how to call the api internally if you choose to. Namely if you want to use things like the query api internally. It doesn't even mention editing besides how to handle edit tokens.

The 'other' or rather usual way extensions end up trying to make edits is using WikiPage::doEdit or the EditPage class itself.

Not sure how good the state of that all is though to be honest. There are extra checks that EditPage goes and hacks into itself that might actually belong in doEdit.

That said, it's not like Collection is bothering to check for things like if a page is actually saved at all.

Also side note, it's making a bad use of Article. All it's doing is checking for existence, if that's all you want you should be using Title.
It'll break less when we kill off Article in our ideal world.

I applied the patch from Roan in r101149 and fixed the immediate problem.

Patches for further improvements as suggested by Daniel are welcome.

konjahman wrote:

Although this bug has been given the status of "resolved fixed" I got the below error today:

Unexpected non-MediaWiki exception encountered, of type "UsageException"
badtoken: Invalid token

#0 /usr/local/apache/common-local/php-1.18/includes/api/ApiBase.php(1205): ApiBase->dieUsage('Invalid token', 'badtoken')
#1 /usr/local/apache/common-local/php-1.18/includes/api/ApiMain.php(590): ApiBase->dieUsageMsg('sessionfailure')
#2 /usr/local/apache/common-local/php-1.18/includes/api/ApiMain.php(678): ApiMain->setupModule()
#3 /usr/local/apache/common-local/php-1.18/includes/api/ApiMain.php(340): ApiMain->executeAction()
#4 /usr/local/apache/common-local/php-1.18/extensions/Collection/Collection.body.php(867): ApiMain->execute()
#5 /usr/local/apache/common-local/php-1.18/extensions/Collection/Collection.body.php(225): SpecialCollection->saveCollection(Object(Title), false)
#6 /usr/local/apache/common-local/php-1.18/includes/SpecialPageFactory.php(460): SpecialCollection->execute(NULL)
#7 /usr/local/apache/common-local/php-1.18/includes/Wiki.php(224): SpecialPageFactory::executePath(Object(Title), Object(RequestContext))
#8 /usr/local/apache/common-local/php-1.18/includes/Wiki.php(624): MediaWiki->performRequest()
#9 /usr/local/apache/common-local/php-1.18/includes/Wiki.php(531): MediaWiki->main()
#10 /usr/local/apache/common-local/php-1.18/index.php(57): MediaWiki->run()
#11 /usr/local/apache/common-local/live-1.5/index.php(3): require('/usr/local/apac...')
#12 {main}

(In reply to comment #16)

Although this bug has been given the status of "resolved fixed" I got the below
error today:

Unexpected non-MediaWiki exception encountered, of type "UsageException"
badtoken: Invalid token

#0 /usr/local/apache/common-local/php-1.18/includes/api/ApiBase.php(1205):
ApiBase->dieUsage('Invalid token', 'badtoken')
#1 /usr/local/apache/common-local/php-1.18/includes/api/ApiMain.php(590):
ApiBase->dieUsageMsg('sessionfailure')
#2 /usr/local/apache/common-local/php-1.18/includes/api/ApiMain.php(678):
ApiMain->setupModule()
#3 /usr/local/apache/common-local/php-1.18/includes/api/ApiMain.php(340):
ApiMain->executeAction()
#4
/usr/local/apache/common-local/php-1.18/extensions/Collection/Collection.body.php(867):
ApiMain->execute()
#5
/usr/local/apache/common-local/php-1.18/extensions/Collection/Collection.body.php(225):
SpecialCollection->saveCollection(Object(Title), false)
#6
/usr/local/apache/common-local/php-1.18/includes/SpecialPageFactory.php(460):
SpecialCollection->execute(NULL)
#7 /usr/local/apache/common-local/php-1.18/includes/Wiki.php(224):
SpecialPageFactory::executePath(Object(Title), Object(RequestContext))
#8 /usr/local/apache/common-local/php-1.18/includes/Wiki.php(624):
MediaWiki->performRequest()
#9 /usr/local/apache/common-local/php-1.18/includes/Wiki.php(531):
MediaWiki->main()
#10 /usr/local/apache/common-local/php-1.18/index.php(57): MediaWiki->run()
#11 /usr/local/apache/common-local/live-1.5/index.php(3):
require('/usr/local/apac...')
#12 {main}

It was fixed in SVN but the fix has not been deployed yet. It is customary to mark bugs as FIXED as soon as the fix is checked in, though.

kai.marc.heide wrote:

When can the deployment of this fix be expected? Are the deployment cycles big?

Fixes like this one will probably be deployed in a few days time.
I'll try to ping someone tomorrow.

  • Bug 32313 has been marked as a duplicate of this bug. ***

(In reply to comment #19)

Fixes like this one will probably be deployed in a few days time.
I'll try to ping someone tomorrow.

Deployed.