Skip to content

Set Up SSO with Shibboleth โ€‹

Shelf supports SSO with Shibboleth over SAML 2.0. This guide covers the Shelf-specific configuration your identity team adds to your IdP, and how your workspace owner maps your groups to Shelf roles.

Who does what # โ€‹

WhoTaskWhere
Your identity / IdP teamTrust Shelf's SP and release attributesShibboleth XML config (ยง1โ€“ยง6)
Your Shelf contactRegister your IdP in Shelf, enable encryptionHandled by Shelf
Your workspace ownerMap released groups to Shelf rolesShelf workspace settings, a GUI (ยง7)
Your usersSign inYour Shibboleth login page

Prerequisites # โ€‹

Read the general SSO prerequisites first โ€” in particular:

  • You have a non-SSO owner account ready to own the Shelf workspace.
  • Any existing standard accounts on your SSO domain are ready to be removed.
  • You've planned which of your groups/affiliations map to which Shelf role (Administrator, Self service, Base).

1. Service provider (SP) details # โ€‹

Register these Shelf SP values in your metadata-providers.xml:

DetailValue
ACS URLhttps://nmmqcuiasekdacmhwsxk.supabase.co/auth/v1/sso/saml/acs
Entity ID / Metadata URLhttps://nmmqcuiasekdacmhwsxk.supabase.co/auth/v1/sso/saml/metadata
Relay Statehttps://app.shelf.nu/oauthcallback

NOTE

Shelf's SP metadata is a live URL, so add it as an HTTPMetadataProvider (or download it once as a FilesystemMetadataProvider).

xml
<!-- conf/metadata-providers.xml (excerpt) -->
<MetadataProvider id="ShelfSP" xsi:type="HTTPMetadataProvider"
    metadataURL="https://nmmqcuiasekdacmhwsxk.supabase.co/auth/v1/sso/saml/metadata" />

2. Configure a persistent NameID (required) # โ€‹

Shelf identifies a returning user by the SAML NameID. Shibboleth's default is transient, which changes on every login โ€” Shelf rejects it, and sign-in fails immediately after authentication. Configure a persistent NameID for the Shelf relying party (emailAddress is also accepted).

xml
<!-- conf/saml-nameid.xml -->
<util:list id="shibboleth.saml2.NameIDFormatPrecedence">
    <value>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</value>
</util:list>
xml
<!-- conf/relying-party.xml (excerpt) โ€” pin persistent for the Shelf SP -->
<util:list id="shibboleth.RelyingPartyOverrides">
    <bean parent="RelyingPartyByName"
          c:relyingPartyIds="#{ {'https://nmmqcuiasekdacmhwsxk.supabase.co/auth/v1/sso/saml/metadata'} }">
        <property name="profileConfigurations">
            <list>
                <bean parent="SAML2.SSO"
                      p:nameIDFormatPrecedence="#{ {'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent'} }" />
            </list>
        </bean>
    </bean>
</util:list>

IMPORTANT

If you skip this, users reach the login screen but sign-in fails right afterward. If everything else checks out and login still fails at that point, this is almost always why.

3. Release the required attributes # โ€‹

Add an AttributeFilterPolicy scoped to Shelf's entity ID, releasing mail, givenName, sn, and your chosen group attribute (see ยง6). Without a release policy the assertion is empty and sign-in fails with "no email".

xml
<!-- conf/attribute-filter.xml (excerpt) โ€” Shibboleth IdP v5 -->
<AttributeFilterPolicyGroup id="ShelfPolicy"
    xmlns="urn:mace:shibboleth:2.0:afp"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="urn:mace:shibboleth:2.0:afp http://shibboleth.net/schema/idp/shibboleth-afp.xsd">

  <AttributeFilterPolicy id="releaseToShelf">
    <PolicyRequirementRule xsi:type="Requester"
        value="https://nmmqcuiasekdacmhwsxk.supabase.co/auth/v1/sso/saml/metadata" />

    <AttributeRule attributeID="mail"><PermitValueRule xsi:type="ANY" /></AttributeRule>
    <AttributeRule attributeID="givenName"><PermitValueRule xsi:type="ANY" /></AttributeRule>
    <AttributeRule attributeID="sn"><PermitValueRule xsi:type="ANY" /></AttributeRule>
    <AttributeRule attributeID="isMemberOf"><PermitValueRule xsi:type="ANY" /></AttributeRule>
  </AttributeFilterPolicy>
</AttributeFilterPolicyGroup>

NOTE

On v5, SAML encoding lives in the attribute registry (conf/attributes/) โ€” mail, givenName, sn, eduPersonScopedAffiliation, and eduPersonEntitlement ship pre-registered. isMemberOf (eduMember schema) may need its own registry rule if your deployment doesn't already release it.

Friendly name or OID โ€” either works # โ€‹

attributeID in the filter must match whatever ID your resolver/registry actually assigns the attribute internally, and that isn't always the friendly name โ€” depending on your deployment, an attribute can resolve only under its OID. If a rule with PermitValueRule ANY still releases nothing, switch attributeID to the OID form and retest:

AttributeFriendly nameOID
Emailmailurn:oid:0.9.2342.19200300.100.1.3
First namegivenNameurn:oid:2.5.4.42
Last namesnurn:oid:2.5.4.4
GroupsisMemberOfurn:oid:1.3.6.1.4.1.5923.1.5.1.1

