Attribute Authorization Manager#
Introduction#
The Attribute authorization manager allows fine-grained, per-attribute authorization of:
- SCIM Resources (Users, Devices, Delegations).
- GraphQL API operations ( User Management , Dynamic Clients , Database Clients , Granted Authorization ).
- The OAuth 2.0 UserInfo endpoint .
The Attribute authorization manager can authorize attributes defined in ResourceAttributes subclasses, including UserInfo claims represented as attributes. Per-attribute authorization means that with this authorization manager one can configure to allow or deny reading or writing every attribute separately.
When an attribute is denied for a write request (create, update or delete) then the whole request is denied.
When an attribute is denied for a read request then just this attribute is filtered out from the response but the rest of the response is returned.
Usage and Configuration#
At the heart of this authorization manager is the option to configure rule lists and rules. The configuration of rule lists and rules defines how an attribute is authorized. First, the Attribute authorization manager tries to match a request with a rule list. If a match is found then rules from the matched rule list are used. Second, all the rules (from the first matched rule list) are tried to be matched with each attribute individually. The first rule that is matched is applied. If none of the rules (in the first matched rule list) match, the rule list default enforcement restrictions are applied. The second part (where attributes are matched with rules) is done to each attribute individually. When defining rule lists and rules, it’s crucial to remember that the order is important because only the first matching rule list and only the first matching rule are applied.
Rule Lists#
The rule list configuration comprises five settings: name, description, select-rule-list-when setting, enforcement restrictions and a rule list with one or more rules.
| Setting | Description |
|---|---|
name | Rule list name |
description | Rule list description |
select-rule-list-when | Requirements used to find matching rule-lists |
enforcement-restrictions | Enforcement restriction |
rule | List of rules |

