Page MenuHomePhabricator

OAuth should return a useful error message when oauth_token is missing
Closed, ResolvedPublic

Description

Have been struggling with this issue for a good few days.

I am currently trying to get oauth to work from node using passport-mediawiki.

I get as far as getting asked to authorise the oauth application for the user on a screen that reads:

Hi user1,
ResourceEdge Dev 5 would like to have basic access on your behalf on all projects of this site.
Privacy Policy Cancel Allow

Once I press Allow, I get the same box, but with the statement

There are problems with some of your input.
Hi user1,
ResourceEdge Dev 5 would like to have basic access on your behalf on all projects of this site.
Privacy Policy Cancel Allow

(For the record, pressing cancel sends me to a page saying I did not allow the application access

As far as I can tell, there is no info as to what the issue is. I gave the user access to every part of OUTH, no success so far. Will add logs and so forth on next page if the option exist.

The node passport-mediawiki-oauth uses the following three urls to get information:

options.requestTokenURL        = options.baseURL + '/index.php';
options.accessTokenURL         = options.baseURL + '/index.php?title=Special:OAuth/token';
options.userAuthorizationURL   = options.baseURL + '/index.php?title=Special:OAuth/authorize';

And I am pretty certain these are the right ones.

Version information as follows:

Installed software
Product Version
MediaWiki 1.24.1
PHP 5.4.16 (apache2handler)
MariaDB 5.5.41-MariaDB
Entry point URLs
Entry point URL
Article path /dbfswiki/index.php/$1
Script path /dbfswiki
index.php /dbfswiki/index.php
api.php /dbfswiki/api.php
load.php /dbfswiki/load.php
Installed skins
Skin Version License Description Authors
Cologne Blue – GPLv2+ A lightweight skin with minimal formatting Lee Daniel Crocker and others
Foreground 1.2-alpha (7d098d2) 14:23, 8 September 2014 License Provides a skin that focuses on putting your content in the foreground Garrick Van Buren, Jamie Thingelstad, Tom Hutchison and others
Modern – GPLv2+ A blue/grey theme with sidebar and top bar. Derived from MonoBook. River Tarnell and others
MonoBook – GPLv2+ The classic MediaWiki skin since 2004, named after the black-and-white photo of a book in the page background Gabriel Wicke and others
Vector – GPLv2+ Modern version of MonoBook with fresh look and many usability improvements Trevor Parscal, Roan Kattouw and others
Installed extensions
Semantic extensions
Extension Version License Description Authors
Semantic MediaWiki 2.1.1 GPL-2.0+ Making your wiki more accessible - for machines and humans (online documentation) Markus Krötzsch, Jeroen De Dauw, James Hong Kong and others
Semantic Result Formats 2.1.2 GPL-2.0+ Additional result formats for Semantic MediaWiki queries James Hong Kong, Stephan Gambke, Jeroen De Dauw, Yaron Koren and others
SMWAskAPI 0.9 alpha API for executing semantic queries (#ask) in Semantic MediaWiki Pierre Mz
Special pages
Extension Version License Description Authors
Interwiki 3.0 20140719 License Adds a special page to view and edit the interwiki table Stephanie Amanda Stevens, Alexandre Emsenhuber, Robin Pepermans, Siebrand Mazeland, Platonides, Raimond Spekking, Sam Reed, Jack Phoenix, Calimonius the Estrange and others
Renameuser – License Adds a special page to rename a user (need renameuser right) Ævar Arnfjörð Bjarmason and Aaron Schulz
Parser hooks
Extension Version License Description Authors
Cite – GPLv2 Adds <ref[ name=id]> and <references/> tags, for citations Ævar Arnfjörð Bjarmason, Andrew Garrett, Brion Vibber, Marius Hoch, Steve Sanbeg and others
CSS 3.3.0, 2014-03-31 A parser function that allows CSS stylesheets to be included in specific pages Aran Dunkley and Rusty Burchfield
Embed Document 0.13 Allows embedding *.pdf, *.doc and *.wav files on a wiki page SLohse and DrTrigon
ImageMap – License Allows client-side clickable image maps using <imagemap> tag Tim Starling
InputBox 0.2.0 Allow inclusion of predefined HTML forms Erik Moeller, Leonardo Pimenta, Rob Church, Trevor Parscal and DaSch
ParserFunctions 1.6.0 License Enhance parser with logical functions Tim Starling, Robert Rohde, Ross McClure and Juraj Simlovic
SyntaxHighlight 1.0.8.11-wmf1 License Provides syntax highlighting <syntaxhighlight> using GeSHi - Generic Syntax Highlighter Brion Vibber, Tim Starling, Rob Church and Niklas Laxström
Widgets 1.1 (24de39e) 21:13, 23 March 2015 Allows wiki administrators to add free-form widgets to the wiki by editing pages within the Widget namespace. Community-contributed widgets can be found on MediaWikiWidgets.org Sergey Chernyshev and others
Media handlers
Extension Version License Description Authors
PDF Handler – License Handler for viewing PDF files in image mode. Martin Seidel and Mike Połtyn
Spam prevention
Extension Version License Description Authors
ConfirmEdit 1.3 License Provides CAPTCHA techniques to protect against spam and password-guessing Brion Vibber and others
DataValues
Extension Version License Description Authors
DataValues 1.0 GPL-2.0+ Collection of objects representing various kinds of values Jeroen De Dauw
DataValues Common 0.2.3 GPL-2.0+ Contains common implementations of the interfaces defined by DataValuesInterfaces Jeroen De Dauw
DataValues Interfaces 0.1.5 GPL-2.0+ Defines interfaces for ValueParsers, ValueFormatters and ValueValidators Jeroen De Dauw
DataValues Validators 0.1.2 GPL-2.0+ Contains common ValueValidator implementations Jeroen De Dauw and The Wikidata team
Other
Extension Version License Description Authors
Bootstrap 1.1.3 GPLv3+ Provides the Bootstrap framework in the wiki Stephan Gambke and James Hong Kong
Extension Installer 0.2.2 (6d546f1) 19:47, 10 February 2014 Allows installing extensions and PHP libraries via Composer Jeroen De Dauw
Font Awesome – Adds support for FontAwesome icons Lee Miller
Gadgets – License Lets users select custom CSS and JavaScript gadgets in their preferences Daniel Kinzler and Max Semenik
Html5mediator – A simple way to embed audio and video files in a wiki Seung Park
Liquid Threads 2.2-alpha License Add threading discussions to talk pages David McCabe and Andrew Garrett
LocalisationUpdate 1.3.0 Keeps the localised messages as up to date as possible Tom Maaswinkel, Niklas Laxström and Roan Kattouw
OAuth – GPL-2.0+ Allows usage of OAuth 1.0a for API authorization Aaron Schulz, Chris Steipp and Brad Jorsch
Validator 2.0.4 GPL-2.0+ Declarative parameter processing library Jeroen De Dauw
WikiEditor 0.4.0 License Provides an extendable wikitext editing interface and many feature-providing modules Trevor Parscal, Roan Kattouw, Nimish Gautam and Adam Miller
WYSIWYG editor 1.5.6_0 [B551+02.02.2015], CKEditor 4.4.5 [revision 25cdcad] Allow editing using the WYSIWYG editor CKEditor Frederico Caldeira Knabben, Wiktor Walc, Jack Phoenix, ontoprise GmbH and MediaWiki community of wysiwyg
Parser extension tags
<embed_document>, <gallery>, <html>, <html5media>, <imagemap>, <info>, <inputbox>, <nowiki>, <pre>, <ref>, <references>, <smwdoc>, <source>, <syntaxhighlight>, <talkpage> and <thread>
Parser function hooks
anchorencode, ask, basepagename, basepagenamee, calendarenddate, calendarstartdate, canonicalurl, canonicalurle, cascadingsources, concept, css, declare, defaultsort, displaytitle, expr, filepath, formatdate, formatnum, fullpagename, fullpagenamee, fullurl, fullurle, gender, grammar, if, ifeq, iferror, ifexist, ifexpr, info, int, language, lc, lcfirst, localurl, localurle, lqtpagelimit, namespace, namespacee, namespacenumber, ns, nse, numberingroup, numberofactiveusers, numberofadmins, numberofarticles, numberofedits, numberoffiles, numberofpages, numberofusers, numberofviews, padleft, padright, pageid, pagename, pagenamee, pagesincategory, pagesize, plural, protectionlevel, rel2abs, revisionday, revisionday2, revisionid, revisionmonth, revisionmonth1, revisiontimestamp, revisionuser, revisionyear, rootpagename, rootpagenamee, set, set_recurring_event, show, smwdoc, special, speciale, subjectpagename, subjectpagenamee, subjectspace, subjectspacee, subobject, subpagename, subpagenamee, switch, tag, talkpagename, talkpagenamee, talkspace, talkspacee, time, timel, titleparts, uc, ucfirst, urlencode, useliquidthreads and widget

Event Timeline

Vrghost1 created this task.Sep 15 2015, 9:20 AM
Vrghost1 raised the priority of this task from to Needs Triage.
Vrghost1 updated the task description. (Show Details)
Vrghost1 added a subscriber: Vrghost1.
Restricted Application added a subscriber: Aklapper. · View Herald TranscriptSep 15 2015, 9:20 AM

This is the best I can do for debug log (captured from the window below the confirmation box)

Debug data:
Start request POST /dbfswiki/index.php/Special:OAuth/authorize
HTTP HEADERS:
HOST: v-ghost.port0.org:8081
CONNECTION: keep-alive
CONTENT-LENGTH: 190
CACHE-CONTROL: max-age=0
ACCEPT: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
ORIGIN: http://v-ghost.port0.org:8081
UPGRADE-INSECURE-REQUESTS: 1
USER-AGENT: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36
CONTENT-TYPE: application/x-www-form-urlencoded
REFERER: http://v-ghost.port0.org:8081/dbfswiki/index.php?title=Special%3AOAuth%2Fauthorize&oauth_token=&oauth_consumer_key=449c71620457972e86ef20e083ccb87b
ACCEPT-ENCODING: gzip, deflate
ACCEPT-LANGUAGE: en-US,en;q=0.8
COOKIE: wikiEditor-0-toolbar-section=advanced; dbfswikiUserID=1; dbfswikiUserName=Dbfswiki; dbfswiki_session=euho3kd951g59qib5bopgvvlc1
[caches] main: EmptyBagOStuff, message: SqlBagOStuff, parser: SqlBagOStuff
[caches] LocalisationCache: using store LCStoreCDB
Unstubbing $wgParser on call of $wgParser::setHook from registerEmbedDocumentHandler
Parser: using preprocessor: Preprocessor_DOM
Fully initialised
User: cache miss for user 1
Connected to database 0 at localhost
Query dbfswiki (1) (slave): BEGIN /* DatabaseBase::query (User::loadFromDatabase) */
Query dbfswiki (2) (slave): SELECT /* User::loadFromDatabase */ user_id,user_name,user_real_name,user_email,user_touched,user_token,user_email_authenticated,user_email_token,user_email_token_expires,user_registration,user_editcount FROM user WHERE user_id = '1' LIMIT 1
Query dbfswiki (3) (slave): SELECT /* User::loadGroups */ ug_group FROM user_groups WHERE ug_user = '1'
Connected to database 0 at localhost
Query dbfswiki (4) (slave): SELECT /* SqlBagOStuff::getMulti */ keyname,value,exptime FROM objectcache WHERE keyname = 'dbfswiki:messages:en'
MessageCache::load: Loading en... got from global cache
Gadget::loadStructuredList: MediaWiki:Gadgets-definition parsed, cache entry dbfswiki:gadgets-definition:7 updated
User: loading options for user 1 from database.
Query dbfswiki (5) (slave): SELECT /* User::loadOptions */ up_property,up_value FROM user_properties WHERE up_user = '1'
User: logged in from session
User: loading options for user 1 from override cache.
Unstubbing $wgLang on call of $wgLang::_unstub from ParserOptions::__construct
[OAuth] MediaWiki\Extensions\OAuth\SpecialMWOAuth::execute: doing 'authorize' with '' '449c71620457972e86ef20e083ccb87b' for 'Dbfswiki'
Query dbfswiki (6) (slave): SELECT /* MediaWiki\Extensions\OAuth\MWOAuthConsumer::newFromKey Dbfswiki */ oarc_id,oarc_consumer_key,oarc_name,oarc_user_id,oarc_version,oarc_callback_url,oarc_callback_is_prefix,oarc_description,oarc_email,oarc_email_authenticated,oarc_wiki,oarc_grants,oarc_registration,oarc_secret_key,oarc_rsa_key,oarc_restrictions,oarc_stage,oarc_stage_timestamp,oarc_deleted FROM oauth_registered_consumer WHERE oarc_consumer_key = '449c71620457972e86ef20e083ccb87b' LIMIT 1
[autoloader] Class FormatJSON was loaded using incorrect case
Query dbfswiki (7) (slave): SELECT /* MediaWiki\Extensions\OAuth\MWOAuthConsumerAcceptance::newFromUserConsumerWiki Dbfswiki */ oaac_id,oaac_wiki,oaac_user_id,oaac_consumer_id,oaac_access_token,oaac_access_secret,oaac_grants,oaac_accepted FROM oauth_accepted_consumer WHERE oaac_user_id = '1' AND oaac_consumer_id = '3' AND oaac_wiki = 'dbfswiki' LIMIT 1
Query dbfswiki (8) (slave): SELECT /* MediaWiki\Extensions\OAuth\MWOAuthConsumerAcceptance::newFromUserConsumerWiki Dbfswiki */ oaac_id,oaac_wiki,oaac_user_id,oaac_consumer_id,oaac_access_token,oaac_access_secret,oaac_grants,oaac_accepted FROM oauth_accepted_consumer WHERE oaac_user_id = '1' AND oaac_consumer_id = '3' AND oaac_wiki = '*' LIMIT 1
LoadBalancer::reuseConnection: this connection was not opened as a foreign connection
User::getBlockedStatus: checking...
User: cache miss for user 1
Query dbfswiki (9) (slave): SELECT /* User::loadFromDatabase Dbfswiki */ user_id,user_name,user_real_name,user_email,user_touched,user_token,user_email_authenticated,user_email_token,user_email_token_expires,user_registration,user_editcount FROM user WHERE user_id = '1' LIMIT 1
Query dbfswiki (10) (slave): SELECT /* User::loadGroups Dbfswiki */ ug_group FROM user_groups WHERE ug_user = '1'
User: loading options for user 1 from database.
Query dbfswiki (11) (slave): SELECT /* User::loadOptions Dbfswiki */ up_property,up_value FROM user_properties WHERE up_user = '1'
Query dbfswiki (12) (slave): SELECT /* Block::newLoad Dbfswiki */ ipb_id,ipb_address,ipb_by,ipb_by_text,ipb_reason,ipb_timestamp,ipb_auto,ipb_anon_only,ipb_create_account,ipb_enable_autoblock,ipb_expiry,ipb_deleted,ipb_block_email,ipb_allow_usertalk,ipb_parent_block_id FROM ipblocks WHERE ipb_address = 'Dbfswiki'
Query dbfswiki (13) (slave): SELECT /* LinkHolderArray::replaceInternal Dbfswiki */ page_id,page_namespace,page_title,page_is_redirect,page_len,page_latest,page_content_model FROM page WHERE (page_namespace = '4' AND page_title = 'Privacy_policy')
LoadBalancer::reuseConnection: this connection was not opened as a foreign connection
Query dbfswiki (14) (slave): SELECT /* LinkBatch::doQuery (for Skin::preloadExistence) Dbfswiki */ page_id,page_namespace,page_title,page_len,page_is_redirect,page_latest,page_content_model FROM page WHERE (page_namespace = '2' AND page_title = 'Dbfswiki') OR (page_namespace = '3' AND page_title = 'Dbfswiki')
Query dbfswiki (15) (slave): SELECT /* User::checkNewtalk Dbfswiki */ user_id FROM user_newtalk WHERE user_id = '1' LIMIT 1
Query dbfswiki (16) (slave): SELECT /* SqlBagOStuff::getMulti Dbfswiki */ keyname,value,exptime FROM objectcache WHERE keyname = 'dbfswiki:sitenotice'
Query dbfswiki (17) (slave): SELECT /* ResourceLoaderWikiModule::getTitleInfo Dbfswiki */ page_namespace,page_title,page_touched,page_len FROM page WHERE (page_namespace = '8' AND page_title IN ('Common.js','Foreground.js','Common.css','Foreground.css','Print.css') )
Query dbfswiki (18) (slave): SELECT /* ResourceLoaderWikiModule::getTitleInfo Dbfswiki */ page_namespace,page_title,page_touched,page_len FROM page WHERE (page_namespace = '8' AND page_title IN ('Group-bureaucrat.js','Group-bureaucrat.css','Group-oauthadministrators.js','Group-oauthadministrators.css','Group-sysop.js','Group-sysop.css','Group-user.js','Group-user.css','Group-autoconfirmed.js','Group-autoconfirmed.css') )
Query dbfswiki (19) (slave): SELECT /* NewMessages::newMessageCount Dbfswiki */ 1 FROM user_message_state WHERE ums_user = '1' AND ums_read_timestamp IS NULL LIMIT 500
Query dbfswiki (20) (slave): SELECT /* ResourceLoaderWikiModule::getTitleInfo Dbfswiki */ page_namespace,page_title,page_touched,page_len FROM page WHERE (page_namespace = '8' AND page_title IN ('Common.js','Foreground.js','Common.css','Foreground.css','Print.css') )
Query dbfswiki (21) (slave): SELECT /* ResourceLoaderWikiModule::getTitleInfo Dbfswiki */ page_namespace,page_title,page_touched,page_len FROM page WHERE (page_namespace = '8' AND page_title = 'Noscript.css')
Query dbfswiki (22) (slave): SELECT /* SqlBagOStuff::getMulti Dbfswiki */ keyname,value,exptime FROM objectcache WHERE keyname = 'dbfswiki:resourceloader:filter:minify-css:7:67f1fbd7c11038f0915f3c80cbc4dc25'
Query dbfswiki (23) (slave): SELECT /* SqlBagOStuff::getMulti Dbfswiki */ keyname,value,exptime FROM objectcache WHERE keyname = 'dbfswiki:resourceloader:filter:minify-css:7:9e509ea665bc3b91ef00abebf315c10d'
Query dbfswiki (24) (slave): SELECT /* ResourceLoaderWikiModule::getTitleInfo Dbfswiki */ page_namespace,page_title,page_touched,page_len FROM page WHERE (page_namespace = '8' AND page_title IN ('Group-bureaucrat.js','Group-bureaucrat.css','Group-oauthadministrators.js','Group-oauthadministrators.css','Group-sysop.js','Group-sysop.css','Group-user.js','Group-user.css','Group-autoconfirmed.js','Group-autoconfirmed.css') )
Parser: using preprocessor: Preprocessor_DOM
Query dbfswiki (25) (slave): SELECT /* MessageBlobStore::getFromDB Dbfswiki */ mr_blob,mr_resource,mr_timestamp FROM msg_resource WHERE mr_resource IN ('user.options','user.tokens') AND mr_lang = 'en'
Query dbfswiki (26) (slave): SELECT /* SqlBagOStuff::getMulti Dbfswiki */ keyname,value,exptime FROM objectcache WHERE keyname = 'dbfswiki:resourceloader:filter:minify-js:7:32f31fd7b6a0980963c108bdda452758'

scfc added a subscriber: scfc.Sep 15 2015, 3:30 PM

Here's one problem,

[OAuth] MediaWiki\Extensions\OAuth\SpecialMWOAuth::execute: doing 'authorize' with '' '449c71620457972e86ef20e083ccb87b' for 'Dbfswiki'

That first '' should have the request token filled in, and it's not.

Ah,

REFERER: http://v-ghost.port0.org:8081/dbfswiki/index.php?title=Special%3AOAuth%2Fauthorize&oauth_token=&oauth_consumer_key=449c71620457972e86ef20e083ccb87b

So oauth_token= here should have the request token passed in. Since it doesn't, the /authorize can't tie this request to your call to Special:OAuth/initiate.

I don't know anything about node's passport, but it's failing to pass the request token, so need to find a way to do that.

I thought we actually had an error message when Special:OAuth loaded with a blank oauth_token, but apparently not. We should fail with a more informative message there.

Tgr renamed this task from Pressing Allow on OAuth confirmation pop-up returns "There are problems with some of your input" to OAuth should return a useful error message when oauth_token is missing.Sep 15 2015, 5:55 PM
Tgr added a subscriber: Tgr.Sep 15 2015, 9:45 PM

We have an error message, it's just extremely generic (mwoauth-invalid-field-generic). But it's not shown, the text is from htmlform-invalid-input. This looks like a bug in HTMLForm - the message returned from HtmlFormField::validate() is ignored.

Change 238613 had a related patch set uploaded (by Gergő Tisza):
Use text returned by HtmlFormField::validate() when validation fails

https://gerrit.wikimedia.org/r/238613

Change 238615 had a related patch set uploaded (by Gergő Tisza):
Use informative messages on form errors

https://gerrit.wikimedia.org/r/238615

So started hacking around a bit in the code, and have manage to get the request to be
http://v-ghost.port0.org:8081/dbfswiki/index.php?title=Special%3AOAuth%2Fauthorize&oauth_token=98dfb1734b0db5cf765d3db1366737f37c652eaa&oauth_consumer_key=449c71620457972e86ef20e083ccb87b

So I have oauth_token and oauth_consumer_key but still have the same issue.
Are these the right things to send, I.E. should it accept the request with a oauth_token and a oauth_consumer_key. And should they be in the url?

And would I be right in saying that in theory, this should be the "registration" prior to actually trying to access oauth.

I.E. the system has not yet created the "init" key for the communication, but I expect that this is because the registration must complete first. Which also means that in theory, I should be able to open that API and accept registration in a web browser.

csteipp added a comment.EditedSep 17 2015, 4:29 PM

And would I be right in saying that in theory, this should be the "registration" prior to actually trying to access oauth.

I don't think you have this right. To clarify, MediaWiki's OAuth implementation is OAuth 1.0a (i.e., "3-legged OAuth"). So,

  1. Your server connects directly to MediaWiki (making a signed request to Special:OAuth/initiate). That call returns a token, which is the "request token" for the user who is going to do the authorization.
  1. You redirect the user's browser to Special:OAuth/authorize, passing the request token and your application's token in the "oauth_token" and "oauth_consumer_key" GET parameters (just like I think you have in https://phabricator.wikimedia.org/T112635#1649573, although I'm not exactly sure where you got those tokens from). This call to OAuth is not signed, since the request token is a reference to your original, signed request.
  1. After the user authorizes your Consumer on MediaWiki, their browser is redirected back to the callback url that you registered when you got your Consumer key and secret (or submitted as part of step #1). When the user comes back to your application, you make the 3rd call from your server directly to MediaWiki (to Special:OAuth/token) to exchange the authorization code for an "access token".

After all that, call the API with your signature in the Authorization header, and you will be taking actions on behalf of the authorizing user. Of you can call Special:OAuth/identiy to get a signed statement about the user's identity on the wiki.

@Vrghost1 Have you installed and configured memcached? I even needed $wgMainCacheType = CACHE_MEMCACHED for it to work.
Can you test a different framework such as https://github.com/valhallasw/flask-mwoauth to confirm it's MediaWiki's fault?

@csteipp: Just to be clear, I did not write the actual passport-mediawiki-oauth module. So I do not know if it is correct other than indication is that it did work some time in the pass (I am certain that Dan did a good work even if he calls it a hack). So at some point it did work.

@Ricordisamoa: I was actually planning to write a simple test outside of the passport system just to check where the problem is, but thought I would sidestep it and check if I should be able to access that first page before the initiation?

So, trying to find good information on this. Could someone tell me if the below article is correct, in that case it seems to me that I should be able to access this first step prior to initiating the connection. That is at least how the passport module seems to be doing it.
https://www.mediawiki.org/wiki/OAuth/For_Developers

(Its the clearest description of the mediawiki oauth flow I could find)

So, trying to find good information on this. Could someone tell me if the below article is correct, in that case it seems to me that I should be able to access this first step prior to initiating the connection. That is at least how the passport module seems to be doing it.
https://www.mediawiki.org/wiki/OAuth/For_Developers

Yes, that should be correct.

If you get passport working, feel free to add it to the example section.

Seems like the first issue is that for one reason or another the oauth initiaion part does not pick up the oauth token returned. Will try to get it working

Will put any comments on the other bug raised, and leave this to be about the missing error message.
https://phabricator.wikimedia.org/T112705

Change 238615 had a related patch set uploaded (by Gergő Tisza):
Use informative messages on form errors
https://gerrit.wikimedia.org/r/238615

Instead of passing an error message back to the form on submission (although that would be nice too), I was thinking we would throw an Exception that gives a useful error message when the user first gets to the /authorize form, just like we do if the Consumer key isn't valid in handleAuthorizationForm.

Change 238613 merged by jenkins-bot:
Hoist validation errors from hidden fields to the top of the form

https://gerrit.wikimedia.org/r/238613

Change 238615 merged by jenkins-bot:
Use informative messages on form errors

https://gerrit.wikimedia.org/r/238615

Tgr closed this task as Resolved.Aug 23 2016, 7:44 PM
Tgr claimed this task.