The Authorization plugin provides fine-grained access control for HTTP requests based on paths, methods, users, roles, and CSS selectors. It supports DOM-aware authorization, allowing you to control access to specific HTML elements within documents.
The authorization plugin evaluates incoming requests against a set of rules defined in an HTML configuration file. It integrates seamlessly with the basic-auth plugin to enforce authentication and authorization policies.
${username}
in selectors for user-specific matching/users/:username/*
)The authorization plugin is configured as part of the plugin pipeline in your host configuration:
<li itemprop="plugin" itemscope itemtype="https://rustybeam.net/schema/Plugin">
<span itemprop="library">file://./plugins/authorization.so</span>
<meta itemprop="authfile" content="file://./auth/users.html">
</li>
Parameter | Type | Required | Description |
---|---|---|---|
authfile |
String (URL) | Yes | Path to the HTML file containing users and authorization rules. Supports file:// URLs. |
Authorization rules are defined using the AuthorizationRule schema in your auth configuration file. Each rule specifies:
Rules are evaluated with the following priority (highest to lowest):
:username
parameterThe authorization plugin supports CSS selector-based access control, allowing you to restrict access to specific HTML elements within documents. This feature works in conjunction with the selector-handler plugin.
Range: selector={css-selector}
headerThe plugin follows CSS selector semantics:
p
allows access to all paragraph elementsp.content
or article p
are allowed if p
is allowedThe authorization plugin supports dynamic username placeholders in CSS selectors, allowing you to create user-specific authorization rules without having to define separate rules for each user.
You can use ${username}
as a placeholder in selector rules, which will be replaced with the authenticated user's username at runtime:
<tr itemscope itemtype="https://rustybeam.net/schema/AuthorizationRule">
<td itemprop="username">user</td>
<td itemprop="path">/*</td>
<td itemprop="selector">li:has(meta[content="${username}"])</td>
<td itemprop="method">GET</td>
<td itemprop="action">allow</td>
</tr>
This rule allows users with the "user" role to access only <li>
elements that contain a <meta>
tag with their username in the content attribute.
${username}
, ${ username }
, ${ username}
${username}
placeholders in a single selectoruser@example.com
)${username}
are automatically skipped for anonymous users<!-- HTML structure -->
<ul id="todos">
<li><meta content="alice@example.com">Alice's task</li>
<li><meta content="bob@example.com">Bob's task</li>
</ul>
<!-- Authorization rule -->
<tr itemscope itemtype="https://rustybeam.net/schema/AuthorizationRule">
<td itemprop="username">user</td>
<td itemprop="path">/todos/</td>
<td itemprop="selector">li:has(meta[content="${username}"])</td>
<td itemprop="method">GET</td>
<td itemprop="action">allow</td>
</tr>
With this rule, when alice@example.com
requests the todo list, she will only see her own tasks.
<!-- Authorization rule for user-specific form fields -->
<tr itemscope itemtype="https://rustybeam.net/schema/AuthorizationRule">
<td itemprop="username">user</td>
<td itemprop="path">/profile/</td>
<td itemprop="selector">.user-${username}-section</td>
<td itemprop="method">*</td>
<td itemprop="action">allow</td>
</tr>
This allows users to access only elements with their username in the class name.
${username}
placeholder is replaced with the exact username as authenticated by the basic-auth or oauth2 plugin. For security, quotes and backslashes in usernames are automatically escaped.
Typical pipeline order:
1. basic-auth.so → Authenticates user
2. authorization.so → Checks permissions
3. selector-handler.so → Processes selector requests
4. file-handler.so → Serves files
5. access-log.so → Logs requests
Here's a complete example of an authorization configuration file:
<!DOCTYPE html>
<html>
<head>
<title>Authorization Configuration</title>
</head>
<body>
<!-- Credential definitions -->
<table>
<thead>
<tr>
<th>Username</th>
<th>Password</th>
<th>Roles</th>
<th>Encryption</th>
</tr>
</thead>
<tbody>
<tr itemscope itemtype="https://rustybeam.net/schema/Credential">
<td itemprop="username">admin</td>
<td itemprop="password">admin123</td>
<td>
<ul>
<li itemprop="role">administrators</li>
<li itemprop="role">users</li>
</ul>
</td>
<td itemprop="encryption">plaintext</td>
</tr>
</tbody>
</table>
<!-- Authorization rules -->
<table>
<thead>
<tr>
<th>User/Role</th>
<th>Path</th>
<th>Selector</th>
<th>Methods</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<!-- Administrators have full access -->
<tr itemscope itemtype="https://rustybeam.net/schema/AuthorizationRule">
<td itemprop="role">administrators</td>
<td itemprop="path">/*</td>
<td></td>
<td>
<ul>
<li itemprop="method">GET</li>
<li itemprop="method">PUT</li>
<li itemprop="method">POST</li>
<li itemprop="method">DELETE</li>
</ul>
</td>
<td itemprop="action">allow</td>
</tr>
<!-- Allow specific selectors for anonymous users -->
<tr itemscope itemtype="https://rustybeam.net/schema/AuthorizationRule">
<td itemprop="username">*</td>
<td itemprop="path">/*</td>
<td itemprop="selector">h1</td>
<td itemprop="method">GET</td>
<td itemprop="action">allow</td>
</tr>
</tbody>
</table>
</body>
</html>
<tr itemscope itemtype="https://rustybeam.net/schema/AuthorizationRule">
<td itemprop="username">:username</td>
<td itemprop="path">/users/:username/*</td>
<td itemprop="method">*</td>
<td itemprop="action">allow</td>
</tr>
<tr itemscope itemtype="https://rustybeam.net/schema/AuthorizationRule">
<td itemprop="username">*</td>
<td itemprop="path">/guestbook/</td>
<td itemprop="selector">ul.entries</td>
<td itemprop="method">POST</td>
<td itemprop="action">allow</td>
</tr>
<tr itemscope itemtype="https://rustybeam.net/schema/AuthorizationRule">
<td itemprop="username">*</td>
<td itemprop="path">/*</td>
<td itemprop="selector">.private</td>
<td itemprop="method">GET</td>
<td itemprop="action">deny</td>
</tr>
<tr itemscope itemtype="https://rustybeam.net/schema/AuthorizationRule">
<td itemprop="username">user</td>
<td itemprop="path">/dashboard/</td>
<td itemprop="selector">[data-user="${username}"]</td>
<td itemprop="method">*</td>
<td itemprop="action">allow</td>
</tr>
This pattern allows users to only access elements that have their username in a data attribute, enabling fine-grained content filtering without creating individual rules for each user.
The authorization plugin relies on the basic-auth plugin to authenticate users. The basic-auth plugin sets the authenticated_user
metadata, which the authorization plugin uses to identify the user.
The selector-handler plugin processes Range headers with CSS selectors. The authorization plugin intercepts these requests to enforce element-level access control.
Issue | Cause | Solution |
---|---|---|
403 Forbidden for all requests | No matching authorization rules | Add appropriate rules for your users/paths |
Authorization not working | Plugin order incorrect | Ensure authorization comes after basic-auth |
Selector authorization failing | File not found or not HTML | Check file paths and ensure target is HTML |
Anonymous access not working | Basic-auth rejecting anonymous | Use directory plugin or configure basic-auth appropriately |
${username} not being replaced | User is anonymous or placeholder syntax incorrect | Ensure user is authenticated and use exact syntax: ${username} |
Email addresses in ${username} not matching | Special characters being escaped incorrectly | Check logs for the exact selector being used; @ and . are preserved |
Run the server with -v
flag to see detailed authorization decisions:
./rusty-beam -v config.html