lightSAML / lightSAML-IDP

PHP implementation of the IDP part of SAML Single SignOn protocol
https://www.lightsaml.com/LightSAML-IDP/
GNU General Public License v3.0
29 stars 15 forks source link

Response signing problems #7

Open frostieDE opened 7 years ago

frostieDE commented 7 years ago

Hi,

I am trying to implement an SAML IdP using your library. But something seems to be broken with my configuration or to be a bug :-(

Here is what I did:

I set up a service provider which is basically just a cloned version of your light-saml core library. My webserver serves the /web/sp folder at https://sp.localhost.tld. It is configured using this XML file:

<?xml version="1.0"?>
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" entityID="https://sso.localhost.tld/">
  <IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol" WantAuthnRequestsSigned="true">
    <KeyDescriptor use="encryption">
      <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:X509Data>
          <ds:X509Certificate>
IDP CERTIFICATE GOES HERE
          </ds:X509Certificate>
        </ds:X509Data>
      </ds:KeyInfo>
    </KeyDescriptor>
    <KeyDescriptor use="signing">
      <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:X509Data>
          <ds:X509Certificate>
IDP CERTIFICATE GOES HERE
          </ds:X509Certificate>
        </ds:X509Data>
      </ds:KeyInfo>
    </KeyDescriptor>
    <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://sso.localhost.tld/dev.php/idp/saml"/>
    <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://sso.localhost.tld/dev.php/idp/saml"/>
  </IDPSSODescriptor>
</EntityDescriptor>

As you can see, the Identity Provider is seved at https://sso.localhost.tld. This is where my IdP app comes into play. It can be found here. In this IdP, my SP is configured as follows:

EntityID: https://sp.localhost.tld/ Certificate: SP CERTIFICATE (which is a self-signed certificate found in saml.crt) Callback-Url: https://sp.localhost.tld/login.php

This SP is configured using the UI and built by my own ServiceProviderEntityStore.php.

Now, when I start a login from https://sp.localhost.tld/login.php I get redirected to my IdP and I get this exception:

saml-exception

When I debug the code, it seems that OwnSignatureResolver::getSigningCredential() returns a credential without a private key. When debugging any further, the credentialResolver has three potential credentials (all have the same certificate, but only the last has a private key):

I am not really sure, where the first two credentials come from.

Do have any clue?

Regards, Marcel

frostieDE commented 7 years ago

It seems I found a workaround 😄 In the CredentialFactory::build() method you must add the OwnCredentialStore first, and then add the rest:

public function build(
        EntityDescriptorStoreInterface $idpEntityDescriptorStore,
        EntityDescriptorStoreInterface $spEntityDescriptorStore,
        array $ownCredentials,
        array $extraCredentials = null
    ) {
        if (empty($ownCredentials)) {
            throw new LightSamlBuildException('There are no own credentials');
        }

        $store = new CompositeCredentialStore();
        $ownCredentialsStore = new StaticCredentialStore();
        foreach ($ownCredentials as $credential) {
            $ownCredentialsStore->add($credential);
        }
        $store->add($ownCredentialsStore);

        $store->add(new MetadataCredentialStore($idpEntityDescriptorStore));
        $store->add(new MetadataCredentialStore($spEntityDescriptorStore));

        $extraCredentialsStore = new StaticCredentialStore();
        $store->add($extraCredentialsStore);
        if ($extraCredentials) {
            foreach ($extraCredentials as $credential) {
                $extraCredentialsStore->add($credential);
            }
        }

        return $store;
    }