The select-rule-list-when Configuration Setting#
If a request matches the requirements in select-rule-list-when setting of a rule list then all attributes will be authorized using this rule list.
The select-rule-list-when configuration comprises three settings: context requirement, claim requirements, and scope requirement.
| Setting | Description |
|---|---|
scope-requirement | Optional list of scopes an access token must contain in order for a rule list to be matched. |
claim-requirement | Optional list of claims and their values an access token must contain in order for a rule list to be matched |
context-requirement | The list of contexts rule-list is relevant in. |
Only the context requirement is mandatory out of the three.
Context requirement is a list of contexts the rule list can be applied to. It can contain these values:
user-management-scim: the rule list can be applied for all requests in SCIM endpoints.user-management-graphql: the rule list can be applied for all user management requests in the GraphQL endpoint.dcr-graphql: the rule list can be applied for all requests in the GraphQL Dynamic Client Registration endpoint.db-clients: the rule list can be applied for all requests in the GraphQL Database Clients endpoint.openid-userinfo: the rule list can be applied for all requests in the UserInfo endpoint.granted-authorization: the rule list can be applied to Granted Authorization GraphQL API operations.
Enforcement Restrictions#
Enforcement restrictions comprise three settings.
| Setting | Description |
|---|---|
default-allow-read | Boolean indicating whether an attribute in read requests should be allowed in case none of the rules match the attribute. |
default-allow-write | Boolean indicating whether an attribute in write (create, update, delete) requests should be allowed in case none of the rules match the attribute. |
require-subject-match | Boolean indicating whether subject matching should be applied for each request. Setting this to true effectively means that only ResourceAttributes belonging to the logged in user can be read or updated. |
The require-subject-match setting is enforced by using the subject from an access token and comparing it to:
userNameattribute inAccountAttributesauthenticatedUserattribute inDynamicallyRegisteredClientAttributesuserNameinDelegationAttributesownerinDatabaseClientownerinGrantedAuthorizationAttributes.subjectinBucketservice operations
DeviceAttributes contain the accountId attribute. When the require-subject-match setting is set to true, it is required to include the account_id claim in an access token. The value of this claim is then compared to the accountId attribute in DeviceAttributes. This is required for /Devices endpoint in SCIM and for addDeviceToAccountByAccountId and updateDeviceFromAccountByAccountId mutations in the user management GraphQL endpoint.
The require-subject-match setting does not have any effect on requests to the UserInfo endpoint, since this endpoint only returns information from the access token’s subject.
Setting the require-subject-match to true has an important implication: all listing and create operations are denied. These operations include the following:
-
SCIM:
GET /Users(but notGET /Users/{id})GET /Users/.searchGET /Delegations(but notGET /Delegations/{id})GET /Devices(but notGET /Device/{id})POST /Users
-
GraphQL:
accountsquery andcreateAccountmutation in the User Management Endpoint.dynamicallyRegisteredClientsquery in the DCR Endpoint.databaseClientsquery andsetDatabaseClientOwnerByIdmutation in the Database Clients Endpoint.
Rules#
Each rule list must contain at least one rule. A rule configuration comprises three mandatory settings:
| Setting | Description |
|---|---|
access-operation | List of operations the rule applies to (create, read, update, delete). |
attribute | List of attributes the rule applies to. |
decision | One of allow or deny. Denotes what decision will be applied for an attribute that is matched to the given rule. |
The access-operation setting can contain four values. Each request maps to one of the values:
| Operation | Maps To |
|---|---|
| create | - all POST requests in SCIM endpoints- createAccount mutation in the GraphQL user management endpoint |
| read | - all GET requests in SCIM endpoints- all queries in GraphQL endpoints - all mutation responses in GraphQL endpoints - requests to the UserInfo endpoint |
| update | - all PUT and PATCH requests in SCIM endpoints- setClientStatus mutation in the dcr GraphQL endpoint- updateAccountById, addDeviceToAccountByAccountId, addDeviceToAccountByAccountId mutations in the user management GraphQL endpoint |
| delete | - all DELETE requests in SCIM endpoints- deleteAccountById, deleteLinkFromAccountByAccountId, deleteDeviceFromAccountByAccountId, deleteBucketByUserName mutations in the user management GraphQL endpoint |
The attribute setting contains a list of attribute names that a rule is applied to. These attribute names are divided into multiple parts separated by a dot (e.g. device.alias or account.name.givenName). The first part is always a prefix that indicates which ResourceAttributes subclass it is intended for. The available prefixes are:
account.- maps toAccountAttributesdevice.- maps toDeviceAttributesdelegation.- maps toDelegationAttributeslinkedAccount.- maps toLinkedAccountAttributesdynamicClient.- maps toDynamicallyRegisteredClientAttributesdbClient.- maps toDatabaseClientAttributesopenidUserinfo.- maps toResourceAttributeswith the claims to be returned by the UserInfo endpointgrantedAuthorization.- maps toGrantedAuthorizationAttributesbucket.- maps toBucketGraphQL type
Having a rule with attribute account.name will match the name attribute in an Account including all of its nested attributes (e.g. account.name.givenName or account.name.middleName). Having .* as the last part of the attribute is forbidden. The * character is always treated as a literal character, never as a wildcard (it doesn’t have any special meaning).
Before version 9.0 a wildcard character (.*) was supported as the last part of a rule. It would indicate that
the rule should match all nested attributes. However, having rules with attributes account.name and
account.name.* would be almost the same. It could create ambiguities so it is no longer supported. Moreover to
prevent mistakes, having .* at the end of a rule is forbidden.
Delete operations are always authorized using a top level prefix. If one wants to deny deleting devices, the rule must be configured like this (the attribute setting is important to notice).

