IdP Auffrischungs-Workshop

DFN Logo




Vorbereitung

Für den Workshop benötigen wir die nachfolgend beschriebene Schulungs-VM.

Informationen zur Schulungs-VM

Für den Workshop stellen wir eine Schulungs-VM zur Verfügung. Installieren Sie diese bitte vorab und machen sich mit der VM vertraut. Als Virtualisierungssoftware empfehlen wir VirtualBox in der neuesten Version.
  1. Import des heruntergeladenen .ova-Images in Virtualbox: Datei -> Appliance importieren. Im BIOS muss Hardware-Virtualisierung angeschaltet sein.
  2. Für ein Copy & Paste ohne Gasterweiterungen können Sie diese Installationsanleitung selbstverständlich auch im Browser in der VM abrufen. Dazu finden Sie im Firefox ein Lesezeichen in der Leiste.
  3. Betriebssystem der Schulungs-VM: Debian 13
  4. Die Nutzerkennung lautet "shibboleth". Alle Passwörter lauten ebenfalls "shibboleth".
  5. Auf der VM befindet sich ein LDAP-Browser (phpLDAPadmin), der im Web-Browser (Firefox) als Lesezeichen gesetzt ist. Im Verzeichnis finden Sie sechs Test-Accounts mit verschiedenen Attributen.
  6. Zum besseren Verständnis des lokalen Setups (idp/sp1) hilft ein Blick in /etc/hosts und die Apache-Konfiguration unter /etc/apache2/sites-enabled.
  7. Die wichtigsten vorinstallierten Pakete sind Web-, Datenbank- und LDAP-Server:

People im LDAP

BenutzernameeduPersonAffiliationou
annastudent, memberStudierende
claudiaaffiliateGaeste
franziska - Externe
jochenaffiliateGaeste
karlalumnAlumni
petrafaculty,memberLehrende
mariestaff,memberMitarbeitende
thomasstaff,memberMitarbeitende


Hier starten wir mit dem Workshop

Aufgabe Bestandsaufnahme IdP

Zurück zum Inhaltsverzeichnis

Wesentliche Komponenten der Schulungs-VM:
  1. Shibboleth IdP
  2. Shibboleth-SP
  3. Webbrowser Firefox, mit Bookmarks für

Überblick Attribute-Resolver

Zurück zum Inhaltsverzeichnis

Verschaffen Sie sich einen Überblick über Attribut-Definitionen und DataConnectors.
Welche Attribute-Definitionen und DataConnectors sind vorhanden?

Überblick anzeigen

Attribute-Definitions

Attribute IDxsi:typeref
uidsimplemyLDAP
eduPersonAffiliationsimplemyLDAP
eduPersonScopedAffiliationscopedmyLDAP, eduPersonAffiliation
eduPersonEntitlementscriptedAttributeeduPersonAffiliation, common-lib-terms nur für member
samlPairwiseIDscopedStoredId
eduPersonTargetedIDsaml2NameIDStoredId

Data Connectors

DataConnector IDxsi:typeAttribute
staticAttributesstaticschacHomeOrganisation, o
StoredIdStoredIDpersistentID
myLDAPLDAPDirectorygivenName,sn,mail,displayName

Überblick relying-party

Die Datei relying-party.xml definiert, welche Protokolle/Profiles ein IdP anbietet und erlaubt maßgeschneiderte Einstellungen für verschiedene SPs. Zu unterscheiden sind die drei Beans:
Verschaffen Sie sich einen Überblick über die vorhandenen Inhalte dieser Beans.

Überblick anzeigen

shibboleth.unverifiedRelyingParty

ProfileAktivPost-Auth-FlowsNameID-Format-PrioritätBesonderheiten
SAML2.SSOnein--Auskommentiert, deaktiviert

shibboleth.defaultRelyingParty

ProfileAktivPost-Auth-FlowsNameID-Format-PrioritätBesonderheiten
SAML2.SSOjaattribute-releasepersistent,transientHauptprofile mit Attributfreigabe
SAML2.ECPja--Enhanced Client/Proxy für Web-Services
SAML2.Logoutja--Single Logout
SAML2.Attribute.Querynein--Auskommentiert, deaktiviert
SAML2.ArtifactResolutionja--Artifact-Auflösung aktiv

Überblick Attribute-Filter

Welche Filter-Regeln sind vorhanden?

Überblick anzeigen
Policy-IDPolicyRequirementRuleRP/ScopeBetroffene AttributeAuswirkung
alwaysReleaseANYAlle SPsschacHomeOrganzationVollständige Freigabe von schacHomeOrganization (permitAny=“true”)
SPs_localsRequester=“https://sp1.local/shibboleth”Lokaler SP1
  • eduPersonScopeAffiliation
  • sn
  • givenName
  • mail
  • uid
  • eduPersonTargetedId
Vollständige Freigabe von 7 Attributen an sp1.local

Loglevel

FÜr die Dauer dieses Workshops wird das Loglevel erhöht:
<!-- Datei: /opt/shibboleth-idp/conf/logback.xml -->
  <variable name="idp.loglevel.idp" value="DEBUG" />
  <variable name="idp.loglevel.ldap" value="WARN" />
  <variable name="idp.loglevel.messages" value="DEBUG" />
  <variable name="idp.loglevel.encryption" value="DEBUG" />
  <variable name="idp.loglevel.opensaml" value="INFO" />
  <variable name="idp.loglevel.props" value="INFO" />
  <variable name="idp.loglevel.httpclient" value="INFO" />
Stoßen Sie das Neuladen des Servlets manuell an:
touch /opt/shibboleth-idp/war/idp.war

Attribut-Übertragung

Welche Attribute werden bei einem Login auf SP1 und SP2 übertragen. Verlassen Sie sich nicht ausschließlich auf die Anzeige im Browser beim User-Consent. Prüfen Sie im Log-File die Assertion.
Dazu suchen Sie in der Log-Datei /opt/shibboleth-idp/logs/idp-process.log nach Assertion before encryption.
Hier finden Sie die vom IdP an den SP übertragenen Attribute, sowie die NameID im Format urn:oasis:names:tc:SAML:2.0:nameid-format:transient.

