The Shibboleth V1 software has reached its End of Life and is no longer supported. This documentation is available for historical purposes only.

ScriptletAttributeDefinition

Configuring a Scriptlet Attribute Definition

NOTE: This connector is only included since IdP 1.3.1 (see announcement e-mail). If you use an earlier IdP release, you may retrieve it from the source control system if you feel comfortable doing so.

This attribute definition allows Java code to be written in the definition and executed when the attribute is requested. This provides nearly limitless flexibility for creating or transforming attributes. The scripts are processed by the BeanShell interpreter.

Attribute Definition Basics

All attribute definitions are configured in the IdP's resolver.xml file.

Basic Attributes

Each attribute definition supports the following basic XML attributes in their definition:

  • id - (required) used by the definition to determine its source, or input, attribute and by other definitions and data connectors to refer to this definition
  • sourceName - (optional) used to explicitly specify the name of the source, or input, attribute used by the definition

Source Attributes

Most attribute definitions transform other attributes. A definition will determine the name of its source attribute in the following way:

  1. If sourceName is present use an attribute whose name exactly matches the given source name
  2. Use an attribute whose name exactly matches the definitions id
  3. Use an attribute whose name exactly matches the last token of the definitions id split on / or :

Configuring the Definition

  1. Create a ScriptletAttributeDefinition element with its id attribute.
  2. Create a Scriptlet element, child of ScriptletAttributeDefinition, whose content is Java code that should be executed when this attribute is requested. You may wish to place this data in a CDATA section to ensure it does not interfere with the XML processing.

The following fields are made available and may be used in the code

Field Name

Field Type

Description

resolverAttribute

edu.internet2.middleware.shibboleth.aa.attrresolv.ResolverAttribute

The incoming attribute

principal

java.security.Principal

The principal of the user whose attributes are being fetched

requester

String

The ID of the service provider to whom the attributes are going

responder

String

The ID of the identity provider

dependencies

edu.internet2.middleware.shibboleth.aa.attrresolv.Dependencies

The connectors and attributes this definition depends on

log

org.apache.log4j.Logger

The logger for this definition

Example Configuration

<ScriptletAttributeDefinition id="urn:mace:dir:attribute-def:eduPersonAffiliation">
    <DataConnectorDependency requires="directory"/>
    <Scriptlet><![CDATA[
        Attributes attributes = dependencies.getConnectorResolution("directory");
        Attribute affiliation = attributes.get("eduPersonAffiliation");
        if (affiliation.size() > 0) {
            resolverAttribute.addValue("affiliate");
        }
    ]]></Scriptlet>
</ScriptletAttributeDefinition>

Example Configuration for common-lib-terms

This example sets the eduPersonEntitlement to the common-lib-terms URN for a principal with affiliation staff or student while keeping any entitlement values retrieved from the directory.

For the definition of common-lib-terms, refer to http://middleware.internet2.edu/urn-mace/urn-mace-dir-entitlement.html.

<ScriptletAttributeDefinition id="urn:mace:dir:attribute-def:eduPersonEntitlement">
   <DataConnectorDependency requires="directory"/>
   <AttributeDependency requires="urn:mace:dir:attribute-def:eduPersonAffiliation" />
   <Scriptlet><![CDATA[
Attributes attributes = dependencies.getConnectorResolution("directory");

Attribute entitlement = attributes.get("eduPersonEntitlement");

// add values from directory
for (int i = 0; entitlement != null && i < entitlement.size(); i++)
{
    resolverAttribute.addValue(entitlement.get(i));
}

// add common-lib-terms for staff and student
Attribute attribute = attributes.get("eduPersonAffiliation");
if (attribute.contains("staff") ||
    attribute.contains("student"))
{
    resolverAttribute.addValue("urn:mace:dir:entitlement:common-lib-terms");
}
      ]]>
   </Scriptlet>
</ScriptletAttributeDefinition>

Example Configuration for using the Active Directory objectSid as a uniqueID

As the following example shows, you can do even more complex things with the scriptlet attribute engine like converting an attribute. The code below uses the binary "objectSid" attribute to generate a uniqueID attribute that is common in some federations like SWITCHaai.

<!-- Convert objectSid and objectGUID to uniqueID -->

<ScriptletAttributeDefinition id="urn:mace:switch.ch:attribute-def:swissEduPersonUniqueID">
   <DataConnectorDependency requires="directory"/>
   <Scriptlet><![CDATA[

// Import Apache commons codes
import org.apache.commons.codec.digest.DigestUtils;

// Get attributes
Attributes attributes = dependencies.getConnectorResolution("directory");

// Get objectSid
Attribute obsid =  attributes.get("objectSid");
Attribute obguid =  attributes.get("objectGUID");


// Generate md5 hex of objectSid
String uniqueValue = (String)obguid.get(0) + (String)obsid.get(0);

//System.out.println("Unique value: " + uniqueValue );
String localpart = DigestUtils.md5Hex(uniqueValue);


// Add attribute
//System.out.println("UniqueID: " + localpart + "@switch.ch");
resolverAttribute.addValue( localpart + "@switch.ch");


      ]]>
   </Scriptlet>
</ScriptletAttributeDefinition>

Example Configuration for using memberOf attributes to generate affiliation

<ScriptletAttributeDefinition id="urn:mace:dir:attribute-def:eduPersonAffiliation">
   <DataConnectorDependency requires="directory"/>
   <Scriptlet><![CDATA[
Attributes attributes = dependencies.getConnectorResolution("directory");
Attribute memberOf = attributes.get("memberOf");

// add values from directory
String value = "none";
boolean student = false;
boolean faculty = false;
boolean staff = false;
boolean member = false;


for (int i = 0; memberOf != null && i < memberOf.size(); i++)
{
	value = memberOf.get(i);

	if (value.indexOf("Stud") > 0){
		student = true;
	}

	if (value.indexOf("Doz") > 0){
		faculty = true;
	}

	if (value.indexOf("Lehr") > 0){
		faculty = true;
	}
}

if (!student && !faculty){
	staff = true;
}

if (student){
	resolverAttribute.addValue("student");
}

if (faculty){
	resolverAttribute.addValue("faculty");
}

if (staff || faculty){
	resolverAttribute.addValue("staff");
}


if (student || staff){
	resolverAttribute.addValue("affiliate");
}

      ]]>
   </Scriptlet>
</ScriptletAttributeDefinition>

Attribute Definition Dependencies

In order to use attributes from data connectors or other definitions you need to make sure those dependencies are resolved before this definition is called.

If your definition depends on a data connector create a child element, of the main definition element, called DataConnectorDependency and give it an attribute of requires whose value is the id of the data connector this definition depends on.

If your definition depends on another definition create a child element, of the main definition element, called AttributeDependency and give it an attribute of requires whose value is the id of the definition this definition depends on.

Error Propagation

Not every attribute definition may, or need, work for every user in the system. However, the definition may emit an error if it is unable to find any entries for the user or if it depends on another data connector or definition that didn't apply to the current user.

To suppress these errors, so that they don't stop the attribute lookup process, add the follow attribute and value to the main definition element:

  • propagateErrors - with a value of false

Data Caching

Attribute definitions cache their information for the length of one attribute request; until all data connectors and definitions have been evaluated and their information retrieved. You may optionally have the definition cache its data for a fixed period of time. This can increase performance but will result in a lead time for frequently changing data.

To enable this longer-lived cache add the following attribute to the main connector element:

  • cacheTime - the length of time, in seconds, to cache the attributes fetched by this definition