Attribute Release Not Working
Michael B Allen
ioplex at gmail.com
Sat Jul 12 02:28:12 UTC 2025
I'm trying to learn SAML (from zero) so I set up a Shibboleth 5.1.4 IdP and
a minimalistic spring boot SP.
It works, I'm authenticated, I get redirected back to the SP but ... I
can't get attribute release working.
The SAMLResponse has no AttributeStatement (see very bottom of message for
SAMLResponse.xml).
I understand the basic export then filter but I'm blurry on how it all
should be used in practice.
Maybe someone can spot the failure?
Clearly Shibboleth is targeting the University / Research community but I
work more with the Enterprise crowd.
So I'm using the KerberosValidator and LDAPConnector with Active Directory
(confirmed in WireShark decrypted with sslkeylog LDAP search is working)
and trying to release the sAMAccountName as an attribute.
The docs gave me the impression that I just needed to do
exportAttributes="sAMAccountName" and <AttributeRule
attributeID="sAMAccountName" permitAny="true"/> but there is simply no
AttributeStatement in the SAMLResponse.
I thought maybe the SP needed to explicitly request with RequestedAttribute
so I manually added it to the sp metadata but that had no effect.
Output of aacli shows no error but nothing interesting:
$ bin/aacli.sh -n dev at TECH.CORP -r '
http://sp.techi.wan:8080/saml2/service-provider-metadata/techcorp'
(
https://idp.tech.corp:8443/profile/admin/resolvertest?requester=http%3A%2F%2Fsp.techi.wan%3A8080%2Fsaml2%2Fservice-provider-metadata%2Ftechcorp&principal=dev%40TECH.CORP)
https://idp.tech.corp:8443/profile/admin/resolvertest?requester=http%3A%2F%2Fsp.techi.wan%3A8080%2Fsaml2%2Fservice-provider-metadata%2Ftechcorp&principal=dev%40TECH.CORP
Again, I'm a total SAML newb so any general guidance about good Shibboleth
practices (particularly in an Enterprise environment) would be greatly
appreciated.
Below are various files that I *think* are important but heavily trimmed
for reasonable email consumption.
Can anyone recommend diagnostics?
Mike
--8<--
conf/idp.properties
idp.entityID=https://idp.tech.corp:8443/idp/shibboleth
idp.scope=tech.corp
--8<--
conf/services.properties
idp.service.relyingparty.ignoreUnmappedEntityAttributes=true
idp.service.attribute.registry.checkInterval = PT15M
idp.service.attribute.registry.encodeType = false
idp.service.attribute.resolver.checkInterval = PT15M
idp.service.attribute.filter.checkInterval = PT15M
--8<--
conf/metadata-providers.xml
<MetadataProvider id="LocalMetadata"
xsi:type="FilesystemMetadataProvider"
metadataFile="%{idp.home}/metadata/spring-demo-sp-metadata.xml"/>
--8<--
conf/relying-party.xml
<bean id="shibboleth.DefaultRelyingParty" parent="RelyingParty">
<property name="profileConfigurations">
<list>
<ref bean="SAML2.SSO" />
<ref bean="SAML2.ECP" />
<ref bean="SAML2.Logout" />
<!--
<ref bean="SAML2.AttributeQuery" />
-->
<ref bean="SAML2.ArtifactResolution" />
</list>
</property>
</bean>
<util:list id="shibboleth.RelyingPartyOverrides">
<bean id="ExampleSP" parent="RelyingPartyByName" c:relyingPartyIds="
http://sp.techi.wan:8080/saml2/service-provider-metadata/techcorp">
<property name="profileConfigurations">
<list>
<bean parent="SAML2.SSO" p:encryptAssertions="false" />
</list>
</property>
</bean>
</util:list>
--8<--
conf/saml-nameid.xml
<util:list id="shibboleth.SAML2NameIDGenerators">
<ref bean="shibboleth.SAML2TransientGenerator" />
</util:list>
--8<--
conf/services.xml
<util:list id="shibboleth.RelyingPartyResolverResources">
<value>%{idp.home}/conf/relying-party.xml</value>
<value>%{idp.home}/conf/credentials.xml</value>
</util:list>
<util:list id="shibboleth.MetadataResolverResources">
<value>%{idp.home}/conf/metadata-providers.xml</value>
</util:list>
<util:list id ="shibboleth.AttributeResolverResources">
<value>%{idp.home}/conf/attribute-resolver.xml</value>
</util:list>
<util:list id ="shibboleth.AttributeRegistryResources">
<value>%{idp.home}/conf/attribute-registry.xml</value>
<value>%{idp.home}/conf/attributes/default-rules.xml</value>
<value>%{idp.home}/conf/attribute-resolver.xml</value>
</util:list>
<util:list id ="shibboleth.AttributeFilterResources">
<value>%{idp.home}/conf/attribute-filter.xml</value>
</util:list>
<util:list id ="shibboleth.NameIdentifierGenerationResources">
<value>%{idp.home}/conf/saml-nameid.xml</value>
</util:list>
<util:list id="shibboleth.AccessControlResources">
<value>%{idp.home}/conf/access-control.xml</value>
</util:list>
--8<--
conf/attribute-registry.xml
<bean parent="shibboleth.TranscodingRuleLoader"
c:dir="%{idp.home}/conf/attributes/custom"
c:extensions="#{{'.txt', '.props', '.properties', '.rule'}}" />
--8<--
conf/attribute-resolver.xml
<DataConnector id="myLDAP" xsi:type="LDAPDirectory"
ldapURL="%{idp.attribute.resolver.LDAP.ldapURL}"
baseDN="%{idp.attribute.resolver.LDAP.baseDN}"
principal="%{idp.attribute.resolver.LDAP.bindDN}"
principalCredential="%{idp.attribute.resolver.LDAP.bindDNCredential}"
useStartTLS="%{idp.attribute.resolver.LDAP.useStartTLS:true}"
startTLSTimeout="%{idp.attribute.resolver.LDAP.startTLSTimeout}"
connectTimeout="%{idp.attribute.resolver.LDAP.connectTimeout}"
trustFile="%{idp.attribute.resolver.LDAP.trustCertificates}"
responseTimeout="%{idp.attribute.resolver.LDAP.responseTimeout}"
connectionStrategy="%{idp.attribute.resolver.LDAP.connectionStrategy}"
noResultIsError="true"
multipleResultsIsError="true"
excludeResolutionPhases="c14n/attribute"
exportAttributes="sAMAccountName mail displayName sn givenName
departmentNumber employeeNumber eduPersonEntitlement eduPersonAssurance">
<FilterTemplate>
<![CDATA[
%{idp.attribute.resolver.LDAP.searchFilter}
]]>
</FilterTemplate>
<ConnectionPool
minPoolSize="%{idp.pool.LDAP.minSize:3}"
maxPoolSize="%{idp.pool.LDAP.maxSize:10}"
blockWaitTime="%{idp.pool.LDAP.blockWaitTime:PT3S}"
validatePeriodically="%{idp.pool.LDAP.validatePeriodically:true}"
validateTimerPeriod="%{idp.pool.LDAP.validatePeriod:PT5M}"
validateDN="%{idp.pool.LDAP.validateDN:}"
validateOnCheckout="%{idp.pool.LDAP.validateOnCheckout:false}"
validateFilter="%{idp.pool.LDAP.validateFilter:(objectClass=*)}"
prunePeriod="%{idp.pool.LDAP.prunePeriod:PT5M}"
expirationTime="%{idp.pool.LDAP.idleTime:PT10M}"/>
</DataConnector>
--8<--
conf/attribute-filter.xml
<AttributeFilterPolicy id="alwaysRelease">
<PolicyRequirementRule xsi:type="ANY" />
<AttributeRule attributeID="sAMAccountName" permitAny="true" />
</AttributeFilterPolicy>
<AttributeFilterPolicy id="Per-Attribute-singleValued">
<PolicyRequirementRule xsi:type="ANY" />
<AttributeRule attributeID="eduPersonPrincipalName">
<PermitValueRule xsi:type="EntityAttributeExactMatch"
attributeName="
http://shibboleth.net/ns/attributes/releaseAllValues"
attributeNameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
attributeValue="eduPersonPrincipalName" />
</AttributeRule>
<AttributeRule attributeID="mail">
<PermitValueRule xsi:type="EntityAttributeExactMatch"
attributeName="
http://shibboleth.net/ns/attributes/releaseAllValues"
attributeNameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
attributeValue="mail" />
</AttributeRule>
</AttributeFilterPolicy>
<AttributeFilterPolicy id="Per-Attribute-Affiliation">
<PolicyRequirementRule xsi:type="EntityAttributeExactMatch"
attributeName="
http://shibboleth.net/ns/attributes/releaseAllValues"
attributeNameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
attributeValue="eduPersonScopedAffiliation" />
<AttributeRule attributeID="eduPersonScopedAffiliation"
permitAny="true" />
</AttributeFilterPolicy>
<AttributeFilterPolicy id="subject-identifiers">
<PolicyRequirementRule xsi:type="ANY" />
<AttributeRule attributeID="samlPairwiseID">
<PermitValueRule xsi:type="OR">
<Rule xsi:type="EntityAttributeExactMatch"
attributeName="urn:oasis:names:tc:SAML:profiles:subject-id:req"
attributeNameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
attributeValue="pairwise-id" />
<Rule xsi:type="EntityAttributeExactMatch"
attributeName="urn:oasis:names:tc:SAML:profiles:subject-id:req"
attributeNameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
attributeValue="any" />
</PermitValueRule>
</AttributeRule>
<AttributeRule attributeID="samlSubjectID">
<PermitValueRule xsi:type="EntityAttributeExactMatch"
attributeName="urn:oasis:names:tc:SAML:profiles:subject-id:req"
attributeNameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
attributeValue="subject-id" />
</AttributeRule>
</AttributeFilterPolicy>
<AttributeFilterPolicy id="example1">
<PolicyRequirementRule xsi:type="Requester" value="
https://sp.example.org" />
<AttributeRule attributeID="uid" permitAny="true" />
</AttributeFilterPolicy>
<AttributeFilterPolicy id="example2">
<PolicyRequirementRule xsi:type="OR">
<Rule xsi:type="Requester" value="https://sp.example.org" />
<Rule xsi:type="Requester" value="
https://another.example.org/shibboleth" />
</PolicyRequirementRule>
<AttributeRule attributeID="eduPersonScopedAffiliation"
permitAny="true" />
</AttributeFilterPolicy>
--8<--
metadata/idp-metadata.xml
<md:EntityDescriptor entityID="https://idp.tech.corp:8443/idp/shibboleth"
xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
xmlns:mdui="urn:oasis:names:tc:SAML:metadata:ui"
xmlns:shibmd="urn:mace:shibboleth:metadata:1.0" xmlns:ds="
http://www.w3.org/2000/09/xmldsig#">
<md:IDPSSODescriptor
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:Extensions>
<shibmd:Scope regexp="false">tech.corp</shibmd:Scope>
<mdui:UIInfo>
<mdui:DisplayName xml:lang="en">A name for the IdP at
idp.tech.corp</mdui:DisplayName>
<mdui:Description xml:lang="en">Enter a description for the
IdP at idp.tech.corp</mdui:Description>
<mdui:Logo xml:lang="en" width="80" height="80">
https://idp.tech.corp:8443/path/to/logo.png</mdui:Logo>
</mdui:UIInfo>
</md:Extensions>
<md:KeyDescriptor use="signing">
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>
MIIELDCCApSgAwIBAgIVAK484vuVe9lKp/8o/7eobxivCsMMMA0GCSqGSIb3DQEBCwUAMBsxGTAX
...
RUNnmUC5BXD2Z1RtTousKNzX2d2q5LGzej8heIF7mXmqZhEccG8Eib0h6Nk0XQ==
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:KeyDescriptor use="signing">
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>
MIIEKzCCApOgAwIBAgIUL6IhHqoVAEx3htbU+AB8F8KQeXowDQYJKoZIhvcNAQELBQAwGzEZMBcG
...
v3Q0iVZWuNVwsWCyZ1FGTpUcraXGR/s3SMa+449/0VbjCiNsx6f/mBhDD3y2
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:KeyDescriptor use="encryption">
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>
MIIEKzCCApOgAwIBAgIUUyTDN5iEAgu/crWPHUJvAiuXuzEwDQYJKoZIhvcNAQELBQAwGzEZMBcG
...
ZmpOy1+Qvfc1RXuUpJc/qpxfjAKDuxWZnveE0EHIqt4Sogb1CZyJ732m0ste
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:SingleLogoutService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="
https://idp.tech.corp:8443/idp/profile/SAML2/SOAP/ArtifactResolution" />
<md:SingleSignOnService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign"
Location="https://idp.tech.corp:8443/idp/profile/SAML2/POST-SimpleSign/SSO"
/>
<md:SingleSignOnService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="
https://idp.tech.corp:8443/idp/profile/SAML2/Redirect/SSO" />
<md:SingleSignOnService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="
https://idp.tech.corp:8443/idp/profile/SAML2/POST/SSO" />
</md:IDPSSODescriptor>
</md:EntityDescriptor>
--8<--
metadata/spring-demo-sp-metadata.xml
<?xml version="1.0" encoding="UTF-8"?><md:EntityDescriptor
xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" entityID="
http://sp.techi.wan:8080/saml2/service-provider-metadata/techcorp">
<md:SPSSODescriptor
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:KeyDescriptor use="signing">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>MIICyzCCAbOgAwIBAgIIdt2jV63MaK8wDQYJKoZIh...gi0p6JUjcJ7JcqjzIifowZGLfnryS+V8=</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:KeyDescriptor use="encryption">
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:X509Data>
<ds:X509Certificate>MIIC1DCCAbygAwIBAgIJANjaIWSWABK4MA0GCSqGS...XSPetfJwEk6YwGd/7bKr+OvyPieI+wdnDpopu1s=</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</md:KeyDescriptor>
<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</md:NameIDFormat>
<md:AssertionConsumerService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="http://sp.techi.wan:8080/login/saml2/sso/techcorp"
index="1">
<md:RequestedAttribute
FriendlyName="sAMAccountName"
Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.1"
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
isRequired="true"/>
</md:AssertionConsumerService>
</md:SPSSODescriptor>
</md:EntityDescriptor>
--8<--
SAMLResponse2-2025-07-11.xml
<?xml version="1.0" encoding="UTF-8"?>
<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
Destination="http://sp.techi.wan:8080/login/saml2/sso/techcorp"
ID="_9e1f27825240a708581c70779cec7cd6"
InResponseTo="ARQ1c627e5-a34c-47ed-948e-9e8c446992c3"
IssueInstant="2025-07-12T00:07:11.077Z" Version="2.0">
<saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
https://idp.tech.corp:8443/idp/shibboleth</saml2:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="
http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="
http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference URI="#_9e1f27825240a708581c70779cec7cd6">
<ds:Transforms>
<ds:Transform Algorithm="
http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#
"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256
"/>
<ds:DigestValue>2wU/s6uTZ4Rax0O3Rzx796cWMmJ4a7qEHIbkw13hiZo=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>yorLtaG9F49Hw6ccANyw17u...kkZ29SzFyZc0ubtfN0tkmRcO</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIIEKzCCApOgAwIBA...SMa+449/0VbjCiNsx6f/mBhDD3y2</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
<saml2p:Status>
<saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</saml2p:Status>
<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
ID="_60f532e09214bd3f82cc0109a2abae5f"
IssueInstant="2025-07-12T00:07:11.077Z" Version="2.0">
<saml2:Issuer>https://idp.tech.corp:8443/idp/shibboleth</saml2:Issuer>
<saml2:Subject>
<saml2:NameID xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient" NameQualifier="
https://idp.tech.corp:8443/idp/shibboleth" SPNameQualifier="
http://sp.techi.wan:8080/saml2/service-provider-metadata/techcorp
">AAdzZWNyZXQxLdnracfAlkyoJKq...CYC9pyCRInysvGAWVXNzmyClcI</saml2:NameID>
<saml2:SubjectConfirmation
Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml2:SubjectConfirmationData Address="10.15.15.11"
InResponseTo="ARQ1c627e5-a34c-47ed-948e-9e8c446992c3"
NotOnOrAfter="2025-07-12T00:12:11.100Z" Recipient="
http://sp.techi.wan:8080/login/saml2/sso/techcorp"/>
</saml2:SubjectConfirmation>
</saml2:Subject>
<saml2:Conditions NotBefore="2025-07-12T00:07:11.077Z"
NotOnOrAfter="2025-07-12T00:12:11.077Z">
<saml2:AudienceRestriction>
<saml2:Audience>
http://sp.techi.wan:8080/saml2/service-provider-metadata/techcorp
</saml2:Audience>
</saml2:AudienceRestriction>
</saml2:Conditions>
<saml2:AuthnStatement AuthnInstant="2025-07-12T00:07:11.002Z"
SessionIndex="_750b52ba65d75304840dd91ed89d78a7">
<saml2:SubjectLocality Address="10.15.15.11"/>
<saml2:AuthnContext>
<saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef>
</saml2:AuthnContext>
</saml2:AuthnStatement>
</saml2:Assertion>
</saml2p:Response>
--
Michael B Allen
Java AD DS Integration
https://www.ioplex.com/ <http://www.ioplex.com/>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://shibboleth.net/pipermail/users/attachments/20250711/f756f3fb/attachment.htm>
More information about the users
mailing list