Understanding access control in Authelia: default_policy as a safety net, rules with domain, subject, resources, methods, and networks criteria, and the first match wins evaluation order for applying bypass, one_factor, and two_factor policies.

In episode 5, you set up the authentication backend: determining who can log in with argon2id password hashes, whether from the users_database.yml file or LDAP/Active Directory. Now Authelia can answer the first question: who are you? There's one more question that's just as important: where are you allowed to go?
The answer lives in the access_control section, the heart of authorization in Authelia. Here's an analogy: authentication is like the guard at the building entrance checking your ID, while authorization is the list of rooms you may enter after passing the check. In this episode you'll build that list precisely, starting from the default_policy safety net, the anatomy of each rule, up to the evaluation order that's often the source of subtle bugs.
Imagine a building where every door is locked by default. You can only enter rooms that were deliberately opened for you. That's the philosophy of default_policy: the policy that applies when no rule matches the request.
There are four values you can use:
deny: block all access. Authelia's main recommendation.bypass: allow without any authentication.one_factor: password only.two_factor: password plus a second method (TOTP, WebAuthn, or Duo).access_control:
default_policy: deny
rules: []Important
Always start with default_policy: deny (fail closed). It's safer to lock all doors and then open the ones that need it, than to open everything and close them one by one. A misconfiguration in fail-open mode can expose your services without authentication.
With this pattern, every new service you add is automatically locked until you write an explicit rule to open it. No access happens by accident.
Every entry in rules is a list of criteria plus one policy. All present criteria must match (AND logic), and only then is the policy applied. The available criteria are: domain, domain_regex, subject, resources, methods, networks, and query.
The most basic criterion: matching the requested domain name. domain supports wildcards, while domain_regex uses RE2-style regular expressions (the Go dialect) for wilder patterns.
- domain: "*.example.com"
policy: one_factorThe first rule matches all example.com subdomains. The second rule matches domains like dev-12.example.com, useful when you have many dynamic environments.
subject filters by user or group, with the user: or group: prefix. Authelia supports AND/OR logic: a list inside a list means AND, an outer list means OR.
- domain: "dev.example.com"
resources: ["^/groups/dev/.*$"]
subject:
- ["group:dev", "user:john"]
- "group:admins"
policy: two_factorThe rule above matches if the user is a member of the dev group AND is named john, OR if the user is a member of the admins group. Outside those two combinations, the rule doesn't match.
resources: matches the request path and query with an RE2-style regex. For example ^/api/.*$ matches all paths starting with /api/.methods: restricts to specific HTTP methods such as GET, POST, or DELETE. Useful for example to leave GET open but require authentication for POST.query: an advanced criterion for inspecting query parameters with the equal, not equal, present, absent, pattern, and not pattern operators. For basic needs, the official documentation recommends using resources alone.networks matches the origin IP address — a single IP, a CIDR range, or a network group name defined separately. A classic pattern: an internal service only needs one_factor when accessed from a VPN or LAN, but requires two_factor when accessed from the internet.
bypass: pages that must stay open, like public pages or static assets.one_factor: services that are safe enough with a password. Convenience first.two_factor: sensitive services: admin panels, infrastructure dashboards, or personal data. Requires password plus a second method.deny: hard block, usually for specific services for specific user groups.Remember the logic: one_factor only delays an attack until your password leaks. two_factor adds a second layer so a leaked password alone isn't enough to get in.
This is the most misunderstood point. Authelia evaluates rules from top to bottom, and the first matching rule determines the policy — the request stops being evaluated there. If no rule matches, then default_policy is used.
The practical implication: put more specific rules at the top, and general (catch-all) rules below. If the order is reversed, the general rule will swallow the specific rules behind it — just like a list of bouncers at a club: whoever passes the first door won't get checked by the next.
access_control:
default_policy: deny
rules:
- domain: "admin.example.com"
subject: "group:admins"
policy: two_factor
- domain: "*.example.com"
policy: one_factorWarning
If you reverse the two rules above, the admin.example.com subdomain loses to the *.example.com rule that matches first, so the admin panel is only protected by one_factor. Always write the most specific rules at the top, then test every change.
When building a real configuration, three patterns almost always appear. A complete example:
access_control:
default_policy: deny
rules:
- domain: "example.com"
resources: ["^/(assets|static|images|favicon\\.ico)/?.*$"]
policy: bypass
- domain: "api.example.com"
policy: one_factor
- domain: "admin.example.com"
subject: "group:admins"
policy: two_factor
- domain: "*.example.com"
policy: one_factortwo_factor because the impact of compromise is greatest.Caution
Bypassing static assets means the data in those paths can be accessed by anyone. Never put sensitive data, configuration, or backups under a bypassed path. Overly broad bypass rules are one of the most common configuration mistakes in the real world.
Key points of this episode:
default_policy: deny is the safety net that locks all services by default.domain, domain_regex, subject, resources, methods, networks, and query criteria, plus one policy.bypass for public, one_factor for general services, two_factor for sensitive ones, deny for hard blocks.Now you can determine who can access what. But there's one follow-up question: after logging in, how does Authelia remember who you are on every subsequent request? The answer lies in the session mechanism — the topic you'll dissect in episode 7 on session management, from cookies to session storage in Redis.