Access Control List (ACL)

The Barebone framework features a built-in Access Control List (ACL) system designed to manage authorization at the application, controller, and action levels. The system enables fine-grained control over which routes are accessible to specific users or groups.

Disclaimer: As noted in the source code, the built-in flat-file ACL system is designed primarily for development, staging, or simple administrative/studio dashboards. It should be used with appropriate caution in highly sensitive production environments.

How it Works

The authentication and authorization process integrates directly into the controller lifecycle via the Barebone\AuthController class. If a controller extends AuthController, it enforces access controls automatically for every action unless explicitly excluded.

The request validation steps are as follows:

  1. Checks if the user is authenticated using the global helper isloggedin(). If not, the request is redirected to the login endpoint (or a reauthentication dialog is triggered if it is an AJAX request).
  2. If the user is authenticated and ACL is globally enabled in application.json, the controller instantiates the Barebone\ACL service.
  3. The service evaluates the current routed application, controller, and action segments against rules stored in barebone/config/acl.json.
  4. Deny-First Principle: The ACL system evaluates Deny rules first. If any rule explicitly denies the user access to the resource, access is blocked immediately. Otherwise, it searches for a matching Allow rule. If no matching Allow rule is found for the user or their group, access is denied.

Core Classes

1. Barebone\ACL

The central manager of the ACL system. It handles loading and saving the ACL definitions, checking user credentials, and validating authorization permissions.

  • IsAllowed(ACL_User $user): Evaluates if the given user is allowed to access the current routed resource.
  • isDenied(ACL_User $user): Checks if there are specific rules that deny the user access.
  • valid_user($username, $password): Validates credentials and returns an ACL_User instance on success, or false on failure. Supports both modern password_verify() and legacy multi-hashing fallback.
  • CRUD methods: addUser(), addGroup(), addRule(), saveUser(), saveGroup(), saveRule(), delete(), and their associated query methods.

2. Barebone\ACL\ACL_User

Represents a user entity in the registry. Properties include id, group_id, username, email, and a session safety hash.

  • Security Note: When instantiated, the user's password is replaced with '********' in memory to prevent accidental exposure of hashed passwords.
  • hashIsValid(): Validates that the user session data has not been tampered with by verifying the hash against the session stored data.

3. Barebone\ACL\ACL_Group

Represents a user group (e.g., Developers, Guests), enabling group-based rule definitions.

4. Barebone\ACL\ACL_Rule

Defines permissions by mapping users or groups to route patterns.

  • application, controller, action: Route segments (supports wildcard * to match all).
  • allow and deny: Booleans indicating permission status.

5. Barebone\ACL\ACL_Authenticator

Provides audit trail logging for authentication attempts. It writes all logins and logouts to barebone/config/acl_log.json and delegates authentication persistence to an implementation of IAuthenticator (such as SessionAuthenticator or CookieAuthenticator).


Configuration

You can enable ACL and customize its behavior in barebone/config/application.json:

{
  "ACL": {
    "enabled": "true",
    "auto_create_guest_session": "false"
  }
}
            
  • enabled: Set to "true" to enforce ACL checks in controllers extending AuthController.
  • auto_create_guest_session: If "true", the framework automatically registers a guest user session (user_00000000000) for unauthenticated visitors.

Usage Examples

Example 1: Protecting a Controller

To secure your application, extend Barebone\AuthController instead of Barebone\Controller:

<?php

use Barebone\AuthController;

class SecureController extends AuthController {

    public function indexAction(array $args = []) {
        $this->layout->title('Secret Area');
        // If the user does not have permission, they will never reach this point
    }
}
            

Example 2: Adding a User and a Rule Programmatically

<?php

use Barebone\ACL;
use Barebone\ACL\ACL_User;
use Barebone\ACL\ACL_Rule;

$acl = new ACL();

// 1. Create a new user
$user = new ACL_User([
    'username' => 'alice',
    'password' => 'secret123',
    'email'    => 'alice@example.com',
    'group_id' => 'group_59f4ec25d7748'
]);
$acl->addUser($user);

// 2. Grant Alice access to all controllers in the 'admin' application
$rule = new ACL_Rule([
    'user_id'     => $user->id,
    'group_id'    => '',
    'application' => 'admin',
    'controller'  => '*',
    'action'      => '*',
    'allow'       => true,
    'deny'        => false
]);
$acl->addRule($rule);
            

Example 3: Querying the ACL Registry

<?php

$acl = new ACL();

// Retrieve all configured rules
$rules = $acl->getRules();

foreach ($rules as $rule) {
    echo "Rule ID: " . $rule->id . "\n";
    echo "Applies to User ID: " . ($rule->user_id ?: 'N/A') . "\n";
    echo "Target: " . $rule->application . "/" . $rule->controller . "/" . $rule->action . "\n";
    echo "Access: " . ($rule->allow ? 'Allow' : 'Deny') . "\n\n";
}