We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Getting AJAX to work with security->checkToken()

Here is where I am at: I have created a working AJAX call and reply, but when calling security->checkToken() it fails all the time.

I've created a route that is a specific endpoint for ajax

$router->add("/ajax/{action:[a-zA-Z0-9\-]+}", array(
    'controller' => 'ajax',  
    'action'=>1
));

And I have created a form class with a CSRF token in it like this

public function initialize($entity = null, $options = null)
    {
        $this->setEntity($this);
        $this->add(new Hidden("csrf"));

}

And I have setup a controller called AjaxController.php which loads just fine,

class AjaxController extends ControllerBase
{

    public function initialize()
    {
        $this->view->disable();
    }

    public function submitcontactAction()
    {
        // use the request to check for post
        if ($this->request->isPost() == true) {
            // disable view so that no HTML is sent

            // Check whether the request was made with Ajax
            if ($this->request->isAjax() == true) {
                // set right header
                $this->response->setContentType('application/json', 'UTF-8');
                // will add CSRF later!  annoying
                if($this->security->checkToken()){                    
                    $array = array("status"=>"success", "data"=>"something");                                        
                  }else {
                    $array = array("status"=>"failed", "data"=> $this->security->checkToken(), "session" => $_SESSION , 'token'=>$this->security->getToken() );
                }
                // set content
                $this->response->setContent(json_encode($array));
                // send content
                return $this->response;
            }

        }else{
            // choose to die as that makes it cleaner
            die();
        }
    }

}

I've got a working form that shows both the csrf hidden field andal also tried one that does specific token and tokenkey generation

<form method="post" action="" class="contact-form labels-side" >
    <input type="hidden" value="<?php echo $token ?>" name="<?php echo $tokenKey ?>" />
    <?php  echo $form->render("csrf"); ?>
    </form>

and a working ajax call using jQuery

jQuery(document).ready(function($){

    function sendAjaxRequest(action, data, dataType){
        $.ajax({
            type: "POST",
            url: "/ajax/"+action,
            data: data,
            success:function(results){
                        console.log(results);
                    if(results.status === "success"){
                       console.log("WOOHOO");
                    }else{
                        // did not work

                    }},
            error: function(jqXHR, textStatus, errorThrown) {
                    console.log(JSON.stringify(jqXHR));
                    console.log("AJAX error: " + textStatus + ' : ' + errorThrown);
             },    
            dataType: dataType
         });
    }

    function success(results){
        console.log(results);
    }

    $("form").submit(function(e){
       e.preventDefault();
       data = $(this).serialize(); 
       dataType = 'json';
       action = $(".ajaxaction", this).val();
       sendAjaxRequest(action, data, dataType);

    });

});

BUT when I try to use the security token check, it responds with a different token than the one that is in the session. I have come down to the dea that it must be somethign to do with routing that is stopping or setting up a new SESSION token.

Please help as Iwant omake my AJAX as safe as possible.

any chance anyone has an answer for this??

First try this, and you will see how getToken() works

    $tokens = array();
    for (int $n = 0; $n < 20; $n++) {
        $tokens[] = $this->security->getToken();
    }
    var_dump($tokens);
    exit;

$this->security->checkToken([key], [value]) can accept key & value as parameters. All you have to do, is set those values some where in order to retrieve them with javascript. Like this:


    <form data-key="<? echo $this->security->getToken(); ?>" data-value="<? echo $this->security->getTokenKey(); ?>">

    <script>

        $('form').submit(function(event) {
            event.preventDefault();

            values = {
                key: $('form').attr('data-key'),
                value: $('form').attr('data-value')
            };

            // Send ajax with those values
        })

    </script>

And in php check like this


    // If you sending with POST-method!
    if ($this->security->checkToken($this->request->getPost('key'), $this->request->getPost('value'))) {
        // okay
    }