A user can login via a web form and then a javascript client will be used to access an api. If the user is not logged in the api should return a json response with a 403 error, any other page on the site should continue to redirect to the login page.
The following firewalls exist:
firewalls:
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_token_generator: security.csrf.token_manager
logout: true
anonymous: true
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api/, role: ROLE_USER }
The login form works correctly and the /api/ routes are secure.
If the javascript client ever accesses the /api/* and the user is not logged in they should receive a 403 json response, currently they get a 302 redirect to the /login page. The user might not be logged in because the session could have expired.
How do you return a JSON response when the user is not logged in only for /api/ routes?
I've tried creating various event listeners but can not find the correct event; the following only triggers for failed login form events.
App\EventListener\SecurityListener:
tags:
- { name: kernel.event_listener, event: security.authentication.failure, method: onFailure }
I could also check in each controller method for ! isGranted(ROLE_USER) and return JsonResponse(message: "please login", status: 403) but this is not very optimal and results in lots of duplicated code, there has to be a simpler solution.
The javascript client will always send the headers Content-Type: application/json.