Assertion SP1
<!-- Datei: /opt/shibboleth-idp/logs/idp-process.log -->
    <?xml version="1.0" encoding="UTF-8"?><saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_c7ccec23382116735f43f2b7e6abc982" IssueInstant="2026-01-22T10:17:57.778Z" Version="2.0">
    <saml2:Issuer>https://idp.local/idp/shibboleth</saml2:Issuer>
    <saml2:Subject>
        <saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" NameQualifier="https://idp.local/idp/shibboleth" SPNameQualifier="https://sp1.local/shibboleth"xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">LSPX4Z4UJWIXKWFONRF5YUY75YTQ5TL2
        <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
          <saml2:SubjectConfirmationData Address="127.0.0.1" InResponseTo="_e7012caa5fda31c05824f4a2845ad070" NotOnOrAfter="2026-01-22T10:22:57.800Z" Recipient="https://sp1.local/Shibboleth.sso/SAML2/POST"/>
        </saml2:SubjectConfirmation>
    </saml2:Subject>
    <saml2:Conditions NotBefore="2026-01-22T10:17:57.778Z" NotOnOrAfter="2026-01-22T10:22:57.778Z">
        <saml2:AudienceRestriction>
            <saml2:Audience>https://sp1.local/shibboleth</saml2:Audience>
        </saml2:AudienceRestriction>
    </saml2:Conditions>
    <saml2:AuthnStatement AuthnInstant="2026-01-22T10:17:51.863Z" SessionIndex="_8f9a906bafe493d92cc8707909dc95eb">
        <saml2:SubjectLocality Address="127.0.0.1"/>
        <saml2:AuthnContext>
            <saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef>
        </saml2:AuthnContext>
    </saml2:AuthnStatement>
    <saml2:AttributeStatement>
        <saml2:Attribute FriendlyName="schacHomeOrganization" Name="urn:oid:1.3.6.1.4.1.25178.1.2.9" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
            <saml2:AttributeValue>local</saml2:AttributeValue>
        </saml2:Attribute>
        <saml2:Attribute FriendlyName="eduPersonScopedAffiliation" Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.9" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
            <saml2:AttributeValue>student@local</saml2:AttributeValue>
            <saml2:AttributeValue>member@local</saml2:AttributeValue>
        </saml2:Attribute>
        <saml2:Attribute FriendlyName="givenName" Name="urn:oid:2.5.4.42" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
            <saml2:AttributeValue>Anna</saml2:AttributeValue>
        </saml2:Attribute>
        <saml2:Attribute FriendlyName="uid" Name="urn:oid:0.9.2342.19200300.100.1.1" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
            <saml2:AttributeValue>anna</saml2:AttributeValue>
        </saml2:Attribute>
        <saml2:Attribute FriendlyName="mail" Name="urn:oid:0.9.2342.19200300.100.1.3" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
            <saml2:AttributeValue>anna.schmidt@uni.de</saml2:AttributeValue>
        </saml2:Attribute>
        <saml2:Attribute FriendlyName="eduPersonTargetedID" Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
            <saml2:AttributeValue>
                <saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" NameQualifier="https://idp.local/idp/shibboleth" SPNameQualifier="https://sp1.local/shibboleth">LSPX4Z4UJWIXKWFONRF5YUY75YTQ5TL2</saml2:NameID>
            </saml2:AttributeValue>
        </saml2:Attribute>
        <saml2:Attribute FriendlyName="sn" Name="urn:oid:2.5.4.4" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
            <saml2:AttributeValue>Schmidt</saml2:AttributeValue>
        </saml2:Attribute>
    </saml2:AttributeStatement>
</saml2:Assertion>
  

Assertion SP2
<!-- Datei: /opt/shibboleth-idp/logs/idp-process.log -->
      <?xml version="1.0" encoding="UTF-8"?><saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_2e601cd9c678ea0aa6d2de6a0151fd0c" IssueInstant="2026-01-22T10:18:22.533Z" Version="2.0">
    <saml2:Issuer>https://idp.local/idp/shibboleth</saml2:Issuer>
    <saml2:Subject>
        <saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" NameQualifier="https://idp.local/idp/shibboleth" SPNameQualifier="https://sp2.local/shibboleth" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">QI3P4IOWTZDFLPPISAFD7TYAJLXA5GRX</saml2:NameID>
        <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
            <saml2:SubjectConfirmationData Address="127.0.0.1" InResponseTo="_9adf8c3893cb82c8758a2e5200b3e8fa" NotOnOrAfter="2026-01-22T10:23:22.551Z" Recipient="https://sp2.local/Shibboleth.sso/SAML2/POST"/>
        </saml2:SubjectConfirmation>
    </saml2:Subject>
    <saml2:Conditions NotBefore="2026-01-22T10:18:22.533Z" NotOnOrAfter="2026-01-22T10:23:22.533Z">
        <saml2:AudienceRestriction>
            <saml2:Audience>https://sp2.local/shibboleth</saml2:Audience>
        </saml2:AudienceRestriction>
    </saml2:Conditions>
    <saml2:AuthnStatement AuthnInstant="2026-01-22T10:18:18.582Z" SessionIndex="_6f0771619be64724cbd984657f7289ea">
        <saml2:SubjectLocality Address="127.0.0.1"/>
        <saml2:AuthnContext>
            <saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef>
        </saml2:AuthnContext>
    </saml2:AuthnStatement>
    <saml2:AttributeStatement>
        <saml2:Attribute FriendlyName="schacHomeOrganization" Name="urn:oid:1.3.6.1.4.1.25178.1.2.9" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
            <saml2:AttributeValue>local</saml2:AttributeValue>
        </saml2:Attribute>
    </saml2:AttributeStatement>
</saml2:Assertion>
    

Aufwärmübung

Zurück zum Inhaltsverzeichnis

Aufgabe

Definieren Sie eine zusätzliche Filterregel:
Das Attribut eduPersonEntitlement wird immer übergeben, sofern es den Wert urn:mace:dir:entitlement:common-lib-terms (Bibliotheksnutzung) hat.

Template AttributeFilterPolicy:
<!-- Datei: /opt/shibboleth-idp/conf/attribute-filter.xml -->
  <!-- Template AttributeFilterPolicy -->
    <AttributeFilterPolicy id="example1">
      <PolicyRequirementRule xsi:type="Requester" value="https://sp.example.org"/>
      <AttributeRule attributeID="mail">
        <PermitValueRule xsi:type="ANY"/>
      </AttributeRule>
    </AttributeFilterPolicy">
Im Template kommen die Rule Types Requester und ANY zum Einsatz.
Weitere Rule Types werden hier erläutert: weitere Rule Types

Zur Lösungsfindung helfen Ihnen folgende Fragen:
  1. PolicyRequirementRule
  2. AttributeRule

Lösung

