Search code examples
.htaccesssymfonyeasyapache-4

Symfony3: 404 on DEV, 403 on PROD WITH Controller Response


I am at a loss...

I am doing an AJAX POST to Symfony. In the PROD environment (app.php) I get a 403 FORBIDDEN status code (user does have access), but the response contains an error message that is generated inside the controller for one of the POST parameters that are empty. I have determined that $request->request->all() is empty. Switching to the DEV environment (app_dev.php) I get a 404 NOT FOUND response. Browsing to the route on both PROD & DEV does not provide either 403 or 404 responses. The AJAX POST is to the same server (no cross-domain issue) and the route for the AJAX POST is generated by Symfony.

A couple of notes:

1) The code works flawlessly on my localhost. The problem only occurs on our production server. Security.yml is set up correctly, and I have deactivated the custom ExceptionListener. The 404 NOT FOUND error on PROD is the standard Apache 404, and not the Symfony 404 "Route Not Found". However, when I enable my custom ExceptionListener I get the 404 Response from that, and not the Apache 404.

2) Our hosting provider upgraded our production server from EasyApache 3 to EasyApache 4. Along with this some of our PHP config settings changed. I had to have them re-enable SOAP and iconv in the PHP config. Because it works flawlessly on my localhost, I deduce that it HAS to be something to do with this, but I am going to have to pinpoint the exact issue for them to be able to fix it. I suspect something in the .htaccess settings (RewriteMod), but I do not know a lot about this.

3) There are a hundred different routes that are linked to controller functions, 90% of them are being accessed via AJAX POST. All of them work perfectly except this one (that we have found so far).

Controller Function:

/**
 * @Route("/secured/helpdesk/save", name="saveTicket")
 */ 
public function saveTicketAction(Request $request = null) 
{   
    $data = $request->request->all();

    if (empty($data['message'])) return $this->createJsonResponse(array('error' => 'No Ticket Description or Message Provided', 'data' => $data));  

     ... 
     The function is quite large, so I am not going to paste the whole thing, the error message above is what I receive along with the 403 response in PROD

}

Front-end AJAX POST

function saveTicket()
{
    $.ajax({
        url: '{{ url("saveTicket") }}',
        method: 'POST',
        async: true,
        data: $('#messageForm').serialize()
    })
    .done(function(data)
    {
        if (typeof(data.error) != 'undefined')
        {
            $('#errorMsg').html(data.error);
            $('#pageError').modal('show');
        }
        else
        {
            $('#successMsg').html('Helpdesk Ticket Successfully Saved.');
            $('#pageSuccess').modal('show');
            window.location = '{{url('helpdeskAdmin')}}';
        }
    });
    return false;
}

security.yml

security:
role_hierarchy:
    ROLE_SUPERADMIN:        ROLE_ACCOUNTADMIN
    ROLE_ACCOUNTADMIN:      ROLE_USER

providers:
    main:
        entity:
            class: AppBundle\Entity\User
            property: email

firewalls:
    secured_area:
        pattern:    ^/
        anonymous:  ~
        form_login:
            login_path:  login
            check_path:  login
            default_target_path: portalDashboard
            require_previous_session: false
            success_handler: authentication_handler
            failure_handler: authentication_handler
        logout:
            path:   /logout
            target: /
        http_basic:
            realm: "Smarttrace Portal"  
encoders:
    AppBundle\Entity\User: sha512

access_control:
    - { path: ^/superadmin, roles: ROLE_SUPERADMIN }
    - { path: ^/accountadmin, roles: ROLE_ACCOUNTADMIN }
    - { path: ^/secured, roles: ROLE_USER }
    - { path: ^/payfast, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY }

routing.yml

app:
   resource: "@AppBundle/Controller/"
   type:     annotation

logout:
   path: /logout

Solution

  • I realized that this issue only occured when HTML (Rich-Text) was being sent in one of the POST paramaters. The issue did have to do with EasyApache 4 where the "ModSecurity" rules give false positives. So the 403 was being generated by EasyApache 4 "ModSecurity" and was thus prohibiting the POST parameters to reach Symfony.