What is a XACML Obligation?

Definition

The XACML standard defines the concept of obligations which are elements which can be returned along with a XACML decision (either of Permit or Deny) in order to enrich that decision. Obligations are triggered on either Permit or Deny. The Policy Enforcement Point must implement and enforce obligations. If it fails to do so, it must deny access to the requested resource (in the case of a Permit).

The XACML 3.0 standard defines obligations as follows:

An operation specified in a rule, policy or policy set that should be performed by the PEP in conjunction with the enforcement of an authorization decision

Where can I use an Obligation?

Obligations can be defined in PolicySet, Policy, and Rule elements. This is illustrated in the XACML class diagram below.

XACML 3.0 Class Diagram - taken from the eXtensible Access Control Markup Language (XACML) Version 3.0
XACML 3.0 Class Diagram – taken from the eXtensible Access Control Markup Language (XACML) Version 3.0

Use cases

Obligations are extremely useful to enrich the otherwise simple (and binary) authorization flow. Here are some examples where obligations help take XACML the extra mile:

  • Break-the-glass scenarios: one common scenario in healthcare is to control access to medical records. By default, only those physicians a patient has a relationship to should have access to that patient’s medical. Well, what happens then if the patient is critically ill in an unfamiliar setting e.g. while on a vacation to a different city or country altogether? Should we still deny access to the information? Of course not: the medical staff should have the ability to override the default Deny. This is achievable through a break-the-glass scenario. The first time the medical staff request the information, they will get a Deny + obligation to set an emergency flag in the case that the situation is indeed an emergency flag. Once the flag is set, the medical staff can request access again in which case they will be granted access.
  • Accountability: another great example of obligations is a follow-up to the previous case. What’s to prevent a doctor from waving the emergency flag needlessly for the sole purpose of getting illicit access to medical records? Another obligation of course. This obligation, this time, is to log the fact that a doctor was granted access to a medical record that would have otherwise been off limits because that given doctor used the break-the-glass scenario. The PEP will be responsible for logging the access in a special central log which will be later used to hold the doctor accountable.
  • Notifications: Let’s switch scenarios and move to banking. Let’s imagine a user is repeatedly trying to transfer $1,000. The first time, he/she is denied access, the second time as well. The third time though, not only is the user denied access but on top of that an email alert is triggered through an obligation. The alert can be sent to an administrator, a manager or another user for immediate action. This type of approach leads to more proactive security systems and therefore more secure systems.
  • Strong authentication: another interesting scenario hauls from the banking sector. Imagine the use case where a user logs into their bank account using weak authentication (username / password). That may be enough to get them into their account overview to check their balance. It won’t be enough however to get users to transfer money from one account to another. Yet, as a friendly bank, we want to let our customers get the most out of online banking. In this case, when the user tries to transfer money, they will be denied access plus they will get an obligation which will reroute them to a page where they can enter a one-time password to augment and strengthen their authentication after which they will be able to transfer money. This enables a much more positive user experience than simply denying the user access.

Example in ALFA

First of all, it’s necessary to define the obligation identifiers. This is done as follows:

namespace com.axiomatics.examples{
	import Attributes.*

	obligation logExceptionalAccess = "com.axiomatics.examples.obligations.logExceptionalAccess"
	obligation breakTheGlass = "com.axiomatics.examples.obligations.breakTheGlass"
}

We can now use the newly defined obligations inside a policy ensemble:

namespace com.axiomatics.examples{
	import Attributes.*

	obligation logExceptionalAccess = "com.axiomatics.examples.obligations.logExceptionalAccess"
	obligation breakTheGlass = "com.axiomatics.examples.obligations.breakTheGlass"

	/**
	 * Control access to medical records
	 */
	policyset allowAccessMedicalRecords{
		target clause resourceType=="medical record"
		apply denyOverrides
		/**
		 * Doctors - control access to medical records
		 */
		policy doctorsView{
			target clause userRole=="doctor" and actionId=="view"
			apply firstApplicable
			/**
			 * The assigned doctor can view the medical record
			 */
			rule regularAccess{
				permit
				condition subjectId==assignedDoctorId
			}
			/**
			 * Any doctor can view the medical record if the emergency flag is on
			 */
			rule emergencyAccess{
				condition emergency==true
				permit
				on permit{
					obligation logExceptionalAccess{
						message = "The following doctor has requested access to a medical record"
						recordId = resourceId
						doctorId = subjectId
					}
				}
			}
			/**
			 * Deny
			 */
			rule breakTheGlass{
				deny
				on deny{
					obligation breakTheGlass{
						message = "You do not have access to this record. Please set the emergency flag to true to gain access."
					}
				}
			}
		}

	}
}

The example consists of one policy set with a nested policy inside which in turn contains 3 rules. The policy set scopes the access to medical records. The policy scopes it to doctors and the action view. The three rules work as follows:

  • Rule #1: this rule applies to doctors who have a care relationship with the patient. The access is then granted.
  • Rule #2: this rule applies when a doctor has enabled the emergency flag. Access is then granted and an obligation kicks in to log the special access for accountability.
  • Rule #3: this rule applies when a doctor tries to access a record they do not normally have access to. Access is denied and an obligation is returned to let the doctor they can gain access by waving the emergency flag.

Differences from previous versions of XACML

It’s worth noting that previous versions of XACML (XACML 2.0 and older) do have obligations but these do not allow for variables inside. One of the compelling points of obligations in XACMCL 3.0 is that you can have dynamic variables. For instance, in the example above, the logExceptionalAccess obligation contains three variables: message, recordId, and doctorId. The first one, message, is static. The 2 other ones contain the values resolved at runtime, when access is being granted or denied.

Conclusion

The obligations feature of XACML make the authorization language even more powerful by enabling advanced scenarios such as trust elevation, notifications, and break-the-glass. For more information, head on over to Axiomatics’ website. We provide training courses on-demand.

Previously in TGIF XACML…

Previous tidbits can be found here: