Page tree
Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 18 Next »

Current File(s): conf/saml-nameid.xml, conf/saml-nameid.properties

Format: Native Spring / Deprecated Custom Schema

Legacy V2 File(s): conf/attribute-resolver.xml

Overview

Generation of SAML NameIdentifier/NameID content is handled by the NameIdentifierGeneration service. See the NameIdentifiers topic for a general discussion of name identifiers and a list of specific examples.

The saml-nameid.xml file is used to control the generation of SAML 1 NameIdentifier and SAML 2 NameID content. SAML assertion subjects contain a special slot for an identifier that is less commonly used in Shibboleth deployments (because SAML Attributes are more general and useful) but is very commonly used by vendors seeking to do the bare minimum necessary to support SAML.

When interoperating with Shibboleth SPs, it's rare to need to modify this file, but you might need to do so to add support for more application-oriented identifier types, such as email addresses, or less commonly to enable support for so-called "persistent" identifiers, special privacy-preserving identifiers that are targeted to specific services.

Generators

The configuration defines two list beans, each containing a list of "generator" plugins for the two different SAML versions. Each plugin is specific to an identifier Format, a SAML constant that identifies the kind of value being expressed. The generation process involves selecting a list of Formats to try and generate (see Format Selection below), and then trying each Format until an appropriate value is obtained by running each configured generator in order. Since assertions need not contain a name identifier, it is not an error (from the perspective of the IdP) for all the generators to fail.

The default configuration includes generators for "transient" identifiers. These plugins are configured using saml-nameid.properties to control the strategies used to generate and reverse-map the values (the latter only being necessary to support "back-channel" attribute queries).

In the case of SAML 2, a plugin is present, but commented out, to generate "persistent" identifiers. Certain properties in saml-nameid.properties must be set in order to safely uncomment this plugin (discussed below).

The default configuration also demonstrates how to generate a custom identifier using an arbitrary Format based on an attribute from the attribute resolution process. This mirrors the V2 approach of encoding attributes, but separates the two operations in the configuration. This plugin also has the capability, unlike the resolver-based approach, of selecting the first value present from a list of possible source attributes.

In summary:

  • Support for "transient" identifiers is automatic.
  • If you want "persistent" / pair-wise support, see below.
  • If you want custom values, see below.

Format Selection

For any given request, the list of Formats to try to generate is based on combining the SP's request (SAML 2 requests can include a <NameIDPolicy> element that requires a particular Format), the <NameIDFormat> element(s) in the SP's metadata, and the nameIDFormatPrecedence profile configuration property, if set for the chosen relying party configuration.

If a <NameIDPolicy> element with Format is supplied, a suitable identifier MUST be generated or an error will be returned.

Otherwise the formats specified in an SP's metadata are filtered against a nameIDFormatPrecedence profile configuration property, if set, and the resulting set of Formats is tried in order.

Default Formats for each SAML version are set via saml-nameid.properties and are used in the event that nothing else is called for. You should not alter that setting in most cases.

Transient Identifier Generation

The strategy used to generate transient identifiers is controlled with the idp.transientId.generator property in saml-nameid.properties.

The default strategy is based on the use of a secret key, discussed in the SecurityConfiguration topic (see the idp.sealer.* properties). This maintains support for attribute queries without requiring shared state between a cluster of nodes, apart from sharing the secret key.

You can set this property to "shibboleth.StoredTransientIdGenerator" to generate random values tracked by server-side storage (this makes them shorter, but requires more complex storage approaches when clustering if attribute queries need to be supported).

Persistent Identifier Generation

The strategy used to generate persistent identifiers is controlled with the idp.persistentId.generator property in saml-nameid.properties.

The default strategy is a hash-based approach called "Computed" that avoids the need for a database to store the IDs, but is incapable of reverse-mapping a given identifier, or revoking or changing the identifier associated with a subject. Tracking back to a subject for debugging purposes generally involves the use of audit logs rather than direct access to a mapping of users. It's not the best approach in the abstract, but it is much simpler to deploy.

