Users and roles
Anvil stores roles and their permissions in the database, per tenant. Users and roles are managed in the panel under Access. Login, sessions and passwords are CodeIgniter Shield; Anvil adds roles, authorization, single sign-on and two-factor authentication.
Enabling the administration
Section titled “Enabling the administration”use Anvil\Access\Access;
public function resources(): array{ return [InvoiceResource::class, ...Access::resources()];}
public function pages(): array{ return [Dashboard::class, ...Access::pages()];}| Method | Returns |
|---|---|
Access::resources() |
UserResource, RoleResource; ApiClientResource as well when the API is used (Config\Anvil::$apiEndpoints or $apiPanels not empty, see API) |
Access::pages() |
InboxPage (tasks), ProfilePage, WorkflowsPage (see Workflows) |
A role belongs to one tenant and has
- a list of permissions, e.g.
invoices.view, or a wildcard likeinvoices.*(everything before the first dot), - or full access (
is_super), which grants every permission, including permissions of resources added later.
A user can have several roles. Their permissions in a tenant are the union of the permissions of their roles in that tenant. Roles of other tenants have no effect.
The role editor lists
- the panel permissions (
Panel::permission(), e.g.admin.access, needed to enter a panel at all), - the abilities of every resource (
view,create,update,delete,history, andexportfor exportable resources), - the permissions of actions, bulk actions and relation actions,
- the permissions of workflows (overrides and transition actors),
- the permissions of pages,
- the custom permissions from
Config\Anvil::$permissions:
public array $permissions = [ 'Invoices' => ['invoices.export_datev' => 'Export to DATEV'],];php spark anvil:permissions prints the same list, e.g. to plan roles or
for a review.
With single sign-on configured, the role editor also has a field per provider for the groups of the identity provider that grant the role.
Protection against privilege escalation
Section titled “Protection against privilege escalation”| Rule | Error |
|---|---|
| A user can only add permissions to a role that they hold themselves | permissions |
| Only users with full access can create, change or grant full access roles | is_super |
| A role can only be deleted by users who could grant all of its permissions | 403 |
| A user can only assign roles whose permissions they hold themselves | roles |
| Users cannot deactivate or remove their own account | active, record |
| Users with permissions the editor does not hold (or full access) cannot be edited, removed or have TOTP reset | roles, 403 |
| Username and active state apply in every tenant of the user: they change only if the editor may manage the user in each of them | username |
| Mapping SSO groups to a role needs the right to grant the whole role | sso_<provider> |
Permissions a role already has can be kept when editing, even if the editor does not hold them.
The user list shows the members of the current tenant. Creating a user
- creates the Shield account with e-mail and initial password,
- adds the user to the current tenant,
- marks the password for change at the first sign-in,
- assigns the selected roles.
The minimum length of the initial password is
Config\Auth::$minimumPasswordLength. The e-mail address cannot be changed
afterwards.
Removing a user removes their roles and membership in the current tenant. The account itself is only deleted when the user belongs to no other tenant.
The action Reset two-factor authentication on a user disables their TOTP, see Two-factor authentication.
All changes are written to the audit log, e.g.
user.created, user.roles_changed, role.permissions_changed,
role.sso_groups_changed, tenant.member_added, tenant.member_removed
and the record changes.
Profile and password change
Section titled “Profile and password change”The profile page (/<panel>/profile) shows the account and the roles in
the current tenant, and lets every user change their password and set up
two-factor authentication.
While a password change is pending (initial password, or forced by an
administrator), the anvil-password filter (part of every panel’s
filters) redirects every page to the profile page, and the component
endpoint only accepts the password form.
The password policy is Shield’s (Config\Auth::$minimumPasswordLength,
$passwordValidators). The AppStarter sets the minimum length to 12
characters. Consider enabling PwnedValidator – it sends a hash prefix of
the password to haveibeenpwned.com, so check that this is acceptable for
your environment.
Anvil reads Shield’s settings from the application’s Config\Auth
(Anvil\Support\ShieldConfig::auth()), so the views and layout configured
there also apply to the login and the TOTP pages.
Shield groups
Section titled “Shield groups”With Config\Anvil::$shieldGroupFallback = true (default), the groups and
permissions of Config\AuthGroups are granted in addition to the database
roles. This helps while setting up an application. Disable it once all
permissions are maintained as roles, so that there is only one source of
truth. With Config\Anvil::$rbac = false the database roles are not used at
all and only Shield’s groups apply.
Bootstrapping
Section titled “Bootstrapping”php spark anvil:install creates the first administrator (in the Shield
group superadmin, option --group) and the role Administrator with full
access in the first tenant, and assigns it to them.