Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error Creating Response Cannot read property 'replace' of null #460

Open
joshuablanco opened this issue Dec 6, 2021 · 2 comments
Open

Comments

@joshuablanco
Copy link

joshuablanco commented Dec 6, 2021

Greetings, right now I'm developing an IDP but I'm having the error shown in the title, probably is something obvious but I already struggled with it a long way.
First hand I'm sorry if I'm not writing this wit the guidelines of github forums I'm almost new in this plattforms.

In my IDP

I have the next metadata

<?xml version="1.0"?>
<EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" validUntil="2021-12-06T15:38:00Z" cacheDuration="PT1639064280S" entityID="http://localhost:3000" ID="asd-564y-sfdd">
   <IDPSSODescriptor WantAuthnRequestsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
       <KeyDescriptor use="signing">
           <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
               <ds:X509Data>
                   <ds:X509Certificate>MIIFnTCCA4WgAwIBAgIUJdgAcZ2bBd5pr</ds:X509Certificate>
               </ds:X509Data>
           </ds:KeyInfo>
       </KeyDescriptor>
       <KeyDescriptor use="encryption">
           <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
               <ds:X509Data>
                   <ds:X509Certificate>MIIFnTCCA4WgAwIBAgIUJdgAcZ2bBd5pr</ds:X509Certificate>
               </ds:X509Data>
           </ds:KeyInfo>
       </KeyDescriptor>
       <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://localhost:3000/saml/logout"/>
       <NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:persistent</NameIDFormat>
       <SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://localhost:3000/saml/login"/>
   </IDPSSODescriptor>
</EntityDescriptor>

and this configuration

const defaultIdpConfig ={
    metadata: fs.readFileSync(path.join("./", "oktaIDPEnc.xml")),
    privateKey: fs.readFileSync(path.join("./", "encryptKey.pem")),
    privateKeyPass: 'foobar',
    encPrivateKey: fs.readFileSync(path.join("./", "encryptKey.pem")),
    encPrivateKeyPass: 'foobar',
    isAssertionEncrypted: true,
    messageSigningOrder: 'encrypt-then-sign'
}

As you can see I'm using the same certificate for sign and encrypt and the same private key such as (privateKey and encPrivateKey). In the already mentioned IDP, I have the next SP metadata.

<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
    xmlns:assertion="urn:oasis:names:tc:SAML:2.0:assertion"
    xmlns:ds="http://www.w3.org/2000/09/xmldsig#" entityID="http://localhost:8080/metadata?encrypted=true">
    <SPSSODescriptor AuthnRequestsSigned="false" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
        <NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</NameIDFormat>
        <AssertionConsumerService index="0" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://localhost:8080/sp/acs?encrypted=true"/>
    </SPSSODescriptor>
</EntityDescriptor>

With this configuration.

const sp = saml.ServiceProvider({
    metadata: fs.readFileSync(path.join("./", "SPMetadata.xml")), // OBLIGATORIO PARA TRAER VISTA DE LOGIN DESDE SP
});

I generate the key and certificates with the commands proposed in the documentation.

openssl genrsa -passout pass:foobar -out encryptKey.pem 4096
openssl req -new -x509 -key encryptKey.pem -out encryptionCert.cer -days 3650

In my SP

I Use the same IDP metadata that I already showed before and the same SP metadata. with the next configuration for IDP:

 const oktaIdpEnc = samlify.IdentityProvider({
        metadata: fs.readFileSync(__dirname + '/../metadata/testIDP.xml'),
        isAssertionEncrypted: true,
        messageSigningOrder: 'encrypt-then-sign',
        wantLogoutRequestSigned: true,
    });

and the SP configuration as follows:

const spEnc = samlify.ServiceProvider({
    entityID: 'http://localhost:8080/metadata?encrypted=true',
    authnRequestsSigned: false,
    wantAssertionsSigned: true,
    wantMessageSigned: true,
    wantLogoutResponseSigned: true,
    wantLogoutRequestSigned: true,
    privateKey: fs.readFileSync(__dirname + '/../key/sign/privkey.pem'),
    privateKeyPass: 'VHOSp5RUiBcrsjrcAuXFwU1NKCkGA8px',
    encPrivateKey: fs.readFileSync(__dirname + '/../key/encrypt/privkey.pem'),
    assertionConsumerService: [{
        Binding: binding.post,
        Location: 'http://localhost:8080/sp/acs?encrypted=true',
    }]
    });

Leading to the error

In the SP apparently, I don't have issues, the SP sends the SAML Request correctly, but the problem is in the IDP when I'm creating the Response.
I'm using this template provided by the test/flow.ts in your repo, I made some changes.

<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
    xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="{ID}" Version="2.0" IssueInstant="{IssueInstant}" Destination="{Destination}" InResponseTo="{InResponseTo}">
    <saml:Issuer>{Issuer}</saml:Issuer>
    <samlp:Status>
        <samlp:StatusCode Value="{StatusCode}"/>
    </samlp:Status>
    <saml:Assertion ID="{AssertionID}" Version="2.0" IssueInstant="{IssueInstant}"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
        <saml:Issuer>{Issuer}</saml:Issuer>
        <saml:Subject>
            <saml:NameID Format="{NameIDFormat}">{NameID}</saml:NameID>
            <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
                <saml:SubjectConfirmationData NotOnOrAfter="{SubjectConfirmationDataNotOnOrAfter}" Recipient="{SubjectRecipient}" InResponseTo="{InResponseTo}"/>
            </saml:SubjectConfirmation>
        </saml:Subject>
        <saml:Conditions NotBefore="{ConditionsNotBefore}" NotOnOrAfter="{ConditionsNotOnOrAfter}">
            <saml:AudienceRestriction>
                <saml:Audience>{Audience}</saml:Audience>
            </saml:AudienceRestriction>
        </saml:Conditions>{AttributeStatement}</saml:Assertion>
</samlp:Response>

The way I'm creating the response is as follows:

const response =  await idp.createLoginResponse(
            sp,
            requestInfo,
            'post',
            user,
            createTemplateCallback(idp,sp,'post',user,requestInfo.extract,samllib,clientTemp)            
        ).catch(err => {
            console.error("Error Creating Response",err.message);
            return err;
        });

So the error when it tries to create the Response is Cannot read property 'replace' of null.
Where:

  1. sp is the agent based on the sp configuration already shown
  2. requestiInfo is the extract after parseLoginRequest()
  3. 'post' binding
  4. user ={ email: '[email protected]' };
  5. createTemplateCallback(idp,sp,'post',user,requestInfo.extract,samllib,clientTemp), is the function for creating the response where clientTemp is an object to provide the response attributes it works well.

This flow works without the encryption, setting the SP configuration in the SP just as the react-samlify no encryption.

Mr @tngan I really appreciate your help, I checked the documentation and try to solve this based on your excellent web site https://samlify.js.org/ but I'm stuck.

Thanks.

@khaight
Copy link

khaight commented Mar 25, 2022

Curious if you ever had any luck with this? I am running into a similar issue.

@joshuablanco
Copy link
Author

Hi khaight, yes, basically the problem was the SP metadata.
I was declaring the SP without a certificate and I was trying to encrypt the SAML Response, that logic lead to a problem because the IDP uses the SP certificate to encrypt the SAML Response.
Please make me know any more details about your error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants