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
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.