node.jspassport.jssaml-2.0openam

Configure nodejs as SP with passport-saml and OpenAM as IDP


I deployed OpenAM and created hosted IDP. Then I want to configure NodeJs as Service Provider and implement SSO with passport-saml. For this, I have to register my node.js application as a remote service provider.

I have two questions:

  1. In order to register NodeJs application as a remote service provider, I must tell to OpenAM URL where metadata is located. How I can get metadata with passport-saml ?

  2. How to configure passport-saml to work with OpenAM?


Solution

  • I configured passport-saml like this :

    return new SamlStrategy(
        {
    
    entryPoint: "http://ndcdr001s:8081/OpenAM-12.0.0/saml2/jsp/idpSSOInit.jsp?"
          + "metaAlias=/idp"
          + "&spEntityID=http://ndcui.local:9000/metadata/",
    
          callbackUrl: 'http://ndcui.local:9000/login/callback/',
    
          logoutUrl: "http://ndcdr001s:8081/OpenAM-12.0.0/saml2/jsp/idpSingleLogoutInit.jsp?"
          + "binding=urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
          + "&RelayState=http://ndcui.local:9000/saml/logout/callback",
    
          issuer: 'http://ndcui.local:9000/'
        },
        function (profile, done) {
    
          return done(null,
            {
              id: profile.id,
              email: profile.email,
             // displayName: profile.cn,
            //  firstName: profile.givenName,
             // lastName: profile.sn,
              sessionIndex: profile.sessionIndex,
              saml: {
                nameID: profile.nameID,
                nameIDFormat: profile.nameIDFormat,
                token:profile.getAssertionXml()
              }
            });
        });    
    

    Then I registered "http://ndcui.local:9000/metadata/" as SP in OpenAM.

    I created metadata for SP manually like this: and put under the this link "http://ndcui.local:9000/metadata/"

    <EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" entityID="http://ndcui.local:9000/metadata/">
      <SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
    
        <SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"  Location="http://ndcui.local:9000/logout"  Response_Location="http://ndcui.local:9000/saml/logout/callback"/>
    
        <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://ndcui.local:9000/login/callback" index="0"/>
        <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:1.0:profiles:browser-post" Location="http://ndcui.local:9000/login/callback" index="1"/>
        <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="http://ndcui.local:9000/login/callback" index="2"/>
        <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:1.0:profiles:artifact-01" Location="http://ndcui.local:9000/login/callback" index="3"/>
        <AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:profiles:holder-of-key:SSO:browser" Location="http://ndcui.local:9000/login/callback" index="4"/>
       </SPSSODescriptor>
      <ContactPerson contactType="technical">
        <GivenName>Administrator</GivenName>
        <EmailAddress>noreply@example.org</EmailAddress>
      </ContactPerson>
    </EntityDescriptor>
    

    And my routes:

    app.get('/metadata', function (req, res) {
    
     //Send custom metadata
          res.type('application/xml');
          res.sendfile(__dirname + "/metadata.xml");
        }
      );
    
    app.get("/login", passport.authenticate('saml',
          {
            successRedirect: "/",
            failureRedirect: "/login",
          })
      );
    
    app.post('/login/callback', passport.authenticate('saml',
          {
            failureRedirect: '/',
            failureFlash: true
          }),
        function (req, res) {
          res.redirect('/');
        }
      );
    
    app.get('/logout', auth.requiresLogin, function (req, res) {
    
        req.user.nameID = req.user.saml.nameID;
    
        req.user.nameIDFormat = req.user.saml.nameIDFormat;
    
        samlStrategy.logout(req, function (err, request) {
          if (!err) {
            res.redirect(request);
          }
        });
    
      });
    
    app.get('/saml/logout/callback', auth.requiresLogin, function (req, res) {
        //Logout user
        req.logout();
        res.redirect('/');
    
      });
    

    Link to full Implementation (you will want to google translate the page)

    https://qiita.com/nsp01/items/d1b328e5698f6ffd8345