Using idsh command line interface the same rule would look like the following.
rule Deny_Device_Deletion {
access-operation [ delete ];
attribute [ device ];
decision deny;
}
A rule having attribute set to something else e.g. device.id or device.alias would not work and deleting devices would be allowed.
Details on how attributes are authorized#
Most of the time it’s straightforward how attributes from rules are being matched with attributes being read/written. For example, if there’s a rule having account.title then the title attribute inside an Account will be matched with that rule. However, there is an edge case when a dot (.) character is part of an attribute name. Rules in Attribute Authorization Manager use a dot (.) character to separate nested attribute names. However, it’s possible for attributes to have names with a dot in them, e.g. custom.attr. Therefore a rule account.custom.attr could be meant to match “account”.“custom.attr” or “account”.“custom”.“attr”. Because of this ambiguity, Attribute Authorization Manager will match both attributes in such cases. Suppose we have these attributes inside an Account:
{
"custom.attr" : "value",
"custom" : {
"attr": "another value"
}
}
A rule having account.custom.attr would match both these attributes.
In addition, if an attribute has a dot in its name, then the Attribute Authorization Manager will also match it with a rule with a prefix of that attribute name, up until a dot. Consider the following example for a better explanation. Suppose we have these attributes in an Account:
{
"custom.attr" : "value",
"custom" : "another value"
}
A rule account.custom would match both of these attributes above, because custom is a prefix of custom.attr. However, if we had “custom1.attr” attribute instead of “custom.attr” in the Account, then “custom1.attr” would not be matched by the given rule. In general, a rule would match an attribute with a dot in its name, if a part of the attribute name that precedes the dot matches the full rule. It’s important to pay attention to these details when attributes with dots in their names are expected to be present in any of the attributes being authorized.
Authorization of some specific GraphQL operations#
Some GraphQL operations do not directly query or mutate ResourceAttributes. These operations include:
-
initializeAccountActivation- a mutation initializes the account activation (most likely by sending an account activation email). Therefore, this operation has to access theaccount.emailsfield (to send the email to the user’s email address) so to deny it, a deny rule has to be defined for theaccount.emailsattribute and for theREADaccess operation (even though the operation is a mutation). -
sendPasswordResetEmail- a mutation sends a password reset email to a user. This operation has to access theaccount.emailsfield (to send the email to the user’s email address) so to deny it, a deny rule has to be defined for theaccount.emailsattribute and for theREADaccess operation (even though the operation is a mutation). -
startVerifyTotpDevice- a mutation that starts the process of verifying a TOTP device. This operation does not change anything in the database, however the pair operationcompleteVerifyTotpDeviceadds a device for a user. That’s why to deny thestartVerifyTotpDeviceoperation, a deny rule has to be defined for thedeviceattribute and for theUPDATEaccess operation. -
startVerifyPasskey- a mutation that starts the process of adding a passkey. This operation does not change anything in the database, however the pair operationcompleteVerifyPasskeyadds a passkey (a device in thedevicesDB table) for a user. That’s why to deny thestartVerifyPasskeyoperation, a deny rule has to be defined for thedevice(e.g.device.alias) attribute for theUPDATEaccess operation.
Limitations#
Attribute Authorization Manager has a few limitations. This section provides a list of them.
- Some attributes cannot be filtered out in read requests.
meta.locationfield in all SCIM endpoints cannot be filtered out individually. However, this field will be filtered out if allmetafields are filtered out (e.g. using this attribute:account.meta.*).schemasfield in all SCIM endpoints. This field will always be returned in responses as mandated by the SCIM specification.- if
primaryfield is filtered out underaccount.emails,account.phoneNumbers,account.addressesetc. it will be returned asfalsein the GraphQL user management endpoint account.meta.timeZoneIdfield cannot be filtered out directly in the GraphQL user management endpoint. It will be filtered out if alsoaccount.meta.createdis filtered out.
- Filtering out a mandatory field in any GraphQL endpoint leads to an error returned by the GraphQL engine (
NullValueInNonNullableFielderror) when querying that field. This is required by the GraphQL specification (see GraphQL Error Handling Spec). - Filtering out the
idfield in all SCIM endpoints leads to a 500 error.
Examples#
This section contains examples of Attribute Authorization Manager configurations, defined using the idsh command line interface.
Self-management#
Attribute Authorization Manager that allows self-management of certain Account attributes through GraphQL and SCIM endpoints.
# Attribute Authorization Manager that allows self-management of certain Account attributes through GraphQL and SCIM endpoints.
[edit processing authorization-managers authorization-manager attr attribute]
% show
rule-list Self_Account_Authorization {
select-rule-list-when {
context-requirement [ user-management-graphql user-management-scim ];
}
enforcement-restrictions {
default-allow-read false;
default-allow-write false;
require-subject-match true;
}
rule Allow_Account_Read {
access-operation [ read ];
attribute [ account ];
decision allow;
}
rule Allow_Account_Write {
access-operation [ update ];
attribute [ account.name account.emails account.phoneNumbers account.title ];
decision allow;
}
}
Administration and Self-management#
Attribute Authorization Manager that allows admins to manage all accounts and allows only reading self accounts for other users.
# Attribute Authorization Manager that allows admins to manage all accounts and allows only reading self accounts for other users.
[edit processing authorization-managers authorization-manager attr attribute]
% show
rule-list Admin_Account_Management {
select-rule-list-when {
context-requirement [ user-management-graphql user-management-scim ];
scope-requirement {
applicability any-of;
scope [ admin ];
}
}
enforcement-restrictions {
default-allow-read false;
default-allow-write false;
require-subject-match false;
}
rule Allow_Account_Management {
access-operation [ create read update delete ];
attribute [ account ];
decision allow;
}
}
rule-list User_Self_Account_Reading {
select-rule-list-when {
context-requirement [ user-management-scim user-management-graphql ];
scope-requirement {
applicability any-of;
scope [ user ];
}
}
enforcement-restrictions {
default-allow-read false;
default-allow-write false;
require-subject-match true;
}
rule Allow_Account_Read {
access-operation [ read ];
attribute [ account ];
decision allow;
}
}
DCR authorization#
Attribute Authorization Manager that allows reading of certain DCR attributes through the DCR GraphQL endpoint.
# Attribute Authorization Manager that allows reading of certain DCR attributes through the DCR GraphQL endpoint
[edit processing authorization-managers authorization-manager attr attribute]
% show
rule-list DCR_Authorization {
select-rule-list-when {
context-requirement [ dcr-graphql ];
}
enforcement-restrictions {
default-allow-read false;
default-allow-write false;
require-subject-match false;
}
rule Allow_DCR_Read {
access-operation [ read ];
attribute [ dynamicClient.clientId dynamicClient.scope dynamicClient.redirectUris dynamicClient.grantTypes dynamicClient.authenticatedUser dynamicClient.status ];
decision allow;
}
}
Deletion of self account and devices#
Attribute Authorization Manager that allows deleting of self accounts and devices through the user management GraphQL and SCIM endpoints.
# Attribute Authorization Manager that allows deleting of self accounts and devices through the user management GraphQL and SCIM endpoints
[edit processing authorization-managers authorization-manager attr attribute]
% show
rule-list Self_Delete_Authorization {
select-rule-list-when {
context-requirement [ user-management-graphql user-management-scim ];
}
enforcement-restrictions {
default-allow-read false;
default-allow-write false;
require-subject-match true;
}
rule Allow_Self_Delete {
access-operation [ delete ];
attribute [ account device ];
decision allow;
}
}
Rule ordering#
Incorrectly configured Attribute Authorization Manager. The ‘Deny_Password_Read’ rule is never going to be used as the first (and broader) rule will always be matched first (order matters).
# Incorrectly configured Attribute Authorization Manager. The 'Deny_Password_Read' rule is never going to be used as the first (and broader) rule will always be matched first (order matters).
[edit processing authorization-managers authorization-manager attr attribute]
% show
rule-list Admin_Account_Management {
select-rule-list-when {
context-requirement [ user-management-graphql user-management-scim ];
scope-requirement {
applicability any-of;
scope [ admin ];
}
}
enforcement-restrictions {
default-allow-read false;
default-allow-write false;
require-subject-match false;
}
rule Allow_Account_Management {
access-operation [ create read update delete ];
attribute [ account ];
decision allow;
}
rule Deny_Password_Read {
access-operation [ read update ];
attribute [ account.password ];
decision deny;
}
}