security: # Symfony's default, stated because it is a decision: the session id is regenerated on a # successful login, so a session id an attacker planted beforehand is not the one that ends # up authenticated. session_fixation_strategy: migrate # No password_hashers: there are no passwords here. Authentication is OAuth2 against myep, # which owns the credentials; ephub only ever sees a userinfo response. # An administrator can do everything a supervisor can, so the "may act on other people's # bookings" checks ask for ROLE_SUPERVISOR alone. Only isGranted() sees this: # User::getRoles() still returns the stored roles, which is why CodeVisibility names # ROLE_ADMIN explicitly. role_hierarchy: ROLE_ADMIN: [ROLE_SUPERVISOR] providers: app_user_provider: entity: class: App\Entity\User property: email firewalls: dev: # _error is the dev-only preview of the error pages (/_error/404, /_error/500). pattern: ^/(_profiler|_wdt|_error|assets)/ security: false main: lazy: true provider: app_user_provider entry_point: App\Security\LoginEntryPoint custom_authenticators: - App\Security\EpAuthenticator # The local lockout. Roles follow myep on every login and a deleted row is simply # provisioned again, so this flag is the only thing here that myep cannot undo. user_checker: App\Security\UserChecker logout: path: app_logout target: app_login # Without this any third-party page can log somebody out by embedding the URL. # The header link is a form POST for the same reason. enable_csrf: true # Local only: there is no RP-initiated logout against myep and no token # revocation, so this ends the ephub session and nothing else. It matters less # than it usually would -- myep destroys its own session immediately after an # external authorization request, so there is normally no SSO session left to # end -- and the access token is gone either way, never having been stored. access_control: # The login surface itself has to stay reachable, or the entry point redirects in a loop. - { path: ^/(login|auth|logout)$, roles: PUBLIC_ACCESS, requires_channel: https } - { path: ^/auth/, roles: PUBLIC_ACCESS, requires_channel: https } # Before the catch-all, or ROLE_EMPLOYEE would match ^/ first and the admin area would be # open to everybody. Order is the whole guard here. - { path: ^/admin, roles: ROLE_ADMIN, requires_channel: https } # Everybody's bookings, for supervisors and (through role_hierarchy) administrators. Kept # out of ^/admin so that everything under it stays administrator-only. - { path: ^/manage, roles: ROLE_SUPERVISOR, requires_channel: https } # Any of these opens the app -- access_control treats a list of roles as an OR. Not # ROLE_USER: myep authenticates far more people than work here, and someone who holds # none of these is refused at login with an explanation rather than let in to an empty # screen. Keep in step with Role::ELIGIBLE. - { path: ^/, roles: [ROLE_EMPLOYEE, ROLE_SUPERVISOR, ROLE_ADMIN], requires_channel: https }