tngan / samlify

Node.js library for SAML SSO
https://samlify.js.org
MIT License
604 stars 213 forks source link

Provide more informations about creating the service #118

Closed rolljee closed 6 years ago

rolljee commented 7 years ago

Hello, I'm confusing with the whole setup.

What I want ? I want a user from my application to connect to an ADFS via SAML2 :

What I've done so far:

So, what I understand so far is that my ADFS will be the Identity provider ? And my application will be the Service Provider ?

// for now, I fetch the https://<adfs>/FederationMetadata/2007-06/FederationMetadata.xml
const idp = saml.IdentityProvider({
    metadata,
}); // I believe the package will do the job in order to setup the IDP correctly am I right ?

What I'm missing is the configuration for the service provider ?

const sp = saml.ServiceProvider({
    dataEncryptionAlgorithm: 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
    requestSignatureAlgorithm: 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
    metadata, // using the same Metadata object from the ADFS- I don't know for know what should I put in there ?
});
const url = sp.createLoginRequest(idp, 'redirect'); // this create a request that won't be accepted by our ADFS.

On the ADFS

An error appear each time I sent a SAML request, saying that :

screen shot 2017-08-31 at 17 44 18

What metadata I'm suppose to provide for my SP ? And witch certificate or private key I'm suppose to give in order to make it work ?

I'm still confuse about how this work, if someone can help me. 😞

tngan commented 7 years ago

@rolljee

So, what I understand so far is that my ADFS will be the Identity provider ? And my application will be the Service Provider ?

Answer is yes.

From my understanding, you are trying to do the SP-initiated SSO, right ?

For your configuration of service provider, you can use this online tool to build your metadata.

There are a lot of options to make the service works, feel free to send your message to passify.io@gmail.com if you don't want to expose the business secret here, using this pgp key for email encryption if you want.

rolljee commented 7 years ago

Thank you for the fast answer, I will work on it !

From my understanding, you are trying to do the SP-initiated SSO, right ? Answer is yes.

I will create the metadata on the website then I will run against my ADFS and see what happen.

tngan commented 7 years ago

@rolljee Please also follow https://github.com/Passify/samlify-sp, the example repository will be released very soon.

rolljee commented 6 years ago

Hello again @tngan as discussed

I managed to create the metadata, and tested it against the ADFS

Now i have some more information about my error.

adfs

It seems that my SP metadata are not compliant to my IDP metadata ?

<?xml version="1.0"?>
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
                     validUntil="2017-09-15T15:09:55Z"
                     cacheDuration="PT604800S"
                     entityID="entity">
    <md:SPSSODescriptor AuthnRequestsSigned="false" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
        <md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
                                Location="<mysite>logout" />
        <NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</NameIDFormat>
        <NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</NameIDFormat>
        <NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
        <samlp:NameIDPolicy Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" AllowCreate="false"/>
        <md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
                                     Location="<mysite>samlcallback"
                                     index="1" />

    </md:SPSSODescriptor>
</md:EntityDescriptor>

For now i only get this error when parsing the response : Error -> [TypeError: Cannot read property 'SAMLResponse' of undefined] Do you now what should i do now to pass the emailAddress correctly to my createLoginRequest ?

once again, thank for all your help :)

tngan commented 6 years ago

@rolljee The SAML request is failed in IdP side, it seems that the configuration is not correct. Please also check this thread for more information.

NameIDPolicy in metadata specifies the constraints of the name identifiers, if you don't specify it, that means any format that supported in IdP can be used.

For example, the sample response contains a NameID would be like that.

<saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">user@email.com</saml2:NameID>

In fact, you don't need to include email address in your SAML request. Typical flow of SP-initiated SSO would be like:

  1. SP sends SAML request to IdP
  2. If session is not expired, then user is logged into IdP, otherwise goes (3)
  3. If SAML request is valid (e.g. signature), redirect to login screen of IdP, otherwise it's failed
  4. If credential (login and password) is not correct, it's failed, otherwise goes (5)
  5. IdP creates a session to user, and construct a SAML response back to SP
  6. If SP fails to validate, decrypt and parse the SAML response, it's failed, otherwise goes (7)
  7. User is now logged into SP, SSO is successfully completed
rolljee commented 6 years ago

Hi again @tngan

Thx for all your help, i managed to configure correctly my ADFS.

I modified the binding from the relaying party trust in order to 'redirect' instead of making a 'POST' request, I have now the correct response comming from the IDP.

Using the online tool you provided, i managed to deflate and decode the Signed base64 message. I'm now looking for a way to deflate and decode in my application, since your library doesn't support yet the 'redirect' binding ? ( Am I wrong ?)

You can close this issues as i have now all informations in order to make it work :) You made a good work in that library wish you luck ! πŸ‘

tngan commented 6 years ago

@rolljee Redirect binding for request is supported in this library.

rolljee commented 6 years ago

@tngan I mean redirect binding for adfs response not for request :)

Using this piece of code, i managed to decrypt any response incomming from an adfs redirect binding.

import atob from 'atob';
import inflate from 'tiny-inflate';

const authnRequest = String(params.query.SAMLResponse) + String(params.query.Signature);
const strData = atob(authnRequest);
const charData = strData.split('').map(function (x) { return x.charCodeAt(0); });
const compressedBuffer = new Buffer(charData);
const outputBuffer = new Buffer(compressedBuffer.length * 1000); // GZip max compression ratio
const output = String(inflate(compressedBuffer, outputBuffer));
sagarbetkar commented 9 months ago

@tngan I am using ADFS as IDP, I am able to login using samlify.js but I am facing issue in logout. After I implement the @rolljee last comment code I am receiving a XML response after that I am not sure what exactly to do , which SP method to use to parse it so I can logout properly. If possible please provide a code sample. Thank you.

sagarbetkar commented 9 months ago

Hello, Found the solution for proper logout [Proper LogoutRequest for Single Logout with ADFS IdP](https://stackoverflow.com/questions/44290083/proper-logoutrequest-for-single-logout-with-adfs-idp) Releasing NameID with a Specified Format