Bug 1372640 - [GSS](6.4.z) Picketlink only recognize the IDP certificate for the server that is defined under IdentityURL.
Summary: [GSS](6.4.z) Picketlink only recognize the IDP certificate for the server tha...
Keywords:
Status: CLOSED EOL
Alias: None
Product: JBoss Enterprise Application Platform 6
Classification: JBoss
Component: PicketLink
Version: 6.4.9
Hardware: Unspecified
OS: Unspecified
unspecified
medium
Target Milestone: ---
: ---
Assignee: Jiri Ondrusek
QA Contact: Pavel Slavicek
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2016-09-02 09:34 UTC by Tom Fonteyne
Modified: 2019-12-16 06:36 UTC (History)
7 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2019-08-19 12:47:41 UTC
Type: Bug


Attachments (Terms of Use)

Description Tom Fonteyne 2016-09-02 09:34:07 UTC
Consider a setup with two different IDP that are allowed to create valid SAML-ticket to our service provider (PicketLink on JBoss EAP 6.4.4, same in 6.4.9).

The IDP's of course have different certificates for signing these SAML-tickets, so we would like so verify them by using ValidatingAlias in picketlink.xml.

Since ValidationAlias uses the hostname of the IDP to look up the correct certificate in the keystore to validate the SAML-response, it should be easy to configure. 

Just add two ValidationAlias with the hostname for each IDP and let them point to the right alias fort its certificate.

Unfortunately this doesn't work. Picketlink only recognize the IDP that is defined under IdentityURL.

So the problem is that SAML2AuthenticationHandler always uses this value when looking up the certificate, but it should instead use the Issuer-value in the SAML-response to look up the certificate.

A code inspection done shows:

This first snippet is from  org.picketlink.identity.federation.web.handlers.saml2.SAML2SignatureValidationHandler.validateSender() and it gets the public key to verify the signature from the request instance:
...
        PublicKey publicKey = (PublicKey) request.getOptions().get(GeneralConstants.SENDER_PUBLIC_KEY);
        try {
            boolean isValid;

            HTTPContext httpContext = (HTTPContext) request.getContext();

            logger.trace("HTTP method for validating response: " + httpContext.getRequest().getMethod());

            if (isPostBinding(httpContext)) {
                isValid = verifyPostBindingSignature(signedDocument, publicKey);
            } else {
                isValid = verifyRedirectBindingSignature(httpContext, publicKey);
            }
...

That public key is set in the request here:
org.picketlink.identity.federation.web.process.ServiceProviderBaseProcessor.setRequestOptions()
...
        if (keyManager != null) {
            PublicKey validatingKey = getIDPPublicKey();

            requestOptions.put(GeneralConstants.SENDER_PUBLIC_KEY, validatingKey);
            requestOptions.put(GeneralConstants.DECRYPTING_KEY, keyManager.getSigningKey());
        }
...

And the actual problem is how the key is retrieved from the keystore in the method getIDPPublicKey(). That method gets a URL from the "IdentityURL" in the picketlink-configuration which is a static URL. What it should do is to get the URL from the "Issuer"-tag in SAML-response. Picketlink uses that URL to get an alias for the certificate in the keystore provided in the ValidatingAlias-configuration.

picketlink.xml:
...
			<ValidatingAlias Key="${picketlink.idp.address}" Value="adfs-sign" />
			<ValidatingAlias Key="${picketlink.idp-ext.address}" Value="adfs-sign-ext" />
...

org.picketlink.identity.federation.web.process.ServiceProviderBaseProcessor.getIDPPublicKey()
...
        if (isNullOrEmpty(idpValidatingAlias)) {
            idpValidatingAlias = safeURL(getSpConfiguration().getIdentityURL()).getHost();
        }

        return keyManager.getValidatingKey(idpValidatingAlias);

And the certificate check will fail.


Note You need to log in before you can comment on or make changes to this bug.