Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Invalid Token warnings more user friendly #8445

Merged
merged 5 commits into from
Nov 5, 2016

Conversation

izharaazmi
Copy link
Contributor

@izharaazmi izharaazmi commented Nov 16, 2015

The session token validation implementation in various controller methods currently gives an empty white screen with "Invalid token" text. This is total uninformative to a normal user.

This update implicitly redirects to the previous page if the token is not valid. To prevent implicit redirect pass false as the second argument to JSession::validateToken() $this->checkToken() from the JControllerLegacy controller instance.

To make use of this method we need to replace any occurrence of JSession::checkToken('post') or jexit(JText::_('JINVALID_TOKEN')); with JSession::validateToken('post'); $this->checkToken();

Summary of Changes

  • Based on the discussion below I've removed the method from JSession class and put it in the closer context of its application viz. JControllerLegacy.
  • All the controllers should now be able to simply call $this->checkToken() and the redirection shall be handled implicitly. Implicit redirection is done to the referrer (calling) page always.
  • If a custom handling is required such as alternate redirection url or custom response format like JSON one may call $this->checkToken like:
if (!$this->checkToken('post', false))
{
     // ...
}

or even directly call the current JSession::checkToken (without the die part) like:

if (!JSession::checkToken('post'))
{
     // ...
}

This will skip the implicit redirection and return false if the token does not match. Then the necessary if - else may be implemented as needed.

Test Instruction

To see the effect the respective forms should be submitted after manipulating the token input in the form so as to trigger invalid token situation. This can usually be done by selecting in the browser "inspect element" (or similar) and modify the DOM.

If the token is valid (not manipulated or expired), everything should be working as usual without any difference.

The necessary changes are made in the front-end which should be tested:

  • In com_users component try to register a new user, login, logout, remind username, reset password, save user profile.
  • In com_contact submit the contact form to send an email.
  • In com_content submit a vote.

EDIT June 26, 2016:
Added Summary of changes and Test Instructions based on the new changes.

@joomla-cms-bot joomla-cms-bot added Language Change This is for Translators PR-staging labels Nov 16, 2015
@izharaazmi
Copy link
Contributor Author

I was making changes in the checkToken method itself. But made this a separate method for clarity.

The other similar discussion on this topic is ongoing in the PR #8416.

@izharaazmi
Copy link
Contributor Author

Another idea is to allow passing the second argument to JSession::validateToken($method, $redirect) as:

Value of $redirect Behaviour
true Redirect to the referrer page (default value)
false No redirect, just return false if token is invalid
Custom URL String redirect to this specific url if token is invalid

@izharaazmi
Copy link
Contributor Author

I was recently thinking about this method getting influenced by

... it is the wrong way and against design principles: JSession is a specialised class for sessionhandling and not about redirection handling ... #8416 (comment)

I see most of these checks are done in controllers and all (almost) are inherited from JControllerLegacy. Would that be an appropriate location to move this method validateToken, however I like the name checkToken more.
So that we can do the check like:

$this->checkToken('post', true); // checkToken($method, $redirect)

Then gradually update the core components to use this test by test.

@peterpeter
Copy link
Contributor

Better.

But you don't have to move your new method, just use the allready existing ones from JControllerLegacy instead:
You just have to change

JSession::checkToken('post') or jexit(JText::_('JINVALID_TOKEN'));

to

JSession::checkToken('post') or $this->setRedirect($url, JText::_('JINVALID_TOKEN'), 'error')->redirect();

with the right url and your improved message.

Your solution is still a code- (and thus test-) duplication.


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/8445.

@izharaazmi
Copy link
Contributor Author

@peterpeter I almost agree. But to me the code does not appear to be any duplication. It internally uses the already existing method. The extra method introduced is just to provide the ability to auto calculate the REFERER page url for redirection. If that is not needed then of course we can follow what you suggested. But I think it could be useful.

@henkrijneveld
Copy link

