For the complete documentation index, see llms.txt. This page is also available as Markdown.

URL Rules

Rules that guard parts of the site by path, host, port, IP, route, method or expression. They are matched in declaration order, the first match winning.

access_control:
    rules:
        - { path: ^/admin, roles: [ROLE_ADMIN] }
        - { path: ^/profile, roles: [IS_AUTHENTICATED_FULLY] }
        - { path: ^/api, requires_channel: https }

The options

They are those of security.access_control, with the same normalisations, so a rule moves across without being rewritten.

Option

path

A regular expression, in the urldecoded format: ^/path to resource/

host, port, ips, methods, route

The obvious matchers

attributes

Request attributes to match, _route among them

request_matcher

A service id, which rules out every other matching option above

roles

The attributes to require. Any one granting is enough

allow_if

An expression. Requires symfony/expression-language

requires_channel

http or https

roles and allow_if given together are combined as AtLeastOneOf: either one granting lets the request through. Naming request_matcher alongside path, host, port, ips, methods, attributes or route raises, rather than quietly ignoring one of them. A rule with nothing in it raises too, which catches the stray - in YAML.

They are not a duplicate of Security's

The two sections are identical option for option, but their scopes differ, and this is the part worth knowing:

security.access_control

access_control.rules

Where it applies

Inside a firewall only

Everywhere

Security's rules feed security.access_map, consumed by a listener that is a link in each firewall's chain. A path outside every firewall can only be guarded here.

When both cover the same path

Both apply. The firewall runs first, at kernel.request priority 8, and this component's listener at 7. The result is the intersection of the permissions.

A rule added here can therefore only tighten, never loosen. That is fail-closed and not dangerous, but it is silent: moving a rule from one key to the other without deleting the original leaves you with both, and the permissions of neither.

Declaring rules on both keys at once raises at compile time. What does not raise is the case above, where a rule is moved rather than duplicated.

requires_channel is enforced once

This is the precision that costs an afternoon if you miss it:

  • with a firewall covering the path, the firewall enforces it,

  • without one, this component's ChannelListener does,

  • never both.

When no rule declares requires_channel, that listener is not even registered.

Roles, and the attributes you can put there

Despite the name, roles takes attributes, not only roles. Anything a voter understands works: a role, an authentication state such as IS_AUTHENTICATED_FULLY, or an attribute of your own that a voter answers.

The name is Security's, kept so a security.yaml moves across unchanged.

Last updated

Was this helpful?