To enable the Computed strategy, you must set two properties:

  • idp.persistentId.sourceAttribute
    • A list of attributes from which to derive a key for the subject. The key is used as the hash input, and should be a very stable value for each subject and must never be reassigned later to a different subject. Usually this should be a permanent serial number associated by an IDMS to each account, and not a name-based identifier like a login ID or email address. It must be released (in terms of attribute filter policy) to the relying party, but need not have any attribute encoders attached (which means it won't actually be visible to the relying party in the SAML response). A future update will relax this restriction.
  • idp.persistentId.salt
    • A secret string used as a salt when hashing the subject key derived from the property above. This is required to prevent trivial attacks to determine the identifier for a given subject, and must be kept secret.

The alternative strategy is to generate simple random identifiers on first use and store them in a database for future use. This has significant benefits and addresses most of the limitations of the computed strategy, but requires a highly available database accessible to every IdP node. Using this strategy requires the above settings and requires changing the idp.persistentId.generator property to "shibboleth.StoredPersistentIdGenerator" and setting the idp.persistentId.store property to the name of a bean you must define. You can place it in saml-nameid.xml if you like. The main content of that bean is a reference to a JDBC DataSource object.

A mocked up example of a persistent store using MySQL and the DBCP2 pooling library follows:

Example persistent ID store in saml-nameid.xml
<bean id="MyPersistentStore" class="net.shibboleth.idp.saml.nameid.impl.JDBCPersistentIdStore">
	<property name="dataSource">
		<bean class="org.apache.commons.dbcp2.BasicDataSource"
			p:driverClassName="com.mysql.jdbc.Driver"
			p:url="jdbc:mysql://localhost:3306/shibboleth"
			p:username="shibboleth"
			p:password="foo"
			p:maxIdle="5"
			p:maxWaitMillis="15000"
			p:testOnBorrow="true"
			p:validationQuery="select 1"
			p:validationQueryTimeout="5" />
	</property>
</bean>

It's possible to override the default table and column names used in the data store with properties on the JDBCPersistentIdStore class. The default DDL is designed to be compatible with the V2 data connector.

Lastly, a default feature of the stored strategy is that it uses the computed strategy to produce the initial identifier for each subject, to help with migration. If you don't need that to happen, you can set the idp.persistentId.computed property to an empty value.

Custom Identifier Generation

An identifier that is neither "transient" nor "persistent" is of a more general category referred to as a "custom" identifier. Plugins are included for generating a custom identifier based on an attribute produced by the attribute resolution process. In most cases, this should be sufficient. In unusual scenarios, you may also build your own generator plugin, but this should rarely be necessary.

By default, support for custom identifiers is included in saml-nameid.xml but only partially configured and commented out (because the specifics are a local matter). In the process outlined below, you will create/uncomment one or more copies of the custom generator bean(s) appropriately, and ensure the underlying source attribute(s) are released to the applicable relying parties.

There are no properties relevant to the use of custom identifiers in saml-nameid.properties, so do not be distracted by that content; those settings apply only to the use of "transient" and "persistent" identifiers.

To support a custom identifier Format, take the following steps:

  1. Determine the Format constant you need to support (note that most of the constants used in SAML contain a "1.1" in the URN and apply to both SAML versions).
  2. Choose one or more attributes to use to supply the identifier's value (e.g. "mail").
  3. Configure your attribute filter policy to release the attribute(s) chosen to the relevant SP(s).
  4. Uncomment or create a generator bean in saml-nameid.xml for SAML 1 and/or SAML 2 as required.

    SAML 2.0 E-Mail Format Example
    <util:list id="shibboleth.SAML2NameIDGenerators">
    	<ref bean="shibboleth.SAML2TransientGenerator" />
    
    	<!-- SAML 2 EXAMPLE -->
        <bean parent="shibboleth.SAML2AttributeSourcedGenerator"
            p:format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
            p:attributeSourceIds="#{ {'mail', 'othermail'} }" />
    </util:list>

    The format property is self-explanatory and must contain a single value per bean. The attributeSourceIds property is a list of attribute IDs to source the value from (the first value found will be used), and you can embed a comma-delimited list of quoted IDs inside the double braces (see SpringConfiguration).

  5. Lastly, trigger the appropriate Format to be selected by manipulating the selection process described above. If you control the SP's metadata (which is very common when this use case arises), the best way to do this is by inserting a <NameIDFormat> element into the metadata. If this isn't possible, a nameIDFormatPrecedence profile configuration property can be used in a relying party override definition.

Ideally, you should try and avoid scenarios in which you must generate a different identifier of the same Format for two different SPs. In other words, a given Format should contain the same data regardless of the SP asking. This makes it possible to maintain a simple configuration of any number of generators as above. If you must deviate from that rule, you can accomodate by attaching an activationCondition property to a generator bean that triggers based on a particular relying party. In that fashion, you can include multiple generators for a given Format, but limit their use to specific SPs.

Example of a Generator for a specific SP
    <bean parent="shibboleth.SAML2AttributeSourcedGenerator"
        p:format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
        p:attributeSourceIds="#{ {'mail', 'othermail'} }">

		<property name="activationCondition">
			<bean parent="shibboleth.Conditions.RelyingPartyId" c:candidate="https://sp.example.com/shibboleth" />
        </property>
    </bean>

 

 

The "unspecified" Format

Bear in mind that many vendors make the poor decision to use a Format called urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified, which makes it very difficult to interoperably deal with them. In addition to being, well, unspecified, each vendor may ascribe a totally different set of requirements to that format, making it hard to properly generate without a lot of special rules and configuration.

Shibboleth does not honor this Format when it is encountered in a <NameIDPolicy> element in a request or in an SP's metadata and it is ignored. As a result, if you must support this Format, you must trigger its use with a nameIDFormatPrecedence profile configuration property:

Example Relying Party override specifying a NameID Format
<bean parent="RelyingPartyByName" c:relyingPartyIds="https://scroogle.com">
    <property name="profileConfigurations">
        <list>
            <bean parent="SAML2.SSO" p:encryptAssertions="false"
                p:nameIDFormatPrecedence="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" />
        </list>
    </property>
</bean>

We strongly urge deployers to avoid the use of that Format when possible. Note that in many cases when vendors claim to "require" its use, what they really mean (aside from "we're not interesting in supporting SAML properly") is that they don't care what Format you use. You should always start by trying to use a standard Format of some sort that fits the data you need to send.

If no standard Format exists for the data, use the URI name of the underlying SAML Attribute as the Format. For example, passing an employee ID should be done using a Format of urn:oid:2.16.840.1.113730.3.1.3

Reference

Beans

Beans defined in saml-nameid.xml and related system configuration follow:

Bean IDTypeFunction

shibboleth.SAML2NameIDGenerators

List<SAML2NameIDGenerator>

SAML 2 NameID generator plugins to use

shibboleth.SAML1NameIdentifierGenerators

List<SAML1NameIdentifierGenerator>

SAML 1 NameIdentifier generator plugins to use
shibboleth.SAML2TransientGenerator
shibboleth.SAML1TransientGenerator
SAML2NameIDGenerator
SAML1NameIdentifierGenerator
Plugins for generating transient identifiers using pluggable strategies
shibboleth.StoredTransientIdGeneratorTransientIdGenerationStrategyStrategy plugin that generates transient identifiers randomly and stores them in a server-side StorageService
shibboleth.CryptoTransientIdGeneratorTransientIdGenerationStrategyStrategy plugin that generates transient identifiers by encrypting a subject identity into a long opaque string
shibboleth.SAML2PersistentGeneratorSAML2NameIDGeneratorPlugin for generating persistent identifiers using pluggable strategy
shibboleth.ComputedPersistentIdGeneratorPersistentIdGenerationStrategyStrategy plugin that generates persistent identifiers with a salted hash of an input value
shibboleth.StoredPersistentIdGeneratorPersistentIdGenerationStrategyStrategy plugin that generates persistent identifiers and stores them in a database
shibboleth.SAML2AttributeSourcedGenerator
shibboleth.SAML1AttributeSourcedGenerator
SAML2NameIDGenerator
SAML1NameIdentifierGenerator
Template beans for plugins that generate custom identifiers based on resolved and released attribute values
shibboleth.LegacySAML1NameIdentifierGenerator
shibboleth.LegacySAML2NameIDGenerator
SAML2NameIDGenerator
SAML1NameIdentifierGenerator
Plugins supporting deprecated use of attribute resolver configuration to produce and encode name identifiers

Properties

Properties defined in saml-nameid.properties to customize various aspects of default identifier generation behavior:

PropertyTypeDefaultFunction
idp.transientId.generatorBean ID of a TransientIdGenerationStrategyshibboleth.CryptoTransientIdGeneratorIdentifies the strategy plugin for generating transient IDs
idp.persistentId.generatorBean ID of a PersistentIdGenerationStrategyshibboleth.ComputedPersistentIdGeneratorIdentifies the strategy plugin for generating persistent IDs
idp.persistentId.dataSourceBean ID of a JDBC DataSource Identifies a data source for storage-based strategy for persistent IDs
idp.persistentId.storeBean ID of a PersistentIdStore Identifies the data store plugin for storage-based strategy for persistent IDs
idp.persistentId.computedBean ID of a ComputedPersistentIdGenerationStrategyshibboleth.ComputedPersistentIdGeneratorMay be null, Identifies a strategy plugin to use to generate the first persistent identifier for each subject, used to migrate from the computed to stored strategies
idp.persistentId.sourceAttribute                 Comma-delim'd List List of attributes to search for a value to uniquely identify the subject of a persistent identifier, it MUST be stable, long-lived, and non-reassignable
idp.persistentId.useUnfilteredAttributes3.2BooleantrueWhether or not the previous property has access to unreleased attributes
idp.persistentId.saltString A secret salt for the hash when using computed persistent IDs
idp.persistentId.algorithmStringSHAThe hash algorithm used when using computed persistent IDs
idp.nameid.saml2.legacyGeneratorBean ID Identifies a default generator plugin to use as a last resort if no others succeed
idp.nameid.saml1.legacyGeneratorBean ID Identifies a default generator plugin to use as a last resort if no others succeed
idp.nameid.saml2.defaultURIurn:oasis:names:tc:SAML:2.0:nameid-format:transientThe default Format to generate if nothing else is indicated
idp.nameid.saml1.defaultURIurn:mace:shibboleth:1.0:nameIdentifierThe default Format to generate if nothing else is indicated

V2 Compatibility

The V3 IdP uses a new dedicated service for configuring NameID generation. The legacy V2 approach of encoding attributes into identifiers using attribute-resolver.xml and special attribute encoders that generate NameIdentifiers or NameIDs instead of Attributes is supported for compatibility purposes, but is deprecated and may be removed from a future version.

To enable the legacy support, the idp.nameid.saml2.legacyGenerator and idp.nameid.saml1.legacyGenerator properties must be uncommented and set to the values commented out in the saml-nameid.properties file. This is done for you when performing an upgrade from V2.

The IdP should load any existing V2 attribute-resolver.xml file and configure itself in an expected manner, but that configuration will be superseded by the content of the new saml-nameid.xml file and will fall back to the resolver only as a backstop. You can short-circuit the new functionality by commenting out the content of the two generator list beans and leaving them empty.

Note that unlike in V2, the transient or persistent identifiers produced by the new V3 generation service are not treated as attributes and are not release-controlled via an attribute filter policy. Rather, transients are viewed as harmless (because they are merely one-time values) and persistent identifiers cannot be generated without configuring an appropriate source attribute or other properties.

Finally, note that the two supplied strategies for generating persistent IDs are compatible with the connector plugins in V2 used for this purpose.

Notes

TBD

  • No labels