Page tree

The Shibboleth 2.x software has reached its End of Life and is no longer supported. This documentation is available for historical purposes only. See the IDP30 and SP3 wiki spaces for current documentation on the supported versions.

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 2 Next »

The V2.5 release of the SP includes a pair of mechanisms that support integration with authentication mechanisms that are outside the SP itself. You can think of this as the reverse of the approach described here under "Provisioning the Application's Database or Session".

Instead of transitioning from the SP session to something else, the SP can now support transitioning from "something else" into an SP session. The external mechanism can be anything, including local authentication by password, or other SSO protocols. Technically it doesn't even have to live on the same server as the SP, because this mechanism is in principle a form of SSO in its own right.

Obviously, there are security implications to using this feature, and you should understand them well before enabling them.

SAML Artifact Spoofing

One of the supported mechanisms takes advantage of the less-commonly used SAML binding called the "Artifact Binding". Instead of pushing a SAML response through the client, an encoded reference called an "artifact" is generated by the IdP, passed to the SP via a redirect, and then the SP turns the artifact into the SAML response using a SOAP request.

This support has been extended to support "file-based" resolution of artifacts. In this approach, the local file system is used as a "secure transport" for turning the artifact into a SAML response. It is assumed that the file system between the external mechanism and the shibd daemon is secure, and the artifact is expected to be generated in a secure manner so that valid artifacts cannot be predicted by an attacker. Its security properties are essentially similar to standard artifact usage in SAML.

Some things to keep in mind:

  • The external mechanism is in some sense like a SAML IdP in that it is generating SAML responses and assertions, generating artifacts, and passing them through the client using the SAML HTTP-Artifact binding.
  • The mechanism relies on hard-to-predict artifact values, so a good PRNG is required.
  • The SAML response and assertion do not need to be digitally signed, because the file system is assumed to be a secure exchange medium. This greatly simplifies the work of the external mechanism in mocking up a SAML response to use.
  • Except for the signature, the rest of the SAML message and assertion(s) are processed identically to any other response generated by an IdP, and will be passed through all of the usual security checks. This means a lot of extra "boilerplate" SAML needs to be generated, including unique message and assertion IDs and good timestamps. It's simple to do, but a little tedious.

Technical Specs

So, what do you actually have to do?

Generate the SAML

First, the external mechanism needs to generate a <samlp:ArtifactResponse> message that will be used to generate the user's session. This is a weird animal because it's very layered. It's a SAML assertion inside a SAML response inside a SAML artifact reponse. Two layers of protocol. An example follows.

 SAML Artifact Response
<saml2p:ArtifactResponse xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
    xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
    ID="_0aedefc7f62695c068174a4b5362e0a1" IssueInstant="2012-04-17T17:07:01.260Z" Version="2.0">
    <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity"
        >https://idp.example.org/idp/shibboleth</saml2:Issuer>
    <saml2p:Status>
        <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
    </saml2p:Status>
    <saml2p:Response ID="_bdcdf2fdfc9564976ebf2d5fc68ca2ff" IssueInstant="2012-04-17T17:07:01.120Z"
        Version="2.0">
        <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity"
            >https://idp.example.org/idp/shibboleth</saml2:Issuer>
        <saml2p:Status>
            <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
        </saml2p:Status>
        <saml2:Assertion ID="_80a8853dedd373976a1a39f5fd7231fd" IssueInstant="2012-04-17T17:07:01.120Z"
            Version="2.0">
            <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity"
                >https://idp.example.org/idp/shibboleth</saml2:Issuer>
            <saml2:Subject>
                <saml2:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
                    NameQualifier="https://idp.example.org/idp/shibboleth"
                    SPNameQualifier="https://sp.example.org/shibboleth"
                   >O2S5XNIZEEF7LG7OKYUDGEIO7NBNWMPMST2A4T6NJZPPSH</saml2:NameID>
                <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
                    <saml2:SubjectConfirmationData Address="164.107.160.193"
                        InResponseTo="_9daf8aa18f2b25c822b22c26e8d9a431"
                        NotOnOrAfter="2012-04-17T17:12:01.120Z"
                        Recipient="https://sp.example.org/Shibboleth.sso/SAML2/Artifact"/>
                </saml2:SubjectConfirmation>
            </saml2:Subject>
            <saml2:Conditions NotBefore="2012-04-17T17:07:01.120Z"
                NotOnOrAfter="2012-04-17T17:12:01.120Z">
                <saml2:AudienceRestriction>
                    <saml2:Audience>https://sp.example.org/shibboleth</saml2:Audience>
                </saml2:AudienceRestriction>
            </saml2:Conditions>
            <saml2:AuthnStatement AuthnInstant="2012-04-17T15:19:11.781Z"
                SessionIndex="6c7fb0b96a3450a759e39eda61fc527abd662e1291d55edc8b6b2dcf241092bd">
                <saml2:SubjectLocality Address="164.107.160.193"/>
                <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="eduPersonPrincipalName"
                    Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.6"
                    NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
                    <saml2:AttributeValue>doe@example.org</saml2:AttributeValue>
                </saml2:Attribute>
                <saml2:Attribute FriendlyName="displayName" Name="urn:oid:2.16.840.1.113730.3.1.241"
                    NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
                    <saml2:AttributeValue>John Doe</saml2:AttributeValue>
                </saml2:Attribute>
            </saml2:AttributeStatement>
        </saml2:Assertion>
    </saml2p:Response>