I agree this is a real problem, but in current state untestable (we do not have a solution). Please elaborate, because it is a good idea to solve this.


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/8445.

@roland-d
Copy link
Contributor

Hello @izharaazmi

Thank you for your contribution.

The last comment here was on April 15th. Can you update this PR so it is testable?
If no reply is received within 4 weeks we will close this issue.

Thanks for understanding!


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/8445.

…white screen with "Invalid token" text. This is total uninformative to a normal user.

This update implicitly redirects to the previous page if the token is not valid. To prevent implicit redirect pass `false` as the second argument to `JSession::validateToken()`

To make use of this method we need to replace any occurrence of `JSession::checkToken('post') or jexit(JText::_('JINVALID_TOKEN'));` with `JSession::validateToken('post');`
Example is set up in com_users > login method.
…oser context to the usage.

This allows implicit redirect to the REFERER page in case of token mismatch. In all other case it is same as calling JSession::checkToken() directly.

Changes made in the frontend components to make this change test-able.

Note: We intend to discourage the `die` usage everywhere which leads the the said uninformative white page.
@izharaazmi
Copy link
Contributor Author

I have made the necessary changes in the front-end components. Please see #8445 (comment) for updated notes.

I hope it is now testable for the front-end. I'll preferably do backend implementation as a separate PR if this is approved.

@hardiktailored
Copy link

I have tested this item 🔴 unsuccessfully on 4b630b0

I found issue, after applying patch and I modified token of login form presented on sidebar. It redirects to blank screen, Network tab shows "500 Internal Server Error". Before applying patch "The most recent request was denied because it contained an invalid security token. Please refresh the page and try again." message was appearing on screen.

For the other inner pages warning message "The security token did not match. The request was aborted to prevent any security breach. Please try again." appears after applying the patch.


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/8445.

@hardiktailored
Copy link

Check the warning message after patch applied(All pages except login form problem mentioned above):
screen shot 2016-07-12 at 07 20 46

Before applying patch (for all screens):
screen shot 2016-07-12 at 07 23 01


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/8445.

@izharaazmi
Copy link
Contributor Author

@hardiktailored I tested it again and it worked fine. I may be missing something... can you please explain the issue a little more?

@AnishaTailored
Copy link

I have tested this item 🔴 unsuccessfully on 4b630b0

I have also found the issue after applying this patch (using the patchtester component) same as @hardiktailored, when I login (after modifying the token from DOM), I get the following error "
Fatal error: Call to undefined method JSession::validateToken() in components/com_users/controllers/user.php on line 30".

Before applying the patch login function has JSession::checkToken('post') or jexit(JText::_('JINVALID_TOKEN')); instead of JSession::validateToken('post');
I have checked for other forms (registration, reset password, remind username, edit profile etc.), they are working fine.


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/8445.

@izharaazmi
Copy link
Contributor Author

@AnishaTailored Thanks for explaining the issue in detail. I found that in my previous commit I had missed changing one occurrence of validateToken that was causing failures.

I've fixed it now, please test this again.

@AnishaTailored
Copy link

I have tested this item ✅ successfully on 39a5a50

Now it works fine.


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/8445.

@izharaazmi
Copy link
Contributor Author

@hardiktailored Can you test this again please.

*
* @return boolean True if found and valid, otherwise return false or redirect to referrer page.
*
* @since 3.6.0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use __DEPLOY_VERSION__

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Done.

