Attribute Authorization Managers allow fine-grained, per-attribute authorization of:
It 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/deny reading/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.
ResourceAttributes
At the heart of this 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 for each attribute individually. When defining rule lists and rules it’s crucial to remember that the order is important because always only the first matching rule list and also only the first matching rule is applied.
The rule list configuration comprises three settings: select-rule-list-when setting, enforcement restrictions and one or more rules.
select-rule-list-when
If a request matches the requirements in select-rule-list-when setting of a rule list then all of the attributes are going to be authorized using this rule list. The select-rule-list-when configuration comprises three settings: context requirement, claim requirements, and scope requirement. Only 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:
Claim requirements is an optional list of claims and their values an access token must contain in order for a rule list to be matched.
Scope requirement is an optional list of scopes an access token must contain in order for a rule list to be matched.
Enforcement restrictions comprise three settings:
The require-subject-match setting is enforced by using the subject from an access token and comparing it to:
require-subject-match
userName
AccountAttributes
authenticatedUser
DynamicallyRegisteredClientAttributes
DelegationAttributes
owner
DatabaseClient
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.
DeviceAttributes
accountId
account_id
/Devices
SCIM
addDeviceToAccountByAccountId
updateDeviceFromAccountByAccountId
GraphQL
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 following:
GET /Users
GET /Users/{id}
GET /Users/.search
GET /Delegations
GET /Delegations/{id}
GET /Devices
GET /Device/{id}
POST /Users
accounts
createAccount
dynamicallyRegisteredClients
databaseClients
setDatabaseClientOwnerById
Each rule list must contain at least one rule. A rule configuration comprises three mandatory settings:
create
read
update
delete
allow
deny
The access-operation setting can contain four values. Each request maps to one of the values:
POST
GET
PUT
PATCH
setClientStatus
updateAccountById
DELETE
deleteAccountById
deleteLinkFromAccountByAccountId
deleteDeviceFromAccountByAccountId
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 which indicates which ResourceAttributes subclass it is intended for. There are five defined prefixes:
device.alias
account.name.givenName
account.
device.
delegation.
linkedAccount.
LinkedAccountAttributes
dynamicClient.
dbClient.
DatabaseClientAttributes
openidUserinfo.
Having a rule with attribute account.name will match the name attribute in an Account including all of it’s 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).
account.name
name
account.name.middleName
.*
*
Note
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.
9.0
account.name.*
Important note: 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):
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.
attribute
device.id
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:
account.title
title
.
custom.attr
account.custom.attr
1 2 3 4 5 6
{ "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:
1 2 3 4
{ "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.
account.custom
custom
Attribute Authorization Manager has a few limitations. This section provides a list of them.
meta.location
meta
account.meta.*
schemas
primary
account.emails
account.phoneNumbers
account.addresses
false
account.meta.timeZoneId
account.meta.created
NullValueInNonNullableField
id
This section contains examples of Attribute Authorization Manager configurations.
[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; } }
[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; } }
[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; } }
[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; } }
[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; } }