</saml2p:ArtifactResponse>

The message ID and IssueInstant in the very outer message are not evaluated by the SP, but everything else is, just as if it were a real IdP. That means the values must be unique and fresh, and it means that you have to load metadata corresponding to the "issuer" value you use, just as if it were a real SAML 2.0 IdP.

This is required anyway, because of steps two and three, generating an artifact and storing the XML above in a file.

Generate the Artifact

The SAML artifact format is a binary structure that you have to construct carefully, and then base64-encode to produce the value the SP receives. The structure is as follows:

Bytes

Field

2

Artifact Type, this MUST be 0x04

2

Endpoint Index

20

SHA-1 Digest of IdP's entityID

20

Randomly generated message handle

The first field is hardcoded.

The second field is a 16-bit unsigned integer that is a reference to the index attribute in the <md:ArtifactResolutionService> element in the IdP's metadata. In the case of this back-door trick, you can define multiple file system locations that will be used to pass these messages in, and use the index field to identify which one is used.

The third field is how the SP figures out the IdP sending it the artifact. This is just a hash of the entityID.

The fourth field is the unique part. This MUST be strongly random. Taking the SHA-1 hash of suitably random input is one way of generating the 20 bytes needed.

Once it's all together, you base64-encode the 44 bytes of data and that's the artifact.

Storing the SAML

Once you have the artifact, you take the last 20 bytes (the message handle), and you hex-encode them into a 40-byte string (lower case a-f). That's your filename. The XML you generate is written to a file with that name, stored in whatever location you're using to pass the data to the SP (see last step).

Trigger the Login

To make the SP consume the file, you generate a redirect to the SP's artifact-eating endpoint, usually /Shibboleth.sso/SAML2/Artifact, with a query string parameter of SAMLart set to the base64-encoded artifact. You can also pass a RelayState parameter with a URL to land on, or a value obtained from an initial interaction with the SP. This is standard SAML 2.0.

Finding the File

The SP finds the file that you created earlier by looking up the directory to use in the IdP's SAML metadata. The endpoint index in the artifact must correspond to an <md:ArtifactResolutionService> endpoint that contains a Binding attribute set to urn:mace:shibboleth:2.0:bindings:File and a Location containing a relative or absolute filesystem directory path. It can start with "file://", or not. If the path is relative, the SP's default "runtime file" location will be prepended (e.g., /var/run/shibboleth).

Example Endpoint in Metadata
<ArtifactResolutionService index="1" Binding="urn:mace:shibboleth:2.0:bindings:File"
    Location="file:///opt/shibboleth-sp/var/artifacts" />
  • No labels