I have Symfony2 application separated into 2 bundles: BackendBundle
for API and FrontendBundle
for AngularJS "client". Everything works under firewall.
BackendBundle
has entities, handles API routes; FrontendBundle
has Angular views, routing etc. and has only one controller with wildcard:
class AngularController extends Controller {
/**
* @Route("/{route}", name="angular_index_all_unmatched_routes", requirements={"route" = ".*"})
* @Template("FrontendBundle::index.html.twig")
*/
public function angularIndexAction($route) {
return ['route' => $route];
}
}
FrontendBundle
routing is defined as last resource in app/config/routing.yml
, to be invoked only if any other route was not matched. Thanks to that, it can handle Angular HTML5-mode routes if they're accessed directly (for example copy-paste) - and it works ok.
What I want to do, is define firewall and/or access control in way that all those unmatched routes (handled by AngularController::angularIndexAction()
) could be accessible by anonymous user.
Why? I want to open some API routes (via frontend proxy) to be accessible by non-users (for example confirmation URLs sent by email, with some message to user).
I don't want to hardcode access control list for every anonymous "Angular" route, I would like to do it only for API routes. At the end, those unmatched routes should open Angular's index which should know if user is logged in (for displaying full or simplified layout) and should handle Angular routes and display some kind of "Access denied" message if request failed (there is Symfony listener and Angular's $provide
interceptor for that).
Any suggestions?
Edit: @Security
annotation on AngularController::angularIndexAction()
does not work, it still redirects to firewall entry point.
Edit2: Here is fragment of security.yml
firewalls:
unsecured:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
anonymous: true
secured:
pattern: '^.*$'
form_login:
login_path: /our-provider/login
check_path: /our-provider/callback/
anonymous: true
entry_point: our_provider.entry_point
access_control:
- { path: '^/our-provider/(login(/[a-zA-Z]+)?|logout|redirect|callback)', roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: '^/', roles: ROLE_USER }
I know that { path: '^/', roles: ROLE_USER }
will redirect all routes to login page if user is not logged in. I assumed it's obvious and did not mentioned it. What I want is force ROLE_USER
for matched routes and let IS_AUTHENTICATED_ANONYMOUSLY
for those unmatched, without explicitely defining each frontend "proxy-route". In my case there is not 404 Symfony page, because everything goes to angular_index_all_unmatched_routes
route and there Angular routing definition decides if there is something to handle or not.