Using Azure Entra ID Groups with Scripted Attributes to Enable eduPersonAffiliation in Shibboleth IdP
Overview
This guide describes how to use Azure (Entra ID) groups with Shibboleth's ScriptedAttributeDefinition to populate the eduPersonAffiliation attribute, which in turn supports the scoped version: eduPersonScopedAffiliation.
These attributes follow the eduPerson schema specification and typically contain multiple values (e.g., member@example.com, student@example.com). Scoped values are defined using the domain chosen during the initial IdP installation (e.g., @example.com).
Why Use ScriptedAttributeDefinition?
Using ScriptedAttributeDefinition allows for advanced mapping logic that cannot be expressed through static AttributeResolver maps. It is especially useful when:
Users belong to multiple Azure groups.
Group-to-affiliation mapping varies based on multiple conditions.
Dynamic or context-aware logic is needed.
Note: Scripted attributes require JavaScript knowledge and effective logging. Poorly written scripts may introduce unexpected behavior.
Prerequisites
Before proceeding, ensure that: You have read the following:
This is an alternative technique to enable eduPersonScopedAffiliation. The Mapped AttributeDefinition is mentioned on the Proxy Task 7. Enabling eduPersonAffiliation from Entra ID/Azure (optional)
<AttributeDefinition id="eduPersonAffiliation" xsi:type="ScriptedAttribute">
<InputDataConnector ref="passthroughAttributes" attributeNames="azureGroups"/>
<Script>
<![CDATA[
// This script maps Azure group claims to eduPersonAffiliation values
var IdPAttribute = Java.type("net.shibboleth.idp.attribute.IdPAttribute");
var StringAttributeValue = Java.type("net.shibboleth.idp.attribute.StringAttributeValue");
var logger = Java.type("org.slf4j.LoggerFactory").getLogger("net.shibboleth.idp.attribute");
var groupToAffiliationMap = {
"abc123a-555e-test-86df-random-object-value": "faculty",
"xyz890zbs-52test-a41e5-random-object-value": "staff",
"AzureGroup3": "employee",
"AzureGroup4": "student"
};
if (typeof azureGroups !== "undefined" && azureGroups !== null)
{
var groupValues = azureGroups.getValues();
for (var i = 0; i < groupValues.size(); i++)
{
var group = groupValues.get(i).toString();
var affiliation = groupToAffiliationMap[group];
logger.info("Adding Affiliation as " + affiliation);
if (affiliation !== null && typeof affiliation !== "undefined")
{
eduPersonAffiliation.addValue(new StringAttributeValue(affiliation));
}
}
}
]]>
</Script>
</AttributeDefinition>
Other technique exemplar:
<AttributeDefinition id="eduPersonAssurance" xsi:type="ScriptedAttribute">
<InputDataConnector ref="passthroughAttributes" attributeNames="azureGroups" />
<Script>
<![CDATA[
if (typeof azureGroups != "undefined" && azureGroups != null) {
if (!(azureGroups.getValues().contains("IAP-Zero"))) {
eduPersonAssurance.getValues().add(" https://refeds.org/assurance/IAP/local-enterprise");
}
if (azureGroups.getValues().contains("IAP-Low")) {
eduPersonAssurance.getValues().add(" https://refeds.org/assurance/IAP/low");
}
if (azureGroups.getValues().contains("IAP-Medium")) {
eduPersonAssurance.getValues().add(" https://refeds.org/assurance/IAP/medium");
}
if (azureGroups.getValues().contains("IAP-High")) {
eduPersonAssurance.getValues().add(" https://refeds.org/assurance/IAP/high");
}
}
]]>
</Script>
</AttributeDefinition>Final Notes
This method provides a flexible and powerful way to tailor attribute values based on Azure group membership. It is especially helpful for institutions with diverse affiliation logic not suited to static mapping.
For simpler needs, consider using basic mapped attributes instead of scripting.
Filter by label
There are no items with the selected labels at this time.