Lösung
<!-- Datei: /opt/shibboleth-idp/conf/attribute-filter.xml -->
    <!-- Bibliotheksnutzung -->
    <AttributeFilterPolicy id="lib-entitlement-policy">
      <PolicyRequirementRule xsi:type="ANY"/>
          <AttributeRule attributeID="eduPersonEntitlement">
            <PermitValueRule xsi:type="Value" value="urn:mace:dir:entitlement:common-lib-terms"/>
          </AttributeRule>
    </AttributeFilterPolicy>   

Überprüfen Sie die Filterregel, indem Sie einen Login auf SP1 und SP2 durchführen.

Übung 1 - eduPersonAffiliation

Zurück zum Inhaltsverzeichnis

Aufgabe

  • für die Erzeugung von eduPersonAffiliation soll das Attribut ou verwendet werden
  • Zur Autorisierung soll das Attribut eduPersonAffiliation bereit gestellt werden
  • Passen Sie die Filterregeln an: Nur Angehörige (member) sollen Zugriff auf Bibliotheksinhalte erhalten
  • Herangehensweise Attribute-Definition

    Nehmen Sie an, das Attribut eduPersonAffiliation wird nicht vom LDAP geliefert.

    Schritt 1 - vorhandene Attribute-Definition für eduPersonAffiliation auskommentieren/entfernen

    Dafür kommentieren Sie als erstes die Attribute-Definition in der Datei attribute-resolver.xml aus:
    <!-- Datei: /opt/shibboleth-idp/conf/attribute-resolver.xml -->
      <AttributeDefinition xsi:type="Simple" id="eduPersonAffiliation">
        <InputDataConnector ref="myLDAP" attributeNames="eduPersonAffiliation" />
      </AttributeDefinition> 
    


    Schritt 2 - Attribute-Definition für ou anlegen

    Das Attribut eduPersonAffiliation soll mit Werten aus dem Attribut ou erzeugt/gemappt werden.
    Das Attribut ou ist zwar im LDAP vorhanden, wird aber in der attribute-resolver.xml noch nicht definiert.
    Damit Sie ou verwenden können, müssen Sie es definieren.
    Orientieren Sie sich bei der Attribute-Definition an der auskommentierten Definition von eduPersonAffiliation

    Schritt 3 - Mapping ou zu eduPersonAffiliation

    Informieren Sie sich im DFN-Wiki über das Attribut eduPersonAffiliation und die in Frage kommenden Werte dieses Attributs.

    Sie werden feststellen, dass diese Werte nicht aus dem LDAP kommen.
    Finden Sie ein geeignetes Mapping von ou auf eduPersonAffiliation

    Nachfolgend finden Sie die Tabelle mit dem Mapping.


    Tabelle Zuordnung ou-->eduPersonAffiliation
    GruppeoueduPersonAffiliation
    Mitarbeitendeou=Mitarbeitendestaff
    Studierendeou=Studierendestudent
    Lehrendeou=Lehrendefaculty
    Gaesteou=Gaesteaffiliate
    Externeou=Externe


    Schritt 4 - Attribute-Definition für eduPersonAffiliation vom Type mapped

    Template:
    <!-- Datei: /opt/shibboleth-idp/conf/attribute-resolver.xml -->
      <AttributeDefinition xsi:type="Mapped" id="mappedAttribute">
        <InputAttributeDefinition ref="myLDAP" attributeNames="sourceAttr"/>
        <ValueMap>
          <ReturnValue>mappedValue1</ReturnValue>
          <SourceValue>sourceValue1</SourceValue>
        <ValueMap/>
        <DefaultValue passThru="true"/>
      </AttributeDefinition> 
    

    Lösung Attribute-Definition

    Attribute-Definition
    <!-- Datei: /opt/shibboleth-idp/conf/attribute-resolver.xml -->
        <AttributeDefinition xsi:type="Simple" id="ou">
          <InputDataConnector ref="myLDAP" attributeNames="ou"/>
        </AttributeDefinition>
        <!-- eduPersonAffiliation als Mapping auf ou -->
    <AttributeDefinition xsi:type="Mapped" id="eduPersonAffiliation">
      <InputAttributeDefinition ref="ou"/>
        <ValueMap>
          <ReturnValue>student</ReturnValue>
          <SourceValue>Studierende</SourceValue>
        </ValueMap>
        <ValueMap>
          <ReturnValue>staff</ReturnValue>
          <SourceValue>Mitarbeitende</SourceValue>
        </ValueMap>
        <ValueMap>
          <ReturnValue>faculty</ReturnValue>
          <SourceValue>Lehrende</SourceValue>
        </ValueMap>
        <ValueMap>
          <ReturnValue>affiliate</ReturnValue>
          <SourceValue>Gaeste</SourceValue>
        </ValueMap>
        <ValueMap>
          <ReturnValue>member</ReturnValue>
          <SourceValue>Studierende</SourceValue>
          <SourceValue>Mitarbeitende</SourceValue>
          <SourceValue>Lehrende</SourceValue>
        </ValueMap>
    </AttributeDefinition>
    

    Herangehensweise Attribute-Filter

    Die in der Aufwärmübung erstellte Regel muss geändert werden:
    <!-- Datei: /opt/shibboleth-idp/conf/attribute-filter.xml -->
      <!-- Bibliotheksnutzung -->
      <AttributeFilterPolicy id="lib-entitlement-policy">
        <PolicyRequirementRule xsi:type="ANY"/>
            <AttributeRule attributeID="eduPersonEntitlement">
              <PermitValueRule xsi:type="Value" value="urn:mace:dir:entitlement:common-lib-terms"/>
            </AttributeRule>
      </AttributeFilterPolicy>   
    
    Zur Lösungsfindung helfen Ihnen folgende Fragen:
    1. PolicyRequirementRule
    2. AttributeRule
    Hier noch einmal der Link zu den Rule Types

    Lösung Attribute-Filter

    Attribute-Filter
    <!-- Datei: /opt/shibboleth-idp/conf/attribute-filter.xml --> 
        <!-- Bibliotheksnutzung -->
        <AttributeFilterPolicy id="lib-entitlement-policy">
          <PolicyRequirementRule xsi:type="Value" attributeID="eduPersonAffiliation" value="member" caseSensitive="false"/>
          <AttributeRule attributeID="eduPersonEntitlement">
           <PermitValueRule xsi:type="Value" value="urn:mace:dir:entitlement:common-lib-terms"/>
          </AttributeRule>
        </AttributeFilterPolicy>   
    

    Überprüfen Sie, ob die Filterregel funktioniert.

    Übung 2 - Required Attributes

    Zurück zum Inhaltsverzeichnis

    SP-Verantwortliche deklarieren benötigte Attribute in den Metadaten. Der IdP kann diese Angaben auswerten und bei der Attributfreigabe berücksichtigen.

    Aufgabe - Attributregel für Required Attributes

    Erweitern Sie die Regeln für die lokalen SPs. Attribute sollen nur übermittelt werden, wenn in den Metadaten die Option isRequired="true" gesetzt ist.
    Doku zur AttributeFilterPolicyConfiguration im shib-Wiki (Reference --> XML Attributes)

    Herangehensweise

    Folgende bestehende Regel soll geändert werden:
    <!-- Datei: /opt/shibboleth-idp/conf/attribute-filter.xml -->
      <!-- Release an additional attribute to an SP -->
      <AttributeFilterPolicy id="SPs_locals">
        <PolicyRequirementRule xsi:type="Requester" value="https://sp1.local/shibboleth"/>
            <AttributeRule attributeID="eduPersonScopedAffiliation" permitAny="true"/>
            <AttributeRule attributeID="sn"                         permitAny="true"/>
            <AttributeRule attributeID="givenName"                  permitAny="true"/>
            <AttributeRule attributeID="mail"                       permitAny="true"/>
            <AttributeRule attributeID="uid"                        permitAny="true"/>
            <AttributeRule attributeID="eduPersonEntitlement"       permitAny="true"/>
            <AttributeRule attributeID="eduPersonTargeted"          permitAny="true"/>
      </AttributeFilterPolicy>   
    
    Zur Lösungsfindung helfen Ihnen folgende Fragen:

    Lösung Attributregel für Required Attributes

    Attribute-Filter
    <!-- Datei: /opt/shibboleth-idp/conf/attribute-filter.xml -->
          <!-- Release an additional attribute to an SP -->  
          <AttributeFilterPolicy id="SPs_locals">
            <PolicyRequirementRule xsi:type="Requester" value="https://sp1.local/shibboleth" />
              <AttributeRule attributeID="eduPersonScopedAffiliation" permitAny="true">
                <PermitValueRule xsi:type="AttributeInMetadata" onlyIfRequired="true"/>
              </AttributeRule>
              <AttributeRule attributeID="sn" permitAny="true">
                <PermitValueRule xsi:type="AttributeInMetadata" onlyIfRequired="true"/>
              </AttributeRule>
              <AttributeRule attributeID="givenName" permitAny="true">
                <PermitValueRule xsi:type="AttributeInMetadata" onlyIfRequired="true"/>
              </AttributeRule>
              <AttributeRule attributeID="mail"                       permitAny="true">
                <PermitValueRule xsi:type="AttributeInMetadata" onlyIfRequired="true"/>
              </AttributeRule>
              <AttributeRule attributeID="uid"                        permitAny="true">
                <PermitValueRule xsi:type="AttributeInMetadata" onlyIfRequired="true"/>
              </AttributeRule>
              <AttributeRule attributeID="eduPersonEntitlement"       permitAny="true">
                <PermitValueRule xsi:type="AttributeInMetadata" onlyIfRequired="true"/>
              </AttributeRule>
              <AttributeRule attributeID="eduPersonTargetedID"          permitAny="true">
                <PermitValueRule xsi:type="AttributeInMetadata" onlyIfRequired="true"/>
              </AttributeRule>
            </AttributeFilterPolicy>       
      

    Überprüfen Sie das Funktionieren des Attribute-Filters durch Anmelden an SP1 und SP2 und finden Sie im Logfile idp-process.log den entsprechenden Abschnitt.
    Werfen Sie spätestens jetzt einen Blick in die Metadaten und finden Sie heraus, welche Attribute als required angegeben sind.

    Ausszug Log-File
    <!-- Datei: /opt/shibboleth-idp/logs/idp-process.log -->
          DEBUG [net.shibboleth.idp.attribute.filter.AttributeFilterPolicy:121] - Attribute Filter Policy 'SPs_locals'  Policy is active for this request
    127.0.0.1 - DEBUG [net.shibboleth.idp.attribute.filter.AttributeFilterPolicy:147] - Attribute Filter Policy 'SPs_locals'  Applying attribute filter policy to current set
     of attributes: [samlPairwiseID, eduPersonTargetedID, uid, schacHomeOrganization, eduPersonAffiliation, displayName, mail, givenName, sn, eduPersonScopedAffiliation, ou, eduPersonEntitlement]
    127.0.0.1 - DEBUG [net.shibboleth.idp.attribute.filter.AttributeRule:149] - Attribute filtering engine '/AttributeFilterPolicyGroup:ShibbolethFilterPolicy/AttributeRule:
    _2ff8039f7e80cb06831fd6f1e22f0057'  Filtering values for attribute 'eduPersonScopedAffiliation' which currently contains 2 values
    127.0.0.1 - DEBUG [net.shibboleth.idp.attribute.filter.AttributeRule:158] - Attribute filtering engine '/AttributeFilterPolicyGroup:ShibbolethFilterPolicy/AttributeRule:
    _2ff8039f7e80cb06831fd6f1e22f0057'  Filter has permitted the release of 0 values for attribute 'eduPersonScopedAffiliation'
    127.0.0.1 - DEBUG [net.shibboleth.idp.attribute.filter.AttributeRule:149] - Attribute filtering engine '/AttributeFilterPolicyGroup:ShibbolethFilterPolicy/AttributeRule:
    _5ddfcfda315c39b57fb5c0ac7ad2e305'  Filtering values for attribute 'sn' which currently contains 1 values
    127.0.0.1 - DEBUG [net.shibboleth.idp.attribute.filter.AttributeRule:158] - Attribute filtering engine '/AttributeFilterPolicyGroup:ShibbolethFilterPolicy/AttributeRule:
    _5ddfcfda315c39b57fb5c0ac7ad2e305'  Filter has permitted the release of 0 values for attribute 'sn'
    127.0.0.1 - DEBUG [net.shibboleth.idp.attribute.filter.AttributeRule:149] - Attribute filtering engine '/AttributeFilterPolicyGroup:ShibbolethFilterPolicy/AttributeRule:
    _b12f98cfafad8042bb7bec5f48db391e'  Filtering values for attribute 'givenName' which currently contains 1 values
    127.0.0.1 - DEBUG [net.shibboleth.idp.attribute.filter.AttributeRule:158] - Attribute filtering engine '/AttributeFilterPolicyGroup:ShibbolethFilterPolicy/AttributeRule:
    _b12f98cfafad8042bb7bec5f48db391e'  Filter has permitted the release of 0 values for attribute 'givenName'
    127.0.0.1 - DEBUG [net.shibboleth.idp.attribute.filter.AttributeRule:149] - Attribute filtering engine '/AttributeFilterPolicyGroup:ShibbolethFilterPolicy/AttributeRule:
    _fbab53fc0d7b3ae8f5cb363bfa95b163'  Filtering values for attribute 'mail' which currently contains 1 values
    127.0.0.1 - DEBUG [net.shibboleth.idp.attribute.filter.matcher.saml.impl.AttributeInMetadataMatcher:251] - Attribute Filter '/AttributeFilterPolicyGroup:ShibbolethFilter
    Policy/PermitValueRule:_c1d683e60e9688f9615a2363ce4495ee': Decoded attribute mail found in metadata, but not required, values not matched
    127.0.0.1 - DEBUG [net.shibboleth.idp.attribute.filter.AttributeRule:158] - Attribute filtering engine '/AttributeFilterPolicyGroup:ShibbolethFilterPolicy/AttributeRule:
    _fbab53fc0d7b3ae8f5cb363bfa95b163'  Filter has permitted the release of 0 values for attribute 'mail'
    127.0.0.1 - DEBUG [net.shibboleth.idp.attribute.filter.AttributeRule:149] - Attribute filtering engine '/AttributeFilterPolicyGroup:ShibbolethFilterPolicy/AttributeRule:
    _296bbf7260984e737d4de241431ca9d8'  Filtering values for attribute 'uid' which currently contains 1 values
    127.0.0.1 - DEBUG [net.shibboleth.idp.attribute.filter.AttributeRule:158] - Attribute filtering engine '/AttributeFilterPolicyGroup:ShibbolethFilterPolicy/AttributeRule:
    _296bbf7260984e737d4de241431ca9d8'  Filter has permitted the release of 0 values for attribute 'uid'
    127.0.0.1 - DEBUG [net.shibboleth.idp.attribute.filter.AttributeRule:149] - Attribute filtering engine '/AttributeFilterPolicyGroup:ShibbolethFilterPolicy/AttributeRule:
    _bc136f4b41b15ca2b0f3ac8aab50408c'  Filtering values for attribute 'eduPersonEntitlement' which currently contains 3 values
    127.0.0.1 - DEBUG [net.shibboleth.idp.attribute.filter.AttributeRule:158] - Attribute filtering engine '/AttributeFilterPolicyGroup:ShibbolethFilterPolicy/AttributeRule:
    _bc136f4b41b15ca2b0f3ac8aab50408c'  Filter has permitted the release of 0 values for attribute 'eduPersonEntitlement'
    127.0.0.1 - DEBUG [net.shibboleth.idp.attribute.filter.AttributeRule:149] - Attribute filtering engine '/AttributeFilterPolicyGroup:ShibbolethFilterPolicy/AttributeRule:
    _f2f91f8b94cf5d064727790386ac67a4'  Filtering values for attribute 'eduPersonTargetedID' which currently contains 1 values
    127.0.0.1 - DEBUG [net.shibboleth.idp.attribute.filter.matcher.saml.impl.AttributeInMetadataMatcher:345] - Attribute Filter '/AttributeFilterPolicyGroup:ShibbolethFilter
    Policy/PermitValueRule:_133becbc1f27481810569b769210a3c4': Attribute eduPersonTargetedID found in metadata and no values specified
    127.0.0.1 - DEBUG [net.shibboleth.idp.attribute.filter.AttributeRule:158] - Attribute filtering engine '/AttributeFilterPolicyGroup:ShibbolethFilterPolicy/AttributeRule:
    _f2f91f8b94cf5d064727790386ac67a4'  Filter has permitted the release of 1 values for attribute 'eduPersonTargetedID'
        

    REFEDS Assurance Framework

    Zurück zum Inhaltsverzeichnis

    Ausführliche Informationen zum REFEDS Assurance Framework finden Sie im DFN_Wiki

    Übung 3 - eduPersonAssurance

    Zurück zum Inhaltsverzeichnis

    Definieren Sie das Attribut eduPersonAssurance nach folgenden Kriterien und legen Sie eine Filter-Regel an

    Aufgabe eduPersonAssurance

    1. Signalisieren Sie die grundsätzliche Konformität mit dem REFEDS Assurance Framework und mit Version 2 des REFEDS Assurance Frameworks
    2. Die Prozesse zur Aktualisierung der Nutzendendaten und zur Deprovisionierung sind einheitlich für alle Nutzenden & die Aktualisierung erfolgt innerhalb eines Monats
    3. Die Anforderungen bezüglich Identifier Uniqueness (UN-0 bis UN-3) werden erfüllt
    4. eduPersonAssurance enthält keine personenbezogenen Daten und soll deshalb an alle SP übertragen werden

    Herangehensweise attribute-resolver.xml

    Folgender <DataConnector> soll erweitert werden:
    <!-- Datei: /opt/shibboleth-idp/conf/attribute-resolver.xml -->
      <DataConnector id="staticAttributes" xsi:type="Static" exportAttributes="schacHomeOrganization">
        <Attribute id="schacHomeOrganization">
          <Value>%{idp.scope}</Value>
        </Attribute>
        <Attribute id="o">
          <Value>idp.local</Value>
        </Attribute>
      </DataConnector>
    
    Außerdem benötigen Sie eine Attribut-Definition für das Attribut eduPersonAssurance nach dem Template:
    <!-- Datei: /opt/shibboleth-idp/conf/attribute-resolver.xml -->
      <AttributeDefinition xsi:type="Simple" id="[ATTRIBUTE-ID]">
        <InputDataConnector ref="[DATACONNECTOR-ID]" attributeNames="[SOURCE-ATTRIBUTE-NAME]" />
      </AttributeDefinition>
    

    Lösung attribute-resolver.xml

    Attribute-Resolver
    <!-- Datei: /opt/shibboleth-idp/conf/attribute-resolver.xml -->
      <!--eduPersonAssurance als statisches Attribut -->
    <AttributeDefinition xsi:type="Simple" id="eduPersonAssurance">
      <InputDataConnector ref="staticAttributes" attributeNames="eduPersonAssurance" />
    </AttributeDefinition>
    
    <DataConnector id="staticAttributes" xsi:type="Static" exportAttributes="schacHomeOrganization">
      <Attribute id="schacHomeOrganization">
        <Value>%{idp.scope}</Value>
      </Attribute>
      <Attribute id="o">
        <Value>idp.local</Value>
      </Attribute>
      <Attribute id="eduPersonAssurance">
        <Value>https://refeds.org/assurance</Value>
        <Value>https://refeds.org/assurance/version/2</Value>
        <Value>https://refeds.org/assurance/ATP/ePA-1m</Value>
        <Value>https://refeds.org/assurance/ID/unique</Value>
      </Attribute>
    </DataConnector>
    

    Herangehensweise attribute-filter.xml

    eduPersonAssurance enthält keine personenbezogenen Daten und soll deshalb an alle SP übertragen werden.
    Template AttributeFilterPolicy:
    <!-- Datei: /opt/shibboleth-idp/conf/attribute-filter.xml -->
      <!-- Template AttributeFilterPolicy -->
        <AttributeFilterPolicy id="example1">
          <PolicyRequirementRule xsi:type="Requester" value="https://sp.example.org"/>
          <AttributeRule attributeID="mail">
            <PermitValueRule xsi:type="ANY"/>
          </AttributeRule>
        </AttributeFilterPolicy">
    
    Im Template kommen die Rule Types Requester und ANY zum Einsatz.
    Weitere Rule Types werden hier erläutert: weitere Rule Types

    Zur Lösungsfindung helfen Ihnen folgende Fragen:
    1. PolicyRequirementRule
    2. AttributeRule

    Lösung attribute-filter.xml

    Attribute-Filter
    <!-- Datei: /opt/shibboleth-idp/conf/attribute-filter.xml -->
        <!-- Verlässlichkeitsinformationen sind nicht personenbeziehbar
            und sollten grundsätzlich an jeden SP übertragen werden -->
        <AttributeFilterPolicy id="ReleaseAssuranceToAnyone">
          <PolicyRequirementRule xsi:type="ANY" />
          <AttributeRule attributeID="eduPersonAssurance" permitAny="true" />
        </AttributeFilterPolicy>
    

    Hinweis

    Die Form:
    <!-- Datei: /opt/shibboleth-idp/conf/attribute-filter.xml -->
     <AttributeRule attributeID="..." permitAny="true" />
    ist die Kurzform für:
    <!-- Datei: /opt/shibboleth-idp/conf/attribute-filter.xml -->
      <AttributeRule attributeID="...">
        <PermitValueRule xsi:type="ANY" />
      </AttributeRule>

    Entity Attributes & Categories

    Zurück zum Inhaltsverzeichnis

    Ausführliche Informationen zu Entity Attributes und Entity Categories finden Sie im DFN_Wiki

    Übung 4 - Anbindung des IdP an das DFN edu-ID System

    Zurück zum Inhaltsverzeichnis

    Infos zu edu-ID sind hier zu finden.

    Aufgabe Anbindung des IdP an das DFN edu-ID System

    Richten Sie auf dem IdP die Unterstützung für edu-ID ein. Der Test kann auf SP2 durchgeführt werden. Laut Metadaten nimmt dieser SP bereits an edu-ID teil.

    Herangehensweise

    Stellen Sie fest, welche Attribute benötigt werden und erweitern Sie ggf. die Attribut-Definitionen.

    Attribut-Bundle

    obligatorisch, sofern vorhanden, sind folgende Attribute:
    optional sind weitere Attribute:

    Für die neu zu erstellende Filterregel können Sie folgendes Template verwenden:
    <!-- Datei: /opt/shibboleth-idp/conf/attribute-filter.xml -->
      <!-- Policy gilt nur für Entitäten mit bestimmtem Entity-Category-Attribut -->  
      <AttributeFilterPolicy id="examplePolicy">
        <PolicyRequirementRule xsi:type="EntityAttributeExactMatch"
                                  attributeName="http://macedir.org/entity-category"
                                  attributeValue="http://example.org/category/example-category"/>
    
    <!-- Attribute und deren Freigaben -->                        
          <AttributeRule attributeID="attribute1" permitAny="true"/>
          <AttributeRule attributeID="attribute2" permitAny="true"/>
        </AttributeFilterPolicy>       
    

    Lösung

    Eine mögliche Lösung könnte wie folgt aussehen:
    Attribute-Filter für edu-ID
    <!-- Datei: /opt/shibboleth-idp/conf/attribute-filter.xml -->
          <!-- Freigabe für das edu-id System -->  
          <AttributeFilterPolicy id="eduid_proxy">
            <PolicyRequirementRule xsi:type="EntityAttributeExactMatch" 
                                   attributeName="http://macedir.org/entity-category"
                                   attributeValue="http://aai.dfn.de/category/dfn-edu-id" />
            <AttributeRule attributeID="eduPersonAffiliation"          permitAny="true" />
            <AttributeRule attributeID="samlPairwiseID"                permitAny="true" />
            <AttributeRule attributeID="givenName"                     permitAny="true" />
            <AttributeRule attributeID="sn"                            permitAny="true" />
            <AttributeRule attributeID="mail"                          permitAny="true" />
            <AttributeRule attributeID="schacHomeOrganization"         permitAny="true" />
            <AttributeRule attributeID="eduPersonAssurance"            permitAny="true" />
            <!-- optionale Attribute: -->
            <AttributeRule attributeID="displayName"                   permitAny="true" />
            <AttributeRule attributeID="schacPlaceOfBirth"             permitAny="true" />
            <AttributeRule attributeID="schacDateOfBirth"              permitAny="true" />
            <AttributeRule attributeID="eduPersonEntitlement"          permitAny="true" />
            <AttributeRule attributeID="eduPersonOrcid"                permitAny="true" />
            <AttributeRule attributeID="l"                             permitAny="true" />
            <AttributeRule attributeID="o"                             permitAny="true" />
            <AttributeRule attributeID="postalCode"                    permitAny="true" />
            <AttributeRule attributeID="schacCountryOfResidence"       permitAny="true" />
            <AttributeRule attributeID="schacPersonalUniqueCode"       permitAny="true" />
            <AttributeRule attributeID="street"                        permitAny="true" />
          </AttributeFilterPolicy>       
      

    Übung 5 - Context Check-Modul

    Zurück zum Inhaltsverzeichnis

    IdP-seitig soll der Login auf SP1 auf Angestellte (staff) beschränkt werden. Es soll eine Intercept-Policy erstellt werden, die nur dann weiterläuft, wenn der eingeloggte Benutzer zur Gruppe der Mitarbeitenden gehört. Ein ähnliches Beispiel finden Sie im DFN_Wiki beschrieben.
    Der Context Check Interceptor Flow und dessen Konfiguration ist sehr ausführlich im Shib-Wiki dokumentiert.

    Herangehensweise


    Schritt 1 - Modul aktivieren

    mittels module.sh-Script und Option "-e" enablen:
    /opt/shibboleth-idp/bin/module.sh -e idp.intercept.ContextCheck 

    Modulinformationen anzeigen lassen:
    /opt/shibboleth-idp/bin/module.sh -i idp.intercept.ContextCheck 
    
      Module: idp.intercept.ContextCheck
        Name: Context Checking Interceptor
        Desc: Interceptor flow for authorization based on request state
        Help: https://shibboleth.atlassian.net/wiki/spaces/IDP5/pages/3199509927/ContextCheckInterceptConfiguration
        Status: ENABLED
        Resource: (noreplace) conf/intercept/context-check-intercept-config.xml


    Schritt 2 - Bedingung definieren

    Konfigurieren Sie ein Bean, welches prüft, ob das Attribut eduPersonScopedAffiliation=staff besitzt. Das Bean wird als Condition verwendet.
    Das bedeutet: Es liefert am Ende ein Ja/Nein-Ergebnis zurück.
    (Template in Datei context-check-intercept-config.xml vorhanden)

    Wichtige Bausteine des Beans:
    Die Datei Datei: context-check-intercept-config.xml enthält ein Template:
    <!-- Datei: conf/intercept/context-check-intercept-config.xml -->
      <bean id="shibboleth.context-check.Condition" ....>
    ....
      </bean>   
    

    Die Bedingung basiert auf einer einfachen Attributprüfung, wie im Shibboleth-Wiki beschrieben.
    <!-- Check for a particular entitlement -->
    <bean parent="shibboleth.Conditions.SimpleAttribute" p:useUnfilteredAttributes="true">
      <property name="attributeValueMap">
        <map>
          <entry key="entitlement">
            <list>
              <value>urn:mace:dir:entitlement:common-lib-terms</value>
            </list>
          </entry>
        </map>
      </property>
    </bean>
    
    Lösung - Bedingung definieren
    <!-- Datei: /opt/shibboleth-idp/conf/intercept/context-check-intercept-config.xml -->
        <bean id="shibboleth.context-check.Condition" parent="shibboleth.Conditions.SimpleAttribute" p:useUnfilteredAttributes="true">
        <property name="attributeValueMap">
            <map>
              <entry key="eduPersonScopedAffiliation">
                <list>
                  <value>staff</value>
                </list>
              </entry>
            </map>
          </property>
        </bean>   
    

    Schritt 3 - Post-Authentication-Flows um Context Check erweitern

    Erstellen Sie shibboleth.RelyingPartyOverrides als Kopie von shibboleth.DefaultRelyingParty in conf/relying-party.xml, sodass für den SP https://sp1.local/shibboleth zuerst ein Context-Check und danach Attribut-Release läuft. Hinweis: shibboleth.DefaultRelyingParty ist das Template für ALLE SPs. Kopieren Sie es und ändern nur die Flows für diesen einen SP.
    shibboleth.DefaultRelyingParty als Template:
    <!-- Datei: /opt/shibboleth-idp/conf/relying-party.xml -->
      <bean id="shibboleth.DefaultRelyingParty" parent="RelyingParty">
        <property name="profileConfigurations">
            <list>
                <bean parent="SAML2.SSO"
    p:postAuthenticationFlows="#{{'attribute-release'}}"
    p:nameIDFormatPrecedence="#{{'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent', 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'}}" />
                <ref bean="SAML2.ECP" />
                <ref bean="SAML2.Logout" />
                <ref bean="SAML2.ArtifactResolution" />
            </list>
        </property>
    </bean>
    
    

    shibboleth.RelyingPartyOverrides sind SP-spezifische Ausnahmen von Defaults:
    <!-- Datei: /opt/shibboleth-idp/conf/relying-party.xml -->
      <bean parent="RelyingPartyByName" c:relyingPartyIds="https://sp1.local/shibboleth">
        <property name="profileConfigurations">
           <list>
               <bean parent="SAML2.SSO" 
                     p:postAuthenticationFlows="#{{'context-check', 'attribute-release'}}"
                     p:nameIDFormatPrecedence="#{{'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent', 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'}}" />
               <ref bean="SAML2.Logout" />
           </list>
        </property>
    </bean>
    

    Änderungen:
    Schritt 4 - Servlet neu laden und Loginversuch auf SP1 mit den Usern "anna" und "marie"

    Logfile Auszug - Login anna
    <!--logs/idp-process.log -->
    <?xml version="1.0" encoding="UTF-8"?><samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL="https://sp1.local/Shibboleth.sso/SAML2/POST" Desti
    nation="https://idp.local/idp/profile/SAML2/Redirect/SSO" ID="_ca6933e12d87c34f38f3b55fcd2804bb" IssueInstant="2026-04-28T11:02:22Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0">
       <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">https://sp1.local/shibboleth</saml:Issuer>
       <samlp:NameIDPolicy AllowCreate="1"/>
    </samlp:AuthnRequest>
    ...
    2026-04-28 13:02:33,069 - 127.0.0.1 - DEBUG [net.shibboleth.idp.profile.interceptor.impl.PopulateProfileInterceptorContext:127] - Profile Action PopulateProfileInterceptorContext: 
    Installing post-authn flow intercept/context-check into interceptor context
    2026-04-28 13:02:33,069 - 127.0.0.1 - DEBUG [net.shibboleth.idp.profile.interceptor.impl.PopulateProfileInterceptorContext:127] - Profile Action PopulateProfileInterceptorContext: 
    Installing post-authn flow intercept/attribute-release into interceptor context
    2026-04-28 13:02:33,069 - 127.0.0.1 - DEBUG [net.shibboleth.idp.profile.interceptor.impl.FilterFlowsByNonBrowserSupport:49] - Profile Action FilterFlowsByNonBrowserSupport: 
    Request does not have non-browser requirement, nothing to do
    2026-04-28 13:02:33,070 - 127.0.0.1 - DEBUG [net.shibboleth.idp.profile.interceptor.impl.SelectProfileInterceptorFlow:98] - Profile Action SelectProfileInterceptorFlow: 
    Checking flow intercept/context-check for applicability...
    2026-04-28 13:02:33,070 - 127.0.0.1 - DEBUG [net.shibboleth.idp.profile.interceptor.impl.SelectProfileInterceptorFlow:81] - Profile Action SelectProfileInterceptorFlow: 
    Selecting flow intercept/context-check
    2026-04-28 13:02:33,072 - 127.0.0.1 - INFO [Shibboleth-Audit.SSO:333] - 127.0.0.1|2026-04-28T11:02:23.022639902Z|2026-04 28T11:02:33.072278857Z|anna|
    https://sp1.local/shibboleth|||||||false|false||Redirect||ContextCheckDenied|||febc322726d5bc16c2c7dadf98d643e401698d44ce74aadee0edd9d6d9d0b6d9|
    Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
    


    Logfile Auszug - Login marie
    <!--logs/idp-process.log -->
        <samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL="https://sp1.local/Shibboleth.sso/SAML2/POST" Destination="https://idp.local/idp/profile/SAML2/Redirect/SSO" ID="_932064c98df068439c5cb8701848a599" IssueInstant="2026-04-28T10:54:33Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0">
            <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">https://sp1.local/shibboleth</saml:Issuer>
            <samlp:NameIDPolicy AllowCreate="1"/>
          </samlp:AuthnRequest>
          ...
          2026-04-28 12:54:40,007 - 127.0.0.1 - DEBUG [net.shibboleth.idp.profile.interceptor.impl.PopulateProfileInterceptorContext:127] - Profile Action PopulateProfileInterceptorContext: 
          Installing post-authn flow intercept/context-check into interceptor context
          2026-04-28 12:54:40,008 - 127.0.0.1 - DEBUG [net.shibboleth.idp.profile.interceptor.impl.SelectProfileInterceptorFlow:98] - Profile Action SelectProfileInterceptorFlow: 
          Checking flow intercept/context-check for applicability...
          2026-04-28 12:54:40,008 - 127.0.0.1 - DEBUG [net.shibboleth.idp.profile.interceptor.impl.SelectProfileInterceptorFlow:81] - Profile Action SelectProfileInterceptorFlow: 
          Selecting flow intercept/context-check
          2026-04-28 12:54:40,008 - 127.0.0.1 - DEBUG [net.shibboleth.idp.profile.interceptor.impl.WriteProfileInterceptorResultToStorage:65] - Profile Action WriteProfileInterceptorResultToStorage:
           No results available from interceptor context, nothing to store
          2026-04-28 12:54:40,008 - 127.0.0.1 - DEBUG [net.shibboleth.idp.profile.interceptor.impl.SelectProfileInterceptorFlow:63] - Profile Action SelectProfileInterceptorFlow: Moving completed flow intercept/context-check to completed set, selecting next one
          ...
          2026-04-28 12:54:43,049 - 127.0.0.1 - DEBUG [org.opensaml.saml.saml2.encryption.Encrypter:332] - Assertion before encryption:
          <?xml version="1.0" encoding="UTF-8"?><saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_2ae365f6631da75025ffefa0087cb2d3" IssueInstant="2026-04-28T10:54:43.008Z" Version="2.0">
            <saml2:Issuer>https://idp.local/idp/shibboleth</saml2:Issuer>
              <saml2:Subject>
                <saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" NameQualifier="https://idp.local/idp/shibboleth" SPNameQualifier="https://sp1.local/shibboleth" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">PEYUMXT4LNRI3AJYFXM5CT2PHB64LRLB</saml2:NameID>
                  <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
                    <saml2:SubjectConfirmationData Address="127.0.0.1" InResponseTo="_932064c98df068439c5cb8701848a599" NotOnOrAfter="2026-04-28T10:59:43.035Z" Recipient="https://sp1.local/Shibboleth.sso/SAML2/POST"/>
                  </saml2:SubjectConfirmation>
             </saml2:Subject>
               <saml2:Conditions NotBefore="2026-04-28T10:54:43.008Z" NotOnOrAfter="2026-04-28T10:59:43.008Z">
                 <saml2:AudienceRestriction>
                   <saml2:Audience>https://sp1.local/shibboleth</saml2:Audience>
                 </saml2:AudienceRestriction>
            </saml2:Conditions>
            <saml2:AuthnStatement AuthnInstant="2026-04-28T10:54:39.977Z" SessionIndex="_c629aa1db88c6a9ae49044b3c2f2eb25">
                <saml2:SubjectLocality Address="127.0.0.1"/>
                <saml2:AuthnContext>
                  <saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef>
                </saml2:AuthnContext>
            </saml2:AuthnStatement>
            <saml2:AttributeStatement>
              <saml2:Attribute FriendlyName="eduPersonAssurance" Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.11" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
                <saml2:AttributeValue>https://refeds.org/assurance</saml2:AttributeValue>
                  <saml2:AttributeValue>https://refeds.org/assurance/version/2</saml2:AttributeValue>
                  <saml2:AttributeValue>https://refeds.org/assurance/ATP/ePA-1m</saml2:AttributeValue>
                  <saml2:AttributeValue>https://refeds.org/assurance/ID/unique</saml2:AttributeValue>
              </saml2:Attribute>
              <saml2:Attribute FriendlyName="eduPersonTargetedID" Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
                <saml2:AttributeValue>
                  <saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent" NameQualifier="https://idp.local/idp/shibboleth" SPNameQualifier="https://sp1.local/shibboleth">PEYUMXT4LNRI3AJYFXM5CT2PHB64LRLB</saml2:NameID>
                </saml2:AttributeValue>
              </saml2:Attribute>
              <saml2:Attribute FriendlyName="schacHomeOrganization" Name="urn:oid:1.3.6.1.4.1.25178.1.2.9" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
                <saml2:AttributeValue>local</saml2:AttributeValue>
              </saml2:Attribute>
              <saml2:Attribute FriendlyName="eduPersonEntitlement" Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.7" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
                <saml2:AttributeValue>urn:mace:dir:entitlement:common-lib-terms</saml2:AttributeValue>
              </saml2:Attribute>
            </saml2:AttributeStatement>
          </saml2:Assertion>
          ...
          2026-04-28 12:54:43,090 - 127.0.0.1 - INFO [Shibboleth-Audit.SSO:333] - 127.0.0.1|2026-04-28T10:54:33.046435928Z|2026-04-28T10:54:43.090547833Z|marie|
          https://sp1.local/shibboleth|_2ae365f6631da75025ffefa0087cb2d3|password|2026-04-28T10:54:39.977225644Z|eduPersonAssurance,eduPersonEntitlement,schacHomeOrganization,eduPersonTargetedID|
          PEYUMXT4LNRI3AJYFXM5CT2PHB64LRLB|persistent|false|false|AES128-GCM|Redirect|POST||Success||1b306718a66f7d11d6ca1c68d41df5dece5aefca29d23bcc315d6a202154b361|Mozilla/5.0 
          (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0