3
votes

I want to implement a simple scenario:

  1. User trying to get access a protected resource of information system
  2. Information system sends a request to the identity provider to authenticate the user
  3. Identity provider verifies that the user has an open session and if there is no active session, then perform user authentication (identity provider redirects the user to a web page where he can enter a username / password)
  4. If the user is successfully authenticated, the identity provider sends to the information system the set of statements containing the user identification information
  5. Based on the information received from the identity provider, the information system authenticates the user to the access to a protected resource

As information system (service provider) I use OIOSAML. Remote idP based on Shibboleth (On the customer side, about it I do not know anything. Only that it was written on the basis of Shibboleth)

From docs:

The OIOSAML.java Service Provider package implements a Servlet-compliant SAML Service Provider for use in a SAML federation. The package implements all necessary functionality to work as a OIOSAML compliant Service Provider.

The main component of the package is a servlet filter which handles user authentication. The filter checks if the user is already authenticated, and if not, the user is redirected to the SAML Identity Provider. When the user returns with a SAML assertion, the assertion is validated, and a new session is created for the user. The application can access the received assertion and its attributes through a programming API.

IdP and Service Provider configuration is handled through standard SAML metadata.

My web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" >

    <display-name>OIOSAML-J</display-name>

    <listener>
        <listener-class>dk.itst.oiosaml.sp.service.session.SessionDestroyListener</listener-class>
    </listener>

    <servlet>
        <servlet-name>SAMLDispatcherServlet</servlet-name>
        <servlet-class>dk.itst.oiosaml.sp.service.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>SAMLDispatcherServlet</servlet-name>
        <url-pattern>/saml/*</url-pattern>
    </servlet-mapping>

    <filter>
        <filter-name>LoginFilter</filter-name>
        <filter-class>dk.itst.oiosaml.sp.service.SPFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>LoginFilter</filter-name>
        <url-pattern>/protected/*</url-pattern>
    </filter-mapping>

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>

</web-app>

My oiosaml-sp.properties:

# Properties used by oiosaml-j

# Reference to the location of the certificate used for signing SAML documents with - relative to ${oiosaml.home}
oiosaml-sp.certificate.location=./certificate/keystore

# Opaque/encrypted password to the certificate used for signing SAML documents
oiosaml-sp.certificate.password=some_password

# Required authentication level. 2=password, 3=certificate
oiosaml-sp.assurancelevel=2

# Name of the meta data file for the current service provider - overrides setting in brs-common.properties
common.saml2.metadata.sp.filename=SPMetadata.xml

# URI References to the current service provider
oiosaml-sp.uri.home=

# Whether to validate server certificates. Set to false in production.
# Used for artifact resolution.
oiosaml-sp.resolve.ignorecert=true

# Artifact resolution username and password. Only used the artifact profile is active.
oiosaml-sp.resolve.username=rolf.trifork.com
oiosaml-sp.resolve.password=rolf.trifork.com

Generated AuthnRequest:

<?xml version="1.0" encoding="UTF-8"?>
<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"
                     AssertionConsumerServiceURL="http://.../saml/SAMLAssertionConsumer"
                     Destination="https://someidentityprovider/idp/profile/SAML2/Redirect/SSO" ForceAuthn="false"
                     ID="_183...4" IsPassive="false"
                     IssueInstant="2014-07-10T05:48:02.564Z"
                     ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0">
    <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">some_information</saml2:Issuer>
</saml2p:AuthnRequest>

The resulting URLEncode string:

https://someidentityprovider/idp/profile/SAML2/Redirect/SSO?SAMLRequest=fVL...x3%2B8w%2Fws%3D
&RelayState=_27a...b8d25d4df
&SigAlg=http%3A%2F%2Fwww.w3.org%2F2000%2F09%2Fxmldsig%23dsa-sha1
&Signature=MCwCFFIXyH...%3D

The system works and when I perform request via protected mapping I get the login page of the identity provider, where I can enter a couple login / password to continue. However, identification provider sends this response:

<?xml version="1.0" encoding="UTF-8"?>
<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="..."
                 ID="_3d00f0e5401c168ab42eeafc78726e5e" InResponseTo="_b67...3c10"
                 IssueInstant="2014-07-10T15:33:56.788Z" Version="2.0">
    <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
                  Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">
        https://.../shibboleth
    </saml2:Issuer>
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:SignedInfo>
            <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
            <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
            <ds:Reference URI="#_3d00f0...726e5e">
                <ds:Transforms>
                    <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
                    <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                </ds:Transforms>
                <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
                <ds:DigestValue>yq/0...I=</ds:DigestValue>
            </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>
            IR76Xd51+Vwi...w==
        </ds:SignatureValue>
        <ds:KeyInfo>
            <ds:X509Data>
                <ds:X509Certificate>MIID...zQG</ds:X509Certificate>
            </ds:X509Data>
        </ds:KeyInfo>
    </ds:Signature>

    <saml2p:Status>
        <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Responder"/>
        <saml2p:StatusMessage>Unable to encrypt assertion</saml2p:StatusMessage>
    </saml2p:Status>

</saml2p:Response>

So,

<saml2p:Status>
   <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Responder"/>
   <saml2p:StatusMessage>Unable to encrypt assertion</saml2p:StatusMessage>
</saml2p:Status>

What does this mean and how to overcome it?

1
What does your Assertion encrypt method look like?Patrick M
I'm fairly certain you must encrypt the actual assertion from the code. Take a look at svn.softwareborsen.dk/oiosaml.java/sp/trunk/docs/features.html under Signatures and encryption, You should have EncryptedAssertion element, which can be created wiki.shibboleth.net/confluence/display/OpenSAML/…Patrick M

1 Answers

0
votes

The Identity Provider needs to have a public certificate of your OIOSAML application in order to be able to encrypt the Assertion before sending response back to OIOSAML. The error message might indicate that it's missing.

Can you please verify that the SAML metadata with information about your OIOSAML application which you have imported to the Shibboleth contains element <md:KeyDescriptor use="encryption"> with the certificate information?

As a workaround you can deploy your OIOSAML application on an HTTPS port (with a resulting URL in metadata e.g. https://localdomain.com:8443/...) and re-import the metadata to the Shibboleth. By default Shibboleth will not try to encrypt the Assertion in case it will be provided back to Service Provider application over an encrypted channel.