@@ -440,6 +440,6 @@ public function remind()
public function resend()
{
// Check for request forgeries
JSession::checkToken('post') or jexit(JText::_('JINVALID_TOKEN'));
// $this->checkToken('post');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did that because I don't see any code in that function. I don't understand why that method is kept there.

@hvdmeer
Copy link

hvdmeer commented Nov 4, 2016

I have tested this item ✅ successfully on b05765d


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/8445.
I was missing some information about what exactly DOM is but my neighbor at the PBFNL was so kind to explain it to me. Thus resulting in a succesful test.

@renekreijveld
Copy link

I have tested this item ✅ successfully on b05765d

Tested with modification of the token through Firebug. After patch installation better message in a alert.


This comment was created with the J!Tracker Application at issues.joomla.org/tracker/joomla-cms/8445.

@zero-24
Copy link
Contributor

zero-24 commented Nov 4, 2016

Please resolve the merge conflicts.

@rdeutz or @wilsonge please review and take a final decision here.

@izharaazmi
Copy link
Contributor Author

I was resolving the conflict, then I saw the missing register method the controller. Little investigation led me to bae1d43#diff-f820ef502f338b5be5a00aac838e756fL287. I could not find the exact PR which actually made this change. On 3.7.x branch this method still exists. Somebody guide me at this please!

@zero-24
Copy link
Contributor

zero-24 commented Nov 5, 2016

This is removed in 3.6.4 to avoid registations over the wrong way. 3.7.0-dev branch is not updated with this change as staging is now 3.7.-dev

@izharaazmi
Copy link
Contributor Author

Won't it break b/c for components redirecting/submitting to that task for registration?

@zero-24
Copy link
Contributor

zero-24 commented Nov 5, 2016

Yes. But it was the decision of the JSST to remove that method as it is not used anymore and was never correctly implemented.

@joomla-cms-bot joomla-cms-bot removed the Language Change This is for Translators label Nov 5, 2016
@izharaazmi
Copy link
Contributor Author

@zero-24 Thanks for clarification. I have updated my branch to latest staging hence resolved the conflicts.

@rdeutz rdeutz added this to the Joomla 3.7.0 milestone Nov 5, 2016
@rdeutz rdeutz merged commit a17c0d7 into joomla:staging Nov 5, 2016
@joomla-cms-bot joomla-cms-bot added the Language Change This is for Translators label Nov 5, 2016
@izharaazmi
Copy link
Contributor Author

Thanks everybody for making this to this point 👍

I think this should followed up by some documentation update. Please advise where can I do that.

@izharaazmi izharaazmi deleted the checktoken branch November 5, 2016 10:15
@andrepereiradasilva
Copy link
Contributor

andrepereiradasilva commented Nov 5, 2016

@izharaazmi can you do the same for all other token dies (where applies) so we have a consistent core?

There a lot of JSession::checkToken('xxxxx') or die(JText::_('JINVALID_TOKEN'));

egrep -R "JSession::checkToken" /path/to/joomla-staging/ | awk '{print $1}'

@izharaazmi
Copy link
Contributor Author

@andrepereiradasilva Sure, hope to see it this Monday! Btw, I'm having 152 occurrences. Please do let me know if you find more.

@PhilETaylor

This comment was marked as abuse.

@izharaazmi
Copy link
Contributor Author

@andrepereiradasilva I have made the required changes. Please test the other PR at your convenience.

nvyush pushed a commit to nvyush/joomla-cms that referenced this pull request Nov 9, 2016
* The session token validation implementation currently gives an empty white screen with "Invalid token" text. This is total uninformative to a normal user.
This update implicitly redirects to the previous page if the token is not valid. To prevent implicit redirect pass `false` as the second argument to `JSession::validateToken()`

To make use of this method we need to replace any occurrence of `JSession::checkToken('post') or jexit(JText::_('JINVALID_TOKEN'));` with `JSession::validateToken('post');`
Example is set up in com_users > login method.

* Moved the checkToken method to JControllerLegacy as it is the more closer context to the usage.
This allows implicit redirect to the REFERER page in case of token mismatch. In all other case it is same as calling JSession::checkToken() directly.

Changes made in the frontend components to make this change test-able.

Note: We intend to discourage the `die` usage everywhere which leads the the said uninformative white page.

* Fix wrong function call

* use automatic since tag macro

Thanks @andrepereiradasilva
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Language Change This is for Translators
Projects
None yet
Development

Successfully merging this pull request may close these issues.