XMLAttributeExtractorExamples
In all the examples below, the default XML namespace is assumed to be urn:mace:shibboleth:2.0:attribute-map
, to match the default file shipped with the software. Thus <Attribute>
refers to a mapping rule in the attribute-map.xml file, whereas <saml2:Attribute>
refers to a SAML construct in a message.
Simple Attributes
Some simple cases first, involving string-valued data, which is generally the most common case. You don't generally need to attach an AttributeDecoder to the mapping rules unless the attribute needs filtering rules attached to it later or will be used in access control rules and the attribute has to be processed in a case-insensitive manner. By default, strings will be decoded and assumed to be case-sensitive for the purposes of most value comparisons.
The SP prefers, favors, and encourages Attributes to be named with URIs, because they are unique and provide an inherent way of federating names that avoids conflict. Matching rules for such names will be simpler as a result.
Common Cases
If you want to create a rule to extract this into a variable called "mail":
<saml2:Attribute FriendlyName="mail" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" Name="urn:oid:0.9.2342.19200300.100.1.3"> <saml2:AttributeValue>foo@example.org</saml2:AttributeValue> </saml2:Attribute>
you would do this (note, there's no need to specify the NameFormat
constant to match because it's the Shibboleth default):
<Attribute name="urn:oid:0.9.2342.19200300.100.1.3" id="mail"/>
For the eduPerson-defined "eduPersonAffiliation" attribute, which is case-insensitive, you would map this:
<saml2:Attribute FriendlyName="eduPersonAffiliation" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.1"> <saml2:AttributeValue>member</saml2:AttributeValue> <saml2:AttributeValue>student</saml2:AttributeValue> </saml2:Attribute>
using this:
<Attribute name="urn:oid:1.3.6.1.4.1.5923.1.1.1.1" id="unscoped-affiliation"> <AttributeDecoder xsi:type="StringAttributeDecoder" caseSensitive="false"/> </Attribute>
Hacky Naming
In the common case that you're faced with someone providing made-up names for SAML Attributes, you may or may not need to take extra steps with the rules by setting the nameFormat
XML attribute. There are basically three cases, SAML 1.1 usage, one of the actual alternative NameFormat
values in SAML 2.0, and the extremely ill-advised SAML 2.0 constant for "unspecified" naming.
With SAML 1.1, there was a completely undefined concept called an AttributeNamespace
used as a secondary naming key. In Shibboleth, we defined a fixed value to use, urn:mace:shibboleth:1.0:attributeNamespace:uri
, that is automatically matched. If you actually need to support SAML 1.1 now, you probably have bigger problems than how to use the SP, but chances are you might run into some made up value, and you'll need to include that value in the rule as the nameFormat
.
The more common case is just made-up SAML 2.0 naming. You may run into the "basic" naming format. If you need to map this:
<saml2:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="emailAddress"> <saml2:AttributeValue>foo@example.org</saml2:AttributeValue> </saml2:Attribute>
you would use this:
<Attribute name="emailAddress" nameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" id="mail"/>
The other case is when the NameFormat
XML attribute is omitted or set to its default value. We also match that indiscriminately, so you can map this:
<saml2:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified" Name="emailAddress"> <saml2:AttributeValue>foo@example.org</saml2:AttributeValue> </saml2:Attribute>
with this:
<Attribute name="emailAddress" id="mail"/>
Thus, that rule matches an input SAML Attribute with any of the following NameFormat
values:
- None / omitted
urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified
urn:oasis:names:tc:SAML:2.0:attrname-format:uri
Name Identifiers
Avoiding the use of Name Identifiers is the best option but in the event that you have to accept them, they can be extracted like an Attribute by treating the Format
of the incoming identifier as the name
to map against. It's also necessary to attach a specialized NameID AttributeDecoder to the rule and specify how to produce a simple string from the non-simple XML input format.
As a simple example, to accept an email address in a form like:
<saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">foo@example.org</saml2:NameID>
the rule would be:
<Attribute name="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" id="mail"> <AttributeDecoder xsi:type="NameIDAttributeDecoder" formatter="$Name" /> </Attribute>
A more complex example, a SAML 2.0 "persistent" Name Identifier, is a full "triple" in which both the qualifier XML attributes have to be included in a string representation to be fully accurate:
<saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" NameQualifier="https://idp.example.org/idp" SPNameQualifier="https://sp.example.org/sp"> JGHDGEGKDGSGJSGJKNNFLDLJDJDADAFJJDJG </saml2:NameID>
and the rule might be (might, because the exact serialization is entirely a local choice):
<Attribute name="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" id="persistent-id"> <AttributeDecoder xsi:type="NameIDAttributeDecoder" formatter="$NameQualifier!$SPNameQualifier!$Name" defaultQualifiers="true"/> </Attribute>
Scoped Attributes
The most common "special" case to deal with is decoding a scoped attribute. A scoped attribute is one whose values have two parts, one actual value and one "scope", usually resembling a DNS domain, that qualifies the value. The special part of this is that it's usually important to control which IdP can supply a particular scope by using an AttributeFilter rule, usually based on SAML Metadata containing a Shibboleth-defined metadata extension.
While an email address looks like a scoped value, one doesn't generally apply policy like this to an email address, which should never be used as an important identifier but only as, obviously, a contact address. So email addresses are decoded as "simple" values, but actual identifiers with scopes should usually have a special Scoped AttributeDecoder attached inside the rule.
A good example of a scoped attribute is the new standard "subject ID" SAML Attribute that should be used in new applications, which looks like:
<saml2:Attribute FriendlyName="subject-id" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" Name="urn:oasis:names:tc:SAML:attribute:subject-id"> <saml2:AttributeValue>AJDKHDDISGKHKSHLFLHFHSGKSGK@example.org</saml2:AttributeValue> </saml2:Attribute>
and would be mapped with:
<Attribute name="urn:oasis:names:tc:SAML:attribute:subject-id" id="subject-id"> <AttributeDecoder xsi:type="ScopedAttributeDecoder" caseSensitive="false"/> </Attribute>
Same as all the earlier examples, just a different decode type.