<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>shibboleth &amp;mdash; Kevin Sandy</title>
    <link>https://kevinsandy.com/tag:shibboleth</link>
    <description>Thoughts, musings, ramblings, and rants</description>
    <pubDate>Tue, 21 Apr 2026 10:41:24 +0000</pubDate>
    <image>
      <url>https://i.snap.as/IC0yYUyI.png</url>
      <title>shibboleth &amp;mdash; Kevin Sandy</title>
      <link>https://kevinsandy.com/tag:shibboleth</link>
    </image>
    <item>
      <title>Using objectGUID in Shibboleth IdP</title>
      <link>https://kevinsandy.com/using-objectguid-in-shibboleth-idp?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[I was setting up a new Shibboleth IdP in my lab to run some tests. When integrating it with my Active Directory domain, I wanted to use the objectGUID attribute as a unique user identifier. It meets the requirements of being unique and not reusable, while also not exposing any undesirable information like objectSID would.&#xA;&#xA;!--more--&#xA;&#xA;The problem is that objectGUID is stored as a binary attribute, so it must be handled differently in the IdP. Shibboleth has the ability to automatically handle binary attributes by listing them in a BinaryAttributes tag, but it does so by base64 encoding them. This isn&#39;t ideal because some SAML attributes, like a href=&#34;https://www.switch.ch/aai/support/documents/attributes/edupersonuniqueid/&#34; target=&#34;_blank&#34;eduPersonUniqueId/a, only allow alphanumeric characters.&#xA;&#xA;The solution I came up with was to allow Shibboleth to do the binary conversion, but then transform the base64 data to hex codes. The result is a user identifier that is unique, not reusable, and entirely composed of alphanumeric values.&#xA;&#xA;Here are the relevant parts of my attribute-resolver.xml setup.&#xA;&#xA;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&#xA;&lt;AttributeResolver&#xA;        xmlns=&#34;urn:mace:shibboleth:2.0:resolver&#34; &#xA;        xmlns:xsi=&#34;http://www.w3.org/2001/XMLSchema-instance&#34; &#xA;        xsi:schemaLocation=&#34;urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd&#34;  !-- ========================================== --&#xA;    !--      Attributes                            --&#xA;    !-- ========================================== --&#xA;&#xA;    AttributeDefinition id=&#34;eduPersonPrincipalName&#34; xsi:type=&#34;Scoped&#34; scope=&#34;%{idp.scope}&#34;&#xA;        InputAttributeDefinition ref=&#34;userIdentifier&#34;/&#xA;    /AttributeDefinition&#xA;&#xA;    AttributeDefinition id=&#34;eduPersonUniqueId&#34; xsi:type=&#34;Scoped&#34; scope=&#34;%{idp.scope}&#34;&#xA;        InputAttributeDefinition ref=&#34;userIdentifier&#34;/&#xA;    /AttributeDefinition&#xA;&#xA;    AttributeDefinition id=&#34;userIdentifier&#34; xsi:type=&#34;ScriptedAttribute&#34; dependencyOnly=&#34;true&#34;&#xA;        InputDataConnector ref=&#34;activeDirectory&#34; attributeNames=&#34;objectGUID&#34;/&#xA;        Script&#xA;            &lt;![CDATA[&#xA;            var base64guid = objectGUID.getValues().get(0);&#xA;            var hexguid = &#39;&#39;;&#xA;            for ( var i=0; i &lt; base64guid.length; i++ ) {&#xA;                var hex = base64guid.charCodeAt(i).toString(16);&#xA;                if ( hex.length == 1 ) {&#xA;                    hex = &#39;0&#39; + hex;&#xA;                }&#xA;                hexguid += hex;&#xA;            }&#xA;            userIdentifier.addValue(hexguid);&#xA;            ]]  /Script&#xA;    /AttributeDefinition&#xA;&#xA;    !-- ========================================== --&#xA;    !--      Data Connectors                       --&#xA;    !-- ========================================== --&#xA;&#xA;    &lt;DataConnector&#xA;            id=&#34;activeDirectory&#34;&#xA;            xsi:type=&#34;LDAPDirectory&#34;&#xA;            ldapURL=&#34;%{idp.attribute.resolver.LDAP.ldapURL}&#34;&#xA;            baseDN=&#34;%{idp.attribute.resolver.LDAP.baseDN}&#34;&#xA;            principal=&#34;%{idp.attribute.resolver.LDAP.bindDN}&#34;&#xA;            principalCredential=&#34;%{idp.attribute.resolver.LDAP.bindDNCredential}&#34;&#xA;            useStartTLS=&#34;%{idp.attribute.resolver.LDAP.useStartTLS}&#34;&#xA;            connectTimeout=&#34;%{idp.attribute.resolver.LDAP.connectTimeout}&#34;&#xA;            responseTimeout=&#34;%{idp.attribute.resolver.LDAP.responseTimeout}&#34;  FilterTemplate&#xA;            &lt;![CDATA[&#xA;            %{idp.attribute.resolver.LDAP.searchFilter}&#xA;            ]]  /FilterTemplate&#xA;        BinaryAttributesobjectGUID/BinaryAttributes&#xA;        ReturnAttributesgivenName sn displayName mail objectGUID/ReturnAttributes&#xA;    /DataConnector&#xA;&#xA;/AttributeResolver&#xA;&#xA;shibboleth]]&gt;</description>
      <content:encoded><![CDATA[<p>I was setting up a new Shibboleth IdP in my lab to run some tests. When integrating it with my Active Directory domain, I wanted to use the objectGUID attribute as a unique user identifier. It meets the requirements of being unique and not reusable, while also not exposing any undesirable information like objectSID would.</p>



<p>The problem is that objectGUID is stored as a binary attribute, so it must be handled differently in the IdP. Shibboleth has the ability to automatically handle binary attributes by listing them in a <code>&lt;BinaryAttributes&gt;</code> tag, but it does so by base64 encoding them. This isn&#39;t ideal because some SAML attributes, like <a href="https://www.switch.ch/aai/support/documents/attributes/edupersonuniqueid/" target="_blank">eduPersonUniqueId</a>, only allow alphanumeric characters.</p>

<p>The solution I came up with was to allow Shibboleth to do the binary conversion, but then transform the base64 data to hex codes. The result is a user identifier that is unique, not reusable, and entirely composed of alphanumeric values.</p>

<p>Here are the relevant parts of my attribute-resolver.xml setup.</p>

<pre><code class="language-xml">&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&gt;
&lt;AttributeResolver
        xmlns=&#34;urn:mace:shibboleth:2.0:resolver&#34; 
        xmlns:xsi=&#34;http://www.w3.org/2001/XMLSchema-instance&#34; 
        xsi:schemaLocation=&#34;urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd&#34;&gt;

    &lt;!-- ========================================== --&gt;
    &lt;!--      Attributes                            --&gt;
    &lt;!-- ========================================== --&gt;

    &lt;AttributeDefinition id=&#34;eduPersonPrincipalName&#34; xsi:type=&#34;Scoped&#34; scope=&#34;%{idp.scope}&#34;&gt;
        &lt;InputAttributeDefinition ref=&#34;userIdentifier&#34;/&gt;
    &lt;/AttributeDefinition&gt;

    &lt;AttributeDefinition id=&#34;eduPersonUniqueId&#34; xsi:type=&#34;Scoped&#34; scope=&#34;%{idp.scope}&#34;&gt;
        &lt;InputAttributeDefinition ref=&#34;userIdentifier&#34;/&gt;
    &lt;/AttributeDefinition&gt;

    &lt;AttributeDefinition id=&#34;userIdentifier&#34; xsi:type=&#34;ScriptedAttribute&#34; dependencyOnly=&#34;true&#34;&gt;
        &lt;InputDataConnector ref=&#34;activeDirectory&#34; attributeNames=&#34;objectGUID&#34;/&gt;
        &lt;Script&gt;
            &lt;![CDATA[
            var base64guid = objectGUID.getValues().get(0);
            var hexguid = &#39;&#39;;
            for ( var i=0; i &lt; base64guid.length; i++ ) {
                var hex = base64guid.charCodeAt(i).toString(16);
                if ( hex.length == 1 ) {
                    hex = &#39;0&#39; + hex;
                }
                hexguid += hex;
            }
            userIdentifier.addValue(hexguid);
            ]]&gt;
        &lt;/Script&gt;
    &lt;/AttributeDefinition&gt;

    &lt;!-- ========================================== --&gt;
    &lt;!--      Data Connectors                       --&gt;
    &lt;!-- ========================================== --&gt;

    &lt;DataConnector
            id=&#34;activeDirectory&#34;
            xsi:type=&#34;LDAPDirectory&#34;
            ldapURL=&#34;%{idp.attribute.resolver.LDAP.ldapURL}&#34;
            baseDN=&#34;%{idp.attribute.resolver.LDAP.baseDN}&#34;
            principal=&#34;%{idp.attribute.resolver.LDAP.bindDN}&#34;
            principalCredential=&#34;%{idp.attribute.resolver.LDAP.bindDNCredential}&#34;
            useStartTLS=&#34;%{idp.attribute.resolver.LDAP.useStartTLS}&#34;
            connectTimeout=&#34;%{idp.attribute.resolver.LDAP.connectTimeout}&#34;
            responseTimeout=&#34;%{idp.attribute.resolver.LDAP.responseTimeout}&#34;&gt;
        &lt;FilterTemplate&gt;
            &lt;![CDATA[
            %{idp.attribute.resolver.LDAP.searchFilter}
            ]]&gt;
        &lt;/FilterTemplate&gt;
        &lt;BinaryAttributes&gt;objectGUID&lt;/BinaryAttributes&gt;
        &lt;ReturnAttributes&gt;givenName sn displayName mail objectGUID&lt;/ReturnAttributes&gt;
    &lt;/DataConnector&gt;

&lt;/AttributeResolver&gt;
</code></pre>

<p><a href="https://kevinsandy.com/tag:shibboleth" class="hashtag"><span>#</span><span class="p-category">shibboleth</span></a></p>
]]></content:encoded>
      <guid>https://kevinsandy.com/using-objectguid-in-shibboleth-idp</guid>
      <pubDate>Sat, 05 Nov 2022 13:20:55 +0000</pubDate>
    </item>
  </channel>
</rss>