Shelf accepts either form automatically for every attribute above โ€” there's nothing to tell us and nothing to reconfigure on our side, whichever one your IdP releases.

4. Assertion encryption โ€” automatic # โ€‹

Shelf publishes an encryption certificate in its metadata and accepts encrypted assertions, so your IdP encrypts automatically (Shibboleth's default when the SP advertises an encryption key). Nothing to configure โ€” assertions are encrypted end-to-end.

5. Send us your metadata # โ€‹

Send your Shelf contact:

  • Your IdP metadata โ€” the metadata URL (e.g. https://idp.your.edu/idp/shibboleth, or your federation metadata) or an exported XML file.
  • The domain your users sign in with.
  • Which group strategy you chose (ยง6).

We register the provider and confirm once it's live โ€” usually about 1 business day. Don't test sign-in until you hear back.

6. Choose a group strategy # โ€‹

Shelf assigns roles from the group values you release. Pick whichever your institution already populates โ€” all three work identically on the Shelf side; you only need one.

StrategySAML Name (OID)Example value
isMemberOf (recommended)urn:oid:1.3.6.1.4.1.5923.1.5.1.1cn=shelf-admins,ou=groups,dc=your,dc=edu or a Grouper path your:apps:shelf:admins
eduPersonEntitlementurn:oid:1.3.6.1.4.1.5923.1.1.1.7urn:mace:your.edu:shelf:admin
eduPersonScopedAffiliationurn:oid:1.3.6.1.4.1.5923.1.1.1.9staff@your.edu, faculty@your.edu
  • isMemberOf โ€” best when you can create dedicated Shelf groups in Grouper/LDAP. The most flexible.
  • eduPersonEntitlement โ€” application-specific entitlement URIs.
  • eduPersonScopedAffiliation โ€” coarse mapping by affiliation (e.g. all staff โ†’ one role). No new groups needed.

Whichever you pick, release it via the attribute-filter.xml policy in ยง3 (swap isMemberOf for your attribute id), and tell your Shelf contact so we point the mapping at the right OID.

7. Map your groups to Shelf roles # โ€‹

Once your provider is registered, your workspace owner maps each group value to a Shelf role in workspace settings โ†’ SSO.

Shelf workspace SSO settings โ€” mapping Shibboleth groups to Administrator, Self service, and Base roles

Enter the value your IdP releases next to each role you use:

Shelf rolePaste the group value that should grant it
Administratore.g. cn=shelf-admins,ou=groups,dc=your,dc=edu
Self servicee.g. cn=shelf-staff,ou=groups,dc=your,dc=edu
Basee.g. cn=shelf-users,ou=groups,dc=your,dc=edu

Rules to know:

  • Paste the value exactly as your IdP releases it. If unsure, ask your identity team for a sample assertion (or check the IdP audit log) for the precise string.
  • Multiple groups โ†’ one role: each field accepts several values, comma-separated (e.g. Grouper paths your:apps:shelf:it-staff, your:apps:shelf:av-services) โ€” anyone in any of them gets that role. Note: a value that itself contains commas (a full LDAP DN like cn=โ€ฆ,ou=โ€ฆ,dc=โ€ฆ) can only be used on its own, not comma-listed โ€” to grant one role from several DN-shaped groups, release a comma-free identifier (a Grouper path or an eduPersonEntitlement) for them instead.
  • Matching is trimmed and case-insensitive โ€” but a leading/trailing scope difference still counts as a mismatch, so copy the real value.
  • Precedence is Administrator > Self service > Base. A user whose groups match more than one role gets the highest. A user still only ever holds one role per workspace.
  • Users can be members of many groups โ€” Shelf matches any mapped one regardless of its position in the list. You only need to map the roles you actually use, but at least one must be mapped.

8. Test single sign-on # โ€‹

Go to /sso-login, enter your domain, and sign in as a test user:

  • A user whose groups match a mapped role lands in the workspace with that role.
  • A user with no matching group lands on the pending-assignment screen (expected) rather than being denied โ€” it resolves as soon as an admin maps their group.

Troubleshooting # โ€‹

No email, or missing name/groups after a successful redirect back from Shibboleth. Almost always a missing or mis-scoped attribute-filter.xml policy โ€” the resolver may have the value, but nothing is released until a filter policy permits it to Shelf's entity ID. Check ยง3 first.

One attribute (e.g. last name) still doesn't release, even with a permissive attribute-filter.xml rule for it. The rule's attributeID doesn't match the ID your resolver assigns that attribute internally โ€” some deployments resolve a given attribute only under its OID, not its friendly name (or vice versa). Switch attributeID to the other form (table in ยง3) and retest; Shelf accepts either.

Login fails immediately after the Shibboleth screen, with no clear error. Your IdP is issuing a transient NameID (the default). It must be persistent (or emailAddress) for the Shelf relying party โ€” see ยง2.

A user always lands on the pending-assignment screen even though you mapped their group. The string the IdP released doesn't match what's pasted in Shelf. Matching is case-insensitive and trimmed, but not fuzzy. Get a sample assertion for that user and paste the exact value.

Released under the AGPL-3.0 License.