Article Rating AJAX Never Sends The CSRF Token, So `articlerating()` Rejects Every Click With "Invalid Token" - Question | JoomShaper

is live, now with multi-currency selling.

Article Rating AJAX Never Sends The CSRF Token, So `articlerating()` Rejects Every Click With "Invalid Token"

Goran

Goran

Helix Framework 2 weeks ago

The article rating widget cannot record a vote. Every click is answered with "Invalid Token", so the star rating feature is inert on a default install with article ratings enabled.

templates/shaper_helixultimate/js/main.js:301-334 builds the AJAX payload:

$('.article-ratings .rating-star').on('click', function (event) {
    event.preventDefault();
    var $parent = $(this).closest('.article-ratings');

    var request = {
        option: 'com_ajax',
        template: template,
        action: 'rating',
        rating: $(this).data('number'),
        article_id: $parent.data('id'),
        format: 'json',
    };

    $.ajax({ type: 'POST', data: request, ... });
});

The payload carries no CSRF token, but the endpoint it reaches requires one. templates/shaper_helixultimate/helper.php:27:

Session::checkToken() or die(json_encode($output));

Session::checkToken() (libraries/src/Session/Session.php:64-88) looks for the token in the X-CSRF-Token header or in the POST body; neither is present, so it returns false and the handler dies with {"status":false,"message":"Invalid Token"}.

Reproduced from a normal browser session on an article page, same session for both requests:

POST option=com_ajax&template=shaper_helixultimate&action=rating&rating=5&article_id=45&format=json
  -> {"status":false,"message":"Invalid Token"}

POST option=com_ajax&template=shaper_helixultimate&action=rating&rating=5&article_id=45&format=json&<token>=1
  -> {"status":true,"message":"Thanks for your rating.","rating_count":1,"ratings":"<span class=\"rating-star\" ..."}

The only difference between the two is the token field, and Joomla already publishes it on every page in joomla-script-options under csrf.token, so the fix is three lines in the same handler:

var csrfToken = window.Joomla && Joomla.getOptions ? Joomla.getOptions('csrf.token', '') : '';
if (csrfToken) {
    request[csrfToken] = 1;
}

Two smaller things in the same endpoint, which only become reachable once the token is sent:

  1. helper.php:32 takes rating as a plain (int) and helper.php:86 adds it straight into rating_sum with no range check. A request with rating=99999 inflates the stored average for that article. Clamping to 1..5 is enough.

  2. helper.php:31 takes article_id as a plain (int) and helper.php:94 inserts a #__content_rating row without checking that the article exists or is published, so rows can be created for ids that are not articles.

    Thank you.

1
1 Answers
Ziaul Kabir
Ziaul Kabir
Accepted Answer
Support Agent 2 weeks ago #234031

Hi Goran,

Thank you for the detailed report and for providing the reproduction steps and suggested fixes.

We have forwarded this issue and your additional findings to our development team for review. They will investigate the CSRF token issue along with the rating validation and article ID checks you mentioned.

We appreciate the thorough technical investigation and the clear explanation.

Thanks!

0