PHPackages                             typo3/access-control - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. typo3/access-control

ActiveLibrary[Authentication &amp; Authorization](/categories/authentication)

typo3/access-control
====================

TYPO3 Access Control Component.

0.1.1(6y ago)5985MITPHPPHP ~7.2

Since Dec 2Pushed 5y ago4 watchersCompare

[ Source](https://github.com/TYPO3incubator/access-control)[ Packagist](https://packagist.org/packages/typo3/access-control)[ Docs](https://typo3.org)[ RSS](/packages/typo3-access-control/feed)WikiDiscussions master Synced 6d ago

READMEChangelogDependencies (5)Versions (4)Used By (0)

TYPO3 Access Control
====================

[](#typo3-access-control)

[![Build](https://camo.githubusercontent.com/fc1d73c3b708f841426037409e4a9eeeeb8849fbc81368b6528f1241a5995166/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f776f726b666c6f772f7374617475732f5459504f332f6163636573732d636f6e74726f6c2f504850253230436f6d706f736572)](https://github.com/TYPO3/access-control/actions)[![Coverage](https://camo.githubusercontent.com/a2ac70872463fe2c8214ea11bff66b2f5c4534da230eb93ade046e79d414988d/68747470733a2f2f696d672e736869656c64732e696f2f636f646163792f636f7665726167652f39333164346639336462386534316433396133313734643561623834633761632f6d61737465722e737667)](https://app.codacy.com/project/typo3-initiatives/access-control/dashboard)[![Code Quality](https://camo.githubusercontent.com/a1c5515f18605d1c174a2b81b98d447713959d82698ab2eb21aae9135a82847d/68747470733a2f2f696d672e736869656c64732e696f2f636f646163792f67726164652f39333164346639336462386534316433396133313734643561623834633761632f6d61737465722e737667)](https://app.codacy.com/project/typo3-initiatives/access-control/dashboard)

Installation
------------

[](#installation)

Use composer to install this extension in your project:

```
composer require typo3/access-control
```

Concepts
--------

[](#concepts)

Access rights are granted to users through the use of policies. The underlying model is known as [attribute-based access control](https://en.wikipedia.org/wiki/attribute-based_access_control) (ABAC). It makes use of boolean expressions which decide whether an access request is granted or not. Such a request typically contains the *resource*, *action*, *subject* and *environment* attributes. This extension implements a lightweight policy language and evaluation framework based on [Jiang, Hao &amp; Bouabdallah, Ahmed (2017)](https://www.researchgate.net/publication/325873238).

The policy structure consists of *policy sets*, *policies* and *rules*. A *policy set* is a set of *policies* which in turn has a set of *rules*. Because not all policies are relevant to a given request every element includes the notion of a *target*. It determines whether a policy is applicable to a request by setting constraints on attributes using boolean expressions.

A policy is *applicable* if the access request satisfies the target. If so, its childrend are evaluated and the results returned by those children are combined using a combining algorithm. Otherwise, the policy is skipped without further examining its children and returns a *not applicable* *decision*.

The *rule* is the fundamental unit that can generate a conclusive *decision*. The *condition* of a *rule* is a more complex boolean expression that refines the applicability beyond the predicates specified by its *target*, and is optional. If a request satisfies both the *target* and *condition* of a *rule*, then the *rule* is applicable to the request and its *eﬀect* is returned as its *decision*. Otherwise, *not applicable* is returned.

Each *rule*, *policy* or *policy set* has an unique identifier and *obligations* which represent the operations to perform after granting or denying an access request.

Attributes
----------

[](#attributes)

A request typically contains the following attributes:

AttributeDescription`resource`Is an entity to be protected from unauthorized use. The *resource* is directly provided by the access request. See also `TYPO3\AccessControl\Attribute\ResourceAttribute`.`subject`Represents the entity requesting to perform an operation upon the *resource*. It is provided indirectly through the given context of the policy decision point and can not modifed or set by the access request directly. See also `TYPO3\AccessControl\Attribute\SubjectAttribute`.`action`The operations to be performed on the *resource*. Like the *resource* it is also provided by the access request. See also `TYPO3\AccessControl\Attribute\ActionAttribute`.To define your own attributes, you must derive them from one of the corresponding classes:

```
namespace App\Security\AccessControl\Attribute;

use TYPO3\AccessControl\Attribute\PrincipalAttribute;

class RoleAttribute extends PrincipalAttribute
{
  public function __construct(string $identifier)
  {
    parent::__construct($identifier);
  }
}
```

Expressions
-----------

[](#expressions)

Expressions are used to decied whether a policy is applicable to a request or not. Therefore a so called expression resolver has to be implemented. For example, by using the [expression language component](https://symfony.com/doc/current/components/expression_language):

```
namespace App\Security\AccessControl\Expression;

use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use TYPO3\AccessControl\Expression\ResolverInterface;

class ExpressionLanguageResolver implements ResolverInterface
{
  private $expressionLanguage;

  public function __construct()
  {
    $this->expressionLanguage = new ExpressionLanguage();
    // register a custom function `hasAuthority`
    $this->expressionLanguage->register(
      'hasAuthority', function () {
        // not implemented, we only use the evaluator
      },
      function ($variables, ...$arguments) {
        if (count($arguments) == 1) {
          // checks if the subject has the given principal
          return isset($variables['subject']->principals[$arguments[0]]);
        }
        return false;
      }
    );
  }

  public function validate(string $expression): void
  {
    // only allow the attributes `subject`, `resource` and `action`
    $this->expressionLanguage->parse($expression, ['subject', 'resource', 'action']);
  }

  public function evaluate(string $expression, array $attributes): bool
  {
    return $this->expressionLanguage->evaluate($expression, $attributes);
  }
}
```

Policies
--------

[](#policies)

Policies can be defined declaratively. For example, by using YAML and the policy factory:

```
---
description: 'Root policy set.'
algorithm: highestPriority
policies:
  Admin:
    target: 'hasAuthority("typo3:security:principal:admin")'
    description: 'Administrator policy'
    priority: 100
    rules:
      -
        effect: permit
  Default:
    description: 'Deny everything per default.'
    rules:
      -
        obligation:
          deny:
            Feedback: ['Access denied.']
```

```
use App\Security\AccessControl\Expression\ExpressionLanguageResolver;
use Symfony\Component\Yaml\Parser;
use TYPO3\AccessControl\Policy\PolicyFactory;

$resolver = new ExpressionLanguageResolver();
$factory = new PolicyFactory();
$parser = new Parser();

$policy = $factory->build(
  $parser->parseFile('/path/to/policies.yaml'),
  $resolver
);
```

A **policy set** is a set of *policy sets* and *policies*. It has the following configuration fields:

FieldDescription`description`Optional description of the policy set.`target`Optional boolean expression indicating the *resource*, *action*, *subject* and *environment attributes* to which the *policy set* is applied. Default is `true`.`alogrithm`Optional name of a *combining algorithm* to compute the final decision according to the results returned by its child policies, either `denyOverride`, `permitOverride`, `firstApplicable` or `highestPriority`. Default is `firstApplicable`.`priority`Optional number indicating the weight of the *policy set* when its decision conﬂicts with other policies under the `highestPriority` algorithm. Default is `1`.`obligation`Optional actions to take in case a particular conclusive decision (*permit* or *deny*) is reached.`policies`Required set of child policies (*policy sets* and *policies*).With configuration fields similar to a *policy set* a **policy** is a set of *rules*:

FieldDescription`description`Optional description of the policy.`target`Optional boolean expression indicating the *resource*, *action*, *subject* and *environment attributes* to which the *policy* is applied. Default is `true`.`alogrithm`Optional name of a *combining algorithm* to compute the final decision according to the results returned by its child rules, either `denyOverride`, `permitOverride`, `firstApplicable` or `highestPriority`. Default is `firstApplicable`.`priority`Optional number indicating the weight of the *policy* when its decision conﬂicts with other policies under the `highestPriority` algorithm. Default is `1`.`obligation`Optional actions to take in case a particular conclusive decision (*permit* or *deny*) is reached.`rules`Required set of child *rules*.Unlike a *policy set* or a *policy*, a **rule** does not contain any leaf nodes:

FieldDescription`target`Optional boolean expression indicating the *resource*, *action*, *subject* and *environment attributes* to which the *policy* is applied. Default is `true`.`effect`Optional returned decision when the rule is applied, either `permit` or `deny`. Default is `deny`.`condition`Optional boolean expression that specifies the condition for applying the rule. In comparison to a `target`, a `condition` is typically more complex. If either the `target` or the `condition` is not satisfied, a *not applicable* would be taken as the result instead of the specified `effect`. Default is `true`.`priority`Optional number indicating the weight of the *rule* when its decision conﬂicts with other rules under the `highestPriority` algorithm. Default is `1`.`obligation`Optional actions to take in case a particular conclusive decision (*permit* or *deny*) is reached.Policies may conflict and produce different *decisions* for the same request. To resolve this four kinds of **combining algorithms** are provided. Each algorithm represents a different way for combining multiple local *decisions* into a single global *decision*:

AlgorithmDescription`permitOverrides`Returns *permit* if any *decision* evaluates to *permit* and returns *deny* if all *decisions* evaluate to *deny*.`denyOverrides`Returns *deny* if any *decision* evaluates to *deny* and returns *permit* if all *decisions* evaluate to *permit*.`firstApplicable`Returns the first *decision* that evaluates to either of *permit* or *deny*.`highestPriority`Returns the highest priority *decision* that evaluates to either of *permit* or *deny*. If there are multiple equally highest priority *decisions* that conflict, then *deny overrides* algorithm would be applied among those highest priority *decisions*.Please note that for all of these *combining algorithms*, *not applicable* is returned if not any of the children is applicable.

There is also formal description of the schema for the policy language which can be found [here](resources/schema.json).

Authorisation
-------------

[](#authorisation)

To perform an access request the *policy decision point* has to be used. It evaluates all policies and returns a *decision* either of *permit*, *deny* or *not applicable*:

```
use App\Security\AccessControl\Attribute\ActionAttribute;
use App\Security\AccessControl\Attribute\ResourceAttribute;
use Symfony\Component\EventDispatcher\EventDispatcher;
use TYPO3\AccessControl\Policy\PolicyDecisionPoint;
use TYPO3\AccessControl\Policy\PolicyInformationPoint;

$dispatcher = new EventDispatcher();

// creeates an policy information point
$policyInformationPoint = new PolicyInformationPoint(
  $dispatcher
);

// creates a policy decision point
$policyDecisionPoint = new PolicyDecisionPoint(
  $dispatcher,
  $policy,
  $policyInformationPoint
);

// perform an authorization request
$policyDecision = $policyDecisionPoint->authorize(
  [
    // concrete resource to access
    'resource' => new ResourceAttribute('identifier'),
    // concrete action on resource
    'action' => new ActionAttribute()
  ]
);

if (!$policyDecision->isApplicable()) {
  // access request is not applicable
}

// process determining policy rule
$determinigRule = $policyDecision->getRule();

foreach ($policyDecision->getObligations() as $obligation) {
  // process obligations
}

if ($policyDecision->getValue() === PolicyDecision::PERMIT)
  // access is granted
}

// access is denied otherwise
```

To receive all operations which should be performed after denying or granting an access request the event `\TYPO3\AccessControl\Event\PolicyDecisionEvent` has to be used:

```
namespace App\Security\AccessControl\EventListener;

use TYPO3\AccessControl\Event\PolicyDecisionEvent;

class PolicyDecisionListener
{
    public function __invoke(PolicyDecisionEvent $event)
    {
        // ...
    }
}
```

To provide additional data for an attribute before an access request the event `\TYPO3\AccessControl\Event\AttributeRetrievalEvent` can be used:

```
namespace App\Security\AccessControl\EventListener;

use TYPO3\AccessControl\Event\AttributeRetrievalEvent;

class AttributeRetrievalListener
{
    public function __invoke(AttributeRetrievalEvent $event)
    {
        // ...
    }
}
```

To provide principals for the subject attribute the separate event `\TYPO3\AccessControl\Event\SubjectRetrievalEvent` has to be used:

```
namespace App\Security\AccessControl\EventListener;

use TYPO3\AccessControl\Attribute\PrincipalAttribute;
use TYPO3\AccessControl\Event\SubjectRetrievalEvent;

class SubjectRetrievalListener
{
    public function __invoke(SubjectRetrievalEvent $event)
    {
        // Adds administrator principal
        $event->addPrincipal(new PrincipalAttribute('administrator'));
    }
}
```

Design Principals
-----------------

[](#design-principals)

Whenever possible the authorization logic should be part of a policy. Thus it's auditable and changeable. For reasons of performance or complexity it might be not possible. Then it's recommended to extend the expression language with a custom function if possible.

Development
-----------

[](#development)

Development for this extension is happening as part of the [TYPO3 persistence initiative](https://typo3.org/community/teams/typo3-development/initiatives/persistence/).

###  Health Score

25

—

LowBetter than 37% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity18

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity44

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~2 days

Total

2

Last Release

2357d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/165630?v=4)[Benni Mack](/maintainers/bmack)[@bmack](https://github.com/bmack)

![](https://avatars.githubusercontent.com/u/402145?v=4)[Oliver Hader](/maintainers/ohader)[@ohader](https://github.com/ohader)

---

Top Contributors

[![witrin](https://avatars.githubusercontent.com/u/1394346?v=4)](https://github.com/witrin "witrin (2 commits)")

---

Tags

abacaccess-controlauthorizationpbacpermissionsecuritysecuritytypo3abacPolicypbac

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/typo3-access-control/health.svg)

```
[![Health](https://phpackages.com/badges/typo3-access-control/health.svg)](https://phpackages.com/packages/typo3-access-control)
```

###  Alternatives

[spatie/laravel-permission

Permission handling for Laravel 12 and up

12.9k89.8M1.0k](/packages/spatie-laravel-permission)[hwi/oauth-bundle

Support for authenticating users using both OAuth1.0a and OAuth2 in Symfony.

2.4k21.5M69](/packages/hwi-oauth-bundle)[lusitanian/oauth

PHP 7.2 oAuth 1/2 Library

1.1k23.2M121](/packages/lusitanian-oauth)[bezhansalleh/filament-shield

Filament support for `spatie/laravel-permission`.

2.8k2.9M88](/packages/bezhansalleh-filament-shield)[casbin/casbin

a powerful and efficient open-source access control library for php projects.

1.3k1.4M54](/packages/casbin-casbin)[matricali/akamai-token-auth

This library provides necessary logic to generate Akamai edge authorization token and signed URL.

111.2M](/packages/matricali-akamai-token-auth)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
