This is an experimental feature that is not enabled or enforced yet
Permissions limit the things a user has access to or can control. Permissions are attached to groups, of which a user can be a member. The combined permissions of all groups a user is a member of decides what a user can and cannot see or control.
Permissions do not apply to the user that is flagged as "owner". This user will always have access to everything.
General permission structure
Policies are dictionaries that at the root level consist of different categories of permissions. In the current implementation this is limited to just entities.
Each category can further split into subcategories that describe parts of that category.
If a category is omitted, the user will not have permission to that category.
When defining a policy, any dictionary value at any place can be replaced with
True means that permission is granted and
None means use default, which is deny access.
Entity permissions can be set on a per entity and per domain basis using the subcategories
domains. You can either grant all access by setting the value to
True, or you can specify each entity individually using the "read", "control", "edit" permissions.
The system will return the first matching result, based on the order:
If a user is a member of multiple groups, the groups permission policies will be combined into a single policy at runtime. When merging policies, we will look at each level of the dictionary and compare the values for each source using the following methodology:
- If any of the values is
True, the merged value becomes
- If any value is a dictionary, the merged value becomes a dictionary created by recursively checking each value using this methodology.
- If all values are
None, the merged value becomes
Let's look at an example:
Once merged becomes
We currently have two different permission checks: can the user do the read/control/edit operation on an entity, and is the user an admin and thus allowed to change this configuration setting.
Certain APIs will always be accessible to all users, but might offer a limited scope based on the permissions, like rendering a template.
To check a permission, you will need to have access to the user object. Once you have the user object, checking the permission is easy.
The context object
All service calls, fired events and states in Home Assistant have a context object. This object allows us to attribute changes to events and services. These context objects also contain a user id, which is used for checking the permissions.
It's crucial for permission checking that actions taken on behalf of the user are done with a context containing the user ID. If you are in a service handler, you should re-use the incoming context
call.context. If you are inside a WebSocket API or Rest API endpoint, you should create a context with the correct user:
If a permission check fails
When you detect an anauthorized action, you should raise the
homeassistant.exceptions.Unauthorized exception. This exception will cancel the current action and notifies the user that their action is unauthorized.
Unauthorized exception has various parameters, to identify the permission check that failed. All fields are optional.
| # Not all actions have an ID (like adding config entry) | # We then use this fallback to know what category was unauth
|context||The context of the current call.|
|user_id||The user ID that we tried to operate on.|
|entity_id||The entity ID that we tried to operate on.|
|config_entry_id||The config entry ID that we tried to operate on.|
|perm_category||The permission category that we tested. Only necessary if we don't have an object ID that the user tried to operate on (like when we create a config entry).|
|permission||The permission that we tested, ie |
Securing a service call handler
Service calls allow a user to control entities or with the integration as a whole. A service call uses the attached context to see which user invoked the command. Because context is used, it is important that you also pass the call context to all service calls.
All services that are registered via the entity component (
component.async_register_entity_service()) will automatically have their permissions checked.
Checking entity permissions
Your service call handler will need to check the permissions for each entity that it will act on.
Checking admin permission
Starting Home Assistant 0.90, there is a special decorator to help protect services that require admin access.
Securing a REST API endpoint
Securing a Websocket API endpoint
Verifying permissions in a Websocket API endpoint can be done by accessing the
connection.user. If you need to check admin access, you can use the