Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Namespace: urn:mace:shibboleth:2.0:resolver
Schema: http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd

...

The ScriptedAttribute AttributeDefinition constructs an output attribute via the execution of a JSR-223 script. Scripts are somewhat easier to write and maintain than native Java code, though they are slower. They can also be changed dynamically since the resolver is a ReloadableService.

Scripting

Expand
titleScript Context

The script "context" defines the execution environment for the script and provides the following variables:

  • resolutionContext

    • AttributeResolutionContext for the current resolution step, which exists within the tree of state information that tracks the current request

  • id

    • Variable which implements ScriptedIdPAttribute, whose name is the ID of the AttributeDefinition, and which will be the output of the script. Note: If an attribute of this same name occurs as a dependency (see below), then the attribute will be pre-populated with all the values of the dependent attribute.

  • profileContext

  • custom

    • Contains whatever bean was referenced by the customObjectRef XML Attribute

  • subjects

    • Array of Subject objects associated with this request. Note that these will only be present if the attribute resolution is associated with a completed authentication step (so is not present for back channel requests or certain other cases).

In addition, each defined dependency of the connector, it exists, will be present via an object which implements ScriptedIdPAttribute.

For an AttributeDefinition dependency, that IdPAttribute is supplied. For a DataConnector dependency, each IdPAttribute produced by that connector is supplied.

The variable's name will be the attribute ID of the attribute from the dependency. In the event that more than one dependency produces attributes with the same ID, the values of all of those attributes are merged and made available to the script.

Note that any changes made to these dependency objects within the script will not be reflected in the result of the resolution process. In contrast, changes made to other objects accessed by means of the other variables in most cases will cause side effects, and should usually be avoided.

...

Expand
titleLogging

The same logging framework used throughout the IdP (SLF4J) may be used for logging within a script. First import the package org.slf4j and then obtain an org.slf4j.Logger object from an org.slf4j.LoggerFactory. The logging category name used is arbitrary, but you may need to adjust the IdP's logging configuration to see particular results. Logging levels available are: error, warn, info, debug, trace.

The string passed to the LoggerFactory.getLogger method should be the name of an existing logger element, defined in logging.xml.

For more information on configuring logging within the IdP, see the LoggingConfiguration topic.

Logging (Rhino)
Code Block
languagejs
importPackage(Packages.org.slf4j);
 
logger = LoggerFactory.getLogger("net.shibboleth.idp.attribute");
Scripted.addValue("foo");
Scripted.addValue("bar");

logger.info("Values of scriptTest were: {} ", Scripted.getValues());
Logging (Nashorn)
Code Block
languagejs
logger = Java.type("org.slf4j.LoggerFactory").getLogger("net.shibboleth.idp.attribute");

Scripted.addValue("foo");
Scripted.addValue("bar");

logger.info("Values of scriptTest were: {} ", Scripted.getValues());

...

Expand
titleCommon XML Attributes
Include Page
IDP5IDP4:AttributeDefinitionCommonAttributesIDP5
IDP4:AttributeDefinitionCommonAttributes
Expand
titleCommon XML Elements
Include Page
IDP5IDP4:AttributeDefinitionCommonChildElementsIDP5
IDP4:AttributeDefinitionCommonChildElements

...

Get eduPersonPrincipalName from LDAP or build one from uid

Variant 1: A "Prescoped" AttributeDefinition resolves existing eduPersonPrincipalName values from LDAP, then depends on a "ScriptedAttribute" definition to generate missing values. The Script also needs a dependency on the myLDAP DataConnector in order to have access to existing eduPersonPrincipalName and uid attribute values.

Minimal scripting, using Dependencies (Nashorn)
Code Block
languagexml
<AttributeDefinition id="eduPersonPrincipalName" xsi:type="Prescoped">
	<InputAttributeDefinition ref="eppnFromUid" />
</AttributeDefinition>

<AttributeDefinition id="eppnFromUid" xsi:type="ScriptedAttribute" dependencyOnly="true">
    <InputDataConnector ref="myLDAP" attributeNames="eduPersonPrincipalName uid" />
    <Script><![CDATA[
	if (typeof eduPersonPrincipalName == "undefined") eppnFromUid.addValue(uid.getValues().get(0) + "@%{idp.scope}@example.org");
	]]></Script>
</AttributeDefinition>

...

Code Block
languagexml
<AttributeDefinition id="eduPersonPrincipalName" xsi:type="ScriptedAttribute">
    <InputDataConnector ref="myLDAP" attributeNames="eduPersonPrincipalName uid" />

    <Script><![CDATA[
logger = Java.type("org.slf4j.LoggerFactory").getLogger("org.example.eppnbuilder");
scopedValueType =  Java.type("net.shibboleth.idp.attribute.ScopedStringAttributeValue");
var localpart = "";
if (typeof eduPersonPrincipalName == "undefined" || eduPersonPrincipalName.getValues().size() < 1) {
    logger.debug("No ePPN in LDAP found, creating one");
    localpart = uid.getValues().get(0);
} else {
    logger.debug("ePPN had value: " + eduPersonPrincipalName.getValues().get(0));
    localpart = eduPersonPrincipalName.getValues().get(0).split("@")[0];
    eduPersonPrincipalName.getValues().retainAll([]);
}
eduPersonPrincipalName.addValue(new scopedValueType(localpart, "%{idp.scope}example.org"));
logger.debug("ePPN final value: " + eduPersonPrincipalName.getValues().get(0));
    ]]></Script>
</AttributeDefinition>

...