Coder Social home page Coder Social logo

passport-saml's Introduction

Passport-SAML

Build Status npm version code style: prettier codecov DeepScan grade

NPM

This is a SAML 2.0 authentication provider for Passport, the Node.js authentication library.

Passport-SAML has been tested to work with Onelogin, Okta, Shibboleth, SimpleSAMLphp based Identity Providers, and with Active Directory Federation Services.

Installation

npm install @node-saml/passport-saml

Usage

The examples utilize the Feide OpenIdp identity provider. You need an account there to log in with this. You also need to register your site as a service provider.

Configure strategy

Most of the configuration options for the Strategy constructor are passed through to the underlying node-saml library. For more details on the configuration options and how the underlying SAML flows work, see the node-saml documentation

Config parameter details

These are the Strategy parameters related directly to passport-saml. For the full list of parameters, see the node-saml documentation

  • additionalParams: dictionary of additional query params to add to all requests; if an object with this key is passed to authenticate, the dictionary of additional query params will be appended to those present on the returned URL, overriding any specified by initialization options' additional parameters (additionalParams, additionalAuthorizeParams, and additionalLogoutParams)
  • passReqToCallback: if truthy, req will be passed as the first argument to the verify callback (default: false)
  • name: Optionally, provide a custom name. (default: saml). Useful If you want to instantiate the strategy multiple times with different configurations, allowing users to authenticate against multiple different SAML targets from the same site. You'll need to use a unique set of URLs for each target, and use this custom name when calling passport.authenticate() as well.

Examples

The SAML identity provider will redirect you to the URL provided by the path configuration.

const SamlStrategy = require('@node-saml/passport-saml').Strategy;
[...]

passport.use(
  new SamlStrategy(
    {
      path: "/login/callback",
      entryPoint:
        "https://openidp.feide.no/simplesaml/saml2/idp/SSOService.php",
      issuer: "passport-saml",
      cert: "fake cert", // cert must be provided
    },
    function (profile, done) {
      // for signon
      findByEmail(profile.email, function (err, user) {
        if (err) {
          return done(err);
        }
        return done(null, user);
      });
    },
    function (profile, done) {
      // for logout
      findByNameID(profile.nameID, function (err, user) {
        if (err) {
          return done(err);
        }
        return done(null, user);
      });
    }
  )
);

Configure strategy for multiple providers

You can pass a getSamlOptions parameter to MultiSamlStrategy which will be called before the SAML flows. Passport-SAML will pass in the request object so you can decide which configuration is appropriate.

const { MultiSamlStrategy } = require('@node-saml/passport-saml');
[...]

passport.use(
  new MultiSamlStrategy(
    {
      passReqToCallback: true, // makes req available in callback
      getSamlOptions: function (request, done) {
        findProvider(request, function (err, provider) {
          if (err) {
            return done(err);
          }
          return done(null, provider.configuration);
        });
      },
    },
    function (req, profile, done) {
      // for signon
      findByEmail(profile.email, function (err, user) {
        if (err) {
          return done(err);
        }
        return done(null, user);
      });
    },
    function (req, profile, done) {
      // for logout
      findByNameID(profile.nameID, function (err, user) {
        if (err) {
          return done(err);
        }
        return done(null, user);
      });
    }
  )
);

The options passed when the MultiSamlStrategy is initialized are also passed as default values to each provider. e.g. If you provide an issuer on MultiSamlStrategy, this will be also a default value for every provider. You can override these defaults by passing a new value through the getSamlOptions function.

Using multiple providers supports validateInResponseTo, but all the InResponse values are stored on the same Cache. This means, if you're using the default InMemoryCache, that all providers have access to it and a provider might get its response validated against another's request. Issue Report. To amend this you should provide a different cache provider per SAML provider, through the getSamlOptions function.

Please note that in the above examples, findProvider(), findByNameId(), and findByEmail() are examples of functions you need to implement yourself. These are just examples. You can implement this functionality any way you see fit. Please note that calling getSamlOptions() should result in done() being called with a proper SAML Configuration (see the TypeScript typings for more information) and the done() callbacks for the second and third arguments should be called with an object that represents the user.

Provide the authentication callback

You need to provide a route corresponding to the path configuration parameter given to the strategy:

The authentication callback must be invoked after the body-parser middleware.

const bodyParser = require("body-parser");

app.post(
  "/login/callback",
  bodyParser.urlencoded({ extended: false }),
  passport.authenticate("saml", {
    failureRedirect: "/",
    failureFlash: true,
  }),
  function (req, res) {
    res.redirect("/");
  },
);

Authenticate requests

Use passport.authenticate(), specifying saml as the strategy:

app.get(
  "/login",
  passport.authenticate("saml", { failureRedirect: "/", failureFlash: true }),
  function (req, res) {
    res.redirect("/");
  },
);

...or, if you wish to add or override query string parameters:

app.get(
  "/login",
  passport.authenticate("saml", {
    additionalParams: { username: "[email protected]" },
  }),
  function (req, res) {
    res.redirect("/");
  },
);

In addition to passing the additionalParams option to passport.authenticate, you can also pass samlFallback, either as "login-request" or "logout-request". By default, this is set to "login-request". However, in the case of the req.query and the req.body not containing a SAMLRequest or SAMLResponse, this can be used to dictate which request handler is used in cases where it can not be determined by these standard properties.

generateServiceProviderMetadata( decryptionCert, signingCert )

For details about this method, please see the documentation at node-saml.

The generateServiceProviderMetadata method is also available on the MultiSamlStrategy, but needs an extra request and a callback argument (generateServiceProviderMetadata( req, decryptionCert, signingCert, next )), which are passed to the getSamlOptions to retrieve the correct configuration.

Usage with Active Directory Federation Services

Here is a configuration that has been proven to work with ADFS:

  {
    entryPoint: 'https://ad.example.net/adfs/ls/',
    issuer: 'https://your-app.example.net/login/callback',
    callbackUrl: 'https://your-app.example.net/login/callback',
    idpCert: 'MIICizCCAfQCCQCY8tKaMc0BMjANBgkqh ... W==',
    authnContext: ['http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/windows'],
    identifierFormat: null
  }

Please note that ADFS needs to have a trust established to your service in order for this to work.

For more detailed instructions, see ADFS documentation.

SLO (single logout)

Passport-SAML has built in support for SLO from Node-SAML.

Note: Fully functional IdP initiated SLO support is not provided out of the box. You have to inspect your use cases / implementation / deployment scenarios (location of IdP in respect to SP) and consider things / cases listed e.g. at issue(s) #221 and #419. This library provides you a mechanism to veto "Success" result but it does not provide hooks/interfaces to implement support for IdP initiated SLO which would work under all circumstances. You have to do it yourself.

ChangeLog

See Releases to find the changes that go into each release. Additionally, see the CHANGELOG.

FAQ

Is there an example I can look at?

Gerard Braad has provided an example app at https://github.com/gbraad/passport-saml-example/

Node Support Policy

We only support Long-Term Support versions of Node.

We specifically limit our support to LTS versions of Node, not because this package won't work on other versions, but because we have a limited amount of time, and supporting LTS offers the greatest return on that investment.

It's possible this package will work correctly on newer versions of Node. It may even be possible to use this package on older versions of Node, though that's more unlikely as we'll make every effort to take advantage of features available in the oldest LTS version we support.

As each Node LTS version reaches its end-of-life we will remove that version from the node engines property of our package's package.json file. Removing a Node version is considered a breaking change and will entail the publishing of a new major version of this package. We will not accept any requests to support an end-of-life version of Node. Any merge requests or issues supporting an end-of-life version of Node will be closed.

We will accept code that allows this package to run on newer, non-LTS, versions of Node.

Project History

The project was started by @bergie in 2012 based on Michael Bosworth's express-saml library. From 2014 - 2016, @ploer served as primary maintainer. @markstos served the primary maintainer from 2017 till 2020 when he created the node-saml organization. With a goal to create a team of maintainers, invitations were sent to major contributors and fork authors to work together to maintain all the improvements in one place.

Since 2020, @cjbath emerged as the primary maintainer, with major contributions from @gugu and @zoellner. Major updates from the team included rewriting the project in TypeScript and splitting off a node-saml module which can be used without Passport. Almost 100 other developers have contributed improvements to the project.

The project continues to be maintained by volunteers. Contributions small and large are welcome.

Copyright Notices

OASIS”, “SAML”, and “Security Assertion Markup Language” are trademarks of OASIS, the open standards consortium where the SAML specification is owned and developed. SAML is a copyrighted © work of OASIS Open. All rights reserved.

passport-saml's People

Contributors

adalinesimonian avatar alvinward avatar andkrist avatar archinowsk avatar ashimaathri avatar bergie avatar brianhartsock avatar cjbarth avatar dependabot[bot] avatar dnbard avatar eero3 avatar forty avatar gnawhleinad avatar gugu avatar heikkihakkalasc avatar jess-sheneberger avatar josecolella avatar lcalvy avatar lonerifle avatar mans0954 avatar markstos avatar mhassan1 avatar midgleyc avatar pdspicer avatar ploer avatar rob-gijsens avatar stavros-wb avatar tkopczuk avatar walokra avatar xdmnl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

passport-saml's Issues

express.get() is login in

Is there possibility to do something like this?

express.get('/, function(req, res){
if(userIsLoginIn){
res.render(…);
}else{
// It do not execute this part
passport.authenticate('saml', { failureRedirect: '/', failureFlash: true }),
function(req, res) {
res.redirect('/');
}
}
});

Handling multiple configurations for SAML selected at runtime

I'm working with Okta as a provider for SAML authentication and this repo works wonderfully for one "company" because it only needs one set of configuration parameters. My site however can consume several different companies' logins which we divide by "groups" of logins, meaning it requires different entryPoint, issuer and cert options per group. Ideally I'd like to provide this as part of the call to authenticate because then it can work in real time.

I made a temporary fix for my app, creating a req.saml = { issuer: ..., cert: ..., entryPoint:... } generated by another middleware which seems like the ideal way to pass it in. However I then override the options hash stored in the _saml.options which seems non-ideal because the chance to have a default is lost and opens up to a lot of bugs caused by unintentionally overriding defaults.

I was in a bit of hurry to get it so I haven't gone through the code extensively enough to make a proper pull request with a real solution. Does the above situation seem like something desirable? I can help implement it if needed (not sure when I'll start by myself though).

callbackUrl is not working, always redirect back to port 3000, anything wrong?

I want to change port from 3000 to 3001, but when I start using npm start, I can visit localhost:3001, but after I login, it is been redirected back to port 3000.
I tried to update config as this:

saml : {
callbackUrl : 'http://localhost:3001/login/callback',
//path : '/login/callback',
entryPoint : 'https://openidp.feide.no/simplesaml/saml2/idp/SSOService.php',
issuer : 'passport-saml'
}
Useless, still back to port 3000, anything wrong here?

Thanks

If no protocol specified, fallback to req.protocol, not to https://

If I only specify a path property and not the callbackUrl, I would expect the protocol to fallback to whatever is used in the request, not https.

For example, when I have my server running on http://localhost:4000 and I specify only the property 'path' to be /callback, I would expect the callbackUrl to be http://localhost:4000/callback, currently it will be https://localhost:4000/callback.

How to use with SimpleSAMLphp?

Hi,
I have SimpleSAMLphp IdP and SimpleSAMLphp SP.
I assume my node.js app is the SP. So, probably, I don't need SimpleSAMLphp SP?

Could you provide an example how to configure passport-saml to work with SimpleSAMLphp IdP?

passport-saml integration with onelogin

Hi
Passport-saml is not redirecting to callback url

module.exports = {
development : {
app : {
name : 'Passport SAML strategy example',
port : process.env.PORT || 8080
},
passport: {
strategy : 'saml',
saml : {
entryPoint : 'https://app.onelogin.com/trust/saml2/http-post/sso/1234',
//issuer : 'https://app.onelogin.com/saml/metadata/1234',
issuer: 'http://54.204.231.239:8080/login/callback',
callbackUrl : 'http://54.204.231.239:8080/login/callback',
cert: "onelogin.pem",
identifierFormat: null,
additionalParams:{'RelayState':null}
}
}
}
}
Please help...

Potential security vulnerability

Hi,
I tried to use passport-saml with okta as an identity provider.
I faced an issue with parsing the response from okta.
In the saml.js, there is this function called SAML.prototype.getElement.
This function gets the saml element from response.
In this the keys used to parse saml tags are 'saml' and 'samlp'.
Okta sends back 'saml2' and 'saml2p'.

So I had to add these keys in the code.
Here's how the method looks now.
Can you add it in the main library?

SAML.prototype.getElement = function (parentElement, elementName) {
if (parentElement['saml:' + elementName]) {
return parentElement['saml:' + elementName];
} else if (parentElement['samlp:'+elementName]) {
return parentElement['samlp:'+elementName];
} else if (parentElement['saml2p:'+elementName]) {
return parentElement['saml2p:'+elementName];
} else if (parentElement['saml2:'+elementName]) {
return parentElement['saml2:'+elementName];
}
return parentElement[elementName];
};

Extracting saml.js as its own module

Would you be open to this? I need SAML (but not the passport stuff) for my own nefarious purposes, and am currently approaching it with this plan:

  1. Fork passport-saml, remove everything not directly needed by saml.js
  2. Slim down the requirements (there's a conflict in our codebase with some of the requirements I think)

If you're interested in this (including potentially taking ownership of the resulting module/repo) please let me know. I could even imagine having passport-saml just pull in saml as a dependency?

Validating incoming SAML Responses?

How do you validate incoming SAML responses?

The documentation says to provide the "cert" option, and I'm doing that:

new SamlStrategy(
    {
    path:'/authorization/saml',
    cert:cert
},
function(profile, done){
    //...

, but when I go in and edit the cert by a character, making it invalid, it still works just fine, which suggests that it's not actually validating anything.

I'm testing this by using Okta as the identity provider. Perhaps I'm not setting some Okta option right?

My Okta options:
okta options

Example with logout functionality

As state in the title - I try to logout user using passport-saml. On the node.js side it works fine, but on the side of Identity Provider I'm still logged in. Don't know how correctly pass and use logoffUrl to make sure, that session will be closed also on IP side.

thanx

Getting 'Invalid Signature' error on SAML Response. XML digests do not match

We're having some issues getting passport-saml setup with an Okta IDP. We are getting a response back from our IDP, but the validation is failing. Our IDP made sure that the signature and digests are done with SHA1. Debugging into the code, (all the way into the XMLCrypto), I'm finding that it is failing when the digests don't match. If we comment out the assertion validation, we are getting all the expected data so I'm pretty sure that SAML response is formatted properly.

I added in a console.log to get the canonXML that is being hashed for the digest, and the output is this:

<ns2:Assertion xmlns:ns2="urn:oasis:names:tc:SAML:2.0:assertion" ID="_73bfe3a75de08316ce83cb05534a91aa2837" IssueInstant="2015-03-16T21:50:22Z" Version="2.0">&#xD;
        <ns2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">REDACTED</ns2:Issuer>&#xD;
        <ns2:Subject>&#xD;
            <ns2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">REDACTED</ns2:NameID>&#xD;
            <ns2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">&#xD;
                <ns2:SubjectConfirmationData NotOnOrAfter="2015-03-16T21:51:51Z" Recipient="https://REDACTED"></ns2:SubjectConfirmationData>&#xD;
            </ns2:SubjectConfirmation>&#xD;
        </ns2:Subject>&#xD;
        <ns2:Conditions NotBefore="2015-03-16T21:49:51Z" NotOnOrAfter="2015-03-16T21:51:51Z">&#xD;
            <ns2:AudienceRestriction>&#xD;
                <ns2:Audience>REDACTED</ns2:Audience>&#xD;
            </ns2:AudienceRestriction>&#xD;
        </ns2:Conditions>&#xD;
        <ns2:AuthnStatement AuthnInstant="2015-03-16T21:22:30Z" SessionIndex="rqRyLqemlvvu9A3OE9la6I1Z8iY=RgRbeg==" SessionNotOnOrAfter="2015-03-16T21:51:51Z">&#xD;
            <ns2:AuthnContext>&#xD;
                <ns2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</ns2:AuthnContextClassRef>&#xD;
            </ns2:AuthnContext>&#xD;
        </ns2:AuthnStatement>&#xD;
        <ns2:AttributeStatement>&#xD;
            <ns2:Attribute Name="FirstName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">&#xD;
                <ns2:AttributeValue>REDACTED</ns2:AttributeValue>&#xD;
            </ns2:Attribute>&#xD;
            <ns2:Attribute Name="LastName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">&#xD;
                <ns2:AttributeValue>REDACTED</ns2:AttributeValue>&#xD;
            </ns2:Attribute>&#xD;
        </ns2:AttributeStatement>&#xD;
    </ns2:Assertion>

One thing that concerns is me the ' ' line endings, yet in the console we are also getting the line feeds and other whitespace. I know next to nothing about XML canonicalization, but I'm wondering if the CRLFs in the SAML Response are not being properly transformed into the Canon XML for hashing.

Another thing we're wondering is if our configuration on the provider side has anything to do with digest and signature (aside from the cert). For example, all the code examples we've seen have 'passport-saml' as the issuer, but we used our own issuer that we created basically at random and gave to our IDP. We assumed that was just a placeholder for our own issuer.

Unfortunately, my team isn't in charge of the IDP so we don't really have much control over it, and we're also the first in our org to try to use Node.js with SAML, so we're treading new ground with our SAML team to get this working.

gulp test never quits because of InMemoryCacheProvider

I'm unit-testing the integration of passport-saml with gulp and gulp-jasmine. The problem is the test script never quits when any test initalizing passport-saml runs.

With process._getActiveHandles() I traced this to a single 28800000ms timer - this is all I could find out because node-debug gulp is excruciatingly slow - which appears only once in the entire codebase:

if(!options.requestIdExpirationPeriodMs){
    options.requestIdExpirationPeriodMs = 28800000;  // 8 hours
  }

in saml.js#L46

This is used by the InMemoryCacheProvider's cache expiry timer in inmemory-cache-provider.js#L31

setInterval(function(){
        ...
}, this.options.keyExpirationPeriodMs);

Can you recommend a strategy to "fix" testing? I'd prefer not building a new cache provider, because that would leave the builtin one untested. Perhaps exposing the intervalObject returned by setInterval which would allow clearInterval?

Or maybe there's a simpler solution I just can't see it. This freezing of the test - making gulp watch unusable - has been driving me crazy over the past few days.

Make passport-saml work with wso2 is,

I am using passport-saml nodejs module with WSO2is-5.0.0 using SAMLstragegy trying to implementt SSO, I am able to login WSO2is-5.0.0 server, using it, but when I am try to logout , my session still exist, unable to implement logout .

here my SAMLStrategy configuration:

passport.use(new SamlStrategy(
{
    path: '/AssertionConsumer',
    entryPoint: config.idpUrl,
    issuer: config.issuer,
    protocol: config.httpProtocol,
    identifierFormat : config.identifierFormat,
    logoutUrl:'/logout',
    attributeConsumingServiceIndex:1012175983,
   }, function(profile, done){

    console.log('Profile: %j', profile);
    return done(null, profile);
}
  ));

Is there any configuration I miss for wso2is-5.0.0 with passport-saml ?

This is my config data:

config.idpUrl= "https://localhost:9443/samlsso";
config.issuer = "passport-saml";
config.httpProtocol = "http://";
config.identifierFormat =  "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress";

I had checked further, starting wso2 in debug mode

log4j.logger.org.wso2.carbon.identity=DEBUG

then using a logout url in route also configure in strategy

logoutUrl:'/logout'

 router.get('/logout',passport.authenticate('saml', { failureRedirect:  '/error', failureFlash: true, samlFallback:'logout-request' }),function(req, res) {

req.logout();
res.redirect('/');

 });

now when I click further in http://localhost:9001/logout

I got this error : Error when processing the authentication request! msg in browser

so I did check in my logs found passport-saml have missing SessionIndex information in LogoutRequest

    <?xml version="1.0"?><samlp:LogoutRequest xmlns:samlp="u
      rn:oasis:names:tc:SAML:2.0:protocol"  xmlns:saml="urn:oasis:names:tc:SAML:2.0:ass
   ertion" ID="_66a8e1407de73b21ed44" Version="2.0" IssueInstant="2015-03-16T16:06:
   41.743Z" Destination="https://localhost:9443/samlsso"><saml:Issuer  xmlns:saml="u
      rn:oasis:names:tc:SAML:2.0:assertion">passport-saml</saml:Issuer><saml:NameID Fo
      rmat="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">admin</saml:NameID
    ></samlp:LogoutRequest>

other wise it should also contain session Index in Logout request

some thing like this for example:

    <saml2p:LogoutRequest Destination="https://identityserver:9443/samlsso"
                  ID="_a81995b837df1caceb991926e2adebe3468559fc"
                  IssueInstant="2015-01-02T22:30:57.569Z"
                   Version="2.0"
                    xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
<saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">liferayserver</saml2:Issuer>
 <saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
               xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">[email protected]
</saml2:NameID><saml2p:SessionIndex>8d89a03c-aebc-452f-  8ac5-035bda817ec5</saml2p:SessionIndex>
 </saml2p:LogoutRequest>

In wso2 SessionIndex is used for maintaining session, how can I get work passport-saml work with wso2?

Call validation functions in saml.js directly?

I'd like to call the parsing/validation functions in saml.js directly, bypassing the passport-related stuff altogether. Hypothetical example:

var SAML = require("saml.js").SAML;
var SignedXml = require("xml-crypto").SignedXml;

var sig = new SignedXml();
sig.computeSignature(...);

var xml = sig.getSignedXml();
var res = { SAMLResponse: new Buffer(xml).toString("base64") };

var validator = new SAML({ ... });
validator.validatePostResponse(res, function(err, profile) {
  console.log(err, profile);
});

However, passport-saml doesn't export the saml.js module, so there's no way to do this currently. :(

Perhaps we could move saml.js into it's own lightweight Node package, one that is focused purely on parsing/validating SAML? And then make it a dependency of passport-saml?

I realize this might be a bit of a tall order, but I think it makes sense. Thoughts?

By default initiate a login-request

Currently for getting the lib to work we have to provide the samlFallback property to be login-request, however, I wonder why we should call it fallback.

I believe the default should be login-request (like the older version of the lib was doing).

The default NameID format causes problems

The nameid-format currently defaults to:

urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress

This can causes problems for those IdPs that do not support this specific format e.g. TestShib.

I believe that the SAML specs indicate default should be:

urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified

I understand that the default can be overidden easily using the identifierFormat however I think it would be better if the default was set to the least restrictive option.

Thanks for maintaining a great bit of kit.

FR: SingleLogout

Add a possibility to wire a single logout callback URL, which would work both in SP-initiiated as well as in IdP-initiated scenario.

Now, only LogoutResponse is processed.

Suggestions for generating SAML responses?

Any suggestions for tools to generate SAML responses? I'm working on support for InResponseTo validation in the SAML response and need to be able to sign a SAML response, get the public key, etc...

I've come across XmlSecTool

Which seems likes its capable for the job. However it's not clear how you reference a locally generated keystore. Anyone use this? Also anyone have a good base unsigned response to start from for testing purposes? Is this as simple as taking a SAML response I've intercepted and just removing the Signature element and running it through a tool like XmlSecTool?

Any other recommended tools?

thanks.

example login form

I'm working on an app that would support multiple authentication mechanisms, including SAML. Passport basics are all working, but SAML is new to me.

Am I correct in assuming passport-saml doesn't actually need a username or a password from a login page? Just displaying a "login with your fav. SSO provider" button should be enough, which is connected to the express route that calls the authentication strategy doing redirect and whatnot.

Couldn't find an example, sorry if this is a stupid question.

Is there a preferred way to configure Passport-SAML to support dynamic IdPs?

So I'm working on an app that needs to support dynamic IdPs. Upon receiving a request, the database is queried for a config JSON object based on some request parameters. That config object will contain any and all data about the IdP we're trying to work with for SSO. How would I go about configuring passport-saml to run with dynamic configurations? Is there a smarter approach?

Different digest value's

I'm trying to authenticate using ADFS and I just hit a problem which I don't really get and thought maybe I could get some help.
So after the the response from IdP comes back I can see it has CipherValue so I debugged and saw that the passport-saml decrypts it.
The problem is that while it decrypts it, it throws an exception at signed-xml.js row 291, when it tries to compare between the digest that it calculated and the digest that was recieved.
Any idea why is this happening?

Thanks in advance!

Signature namespace defined in parent

I'm having an issue where in an Assertion, the namespace of the signature is defined in the Response element.

<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" 
xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
...

    <dsig:Signature>      
...
    </dsig:Signature>

So when the validateSignature method extracts the node and converts it to a string, the namespace is lost (and xml-crypto rejects since it queries based on the namespace-uri)

Is this something passport-saml cares about? or is this a bad use of the Signature element/namespace?

Temporarily, I have put a workaround in the validateSignature function for myself:

Instead of simply var signature = signatures[0].toString(); in line 347

  var signature = signatures[0];

  // If Signature doesn't have it's namespace explicitly defined (was defined in parent)
  // it will be lost in the toString(), in this case, add it
  var prefix = signature.prefix;
  var nsAttr = 'xmlns';
  if (prefix) {
    nsAttr += ':' + prefix;
  }
  if (!signature.hasAttribute(nsAttr)) {
    signature.setAttribute(nsAttr, 'http://www.w3.org/2000/09/xmldsig#');
  }

  signature = signature.toString();

Distributed System

Hello Bergie,

Does this module support distributed system authorization?

Thanks.

InCommon Federation

Hello!

I am trying to implement an authentication mechanism for our web application that uses InCommon Federation / IdP discovery (https://www.incommon.org/federation/). This allows user to select their home institution from a list presented by InCommon discovery service (http://www.incommon.org/federation/discovery.html), and forwarded to individual IdP for authentication, and finally get profile back to my web application - instead of manually having to configure IdP individually with my web app.

I am very new to the idea of SAML federation, but it looks like current implementation of passport-saml doesn't support this; it's missing the idpdisc:DiscoveryResponse in the metadata for one thing.

My questions are ..

  1. Does passport-saml already allow me to use InCommon federation? If so, is there a sample code?
  2. If not, is there any plan of adding support to InCommon federation / IpD discovery service?
  3. If there is no plan, I am thinking about adding such support to passport-saml (in a fork). If I do, is there any chance of merging it to upstream?

Thank you!!

Bug in SAML.prototype.generateInstant

Just a heads up, I don't have a fork so Ill just give you the details.

The method SAML.prototype.generateInstant() has a bug in it - it returns invalid time strings when the current time is within 2 hours of midnight UTC. For example, if it is 23:20 UTC, this method will return a string with the time set to 24:20 (which is not valid). A simple fix is below (does the offset prior to conversion to xml datetime string)

ORG CODE

SAML.prototype.generateInstant = function () {
var date = new Date();
return date.getUTCFullYear() + '-' + ('0' + (date.getUTCMonth()+1)).slice(-2) + '-' + ('0' + date.getUTCDate()).slice(-2) + 'T' + ('0' + (date.getUTCHours()+2)).slice(-2) + ":" + ('0' + date.getUTCMinutes()).slice(-2) + ":" + ('0' + date.getUTCSeconds()).slice(-2) + "Z";
};

FIXED CODE

SAML.prototype.generateInstant = function () {
var currDate = new Date();
var date = new Date();
date.setTime(currDate.getTime() + (2 * 60 * 60 * 1000)) // add 2 hours
return date.getUTCFullYear() + '-' + ('0' + (date.getUTCMonth()+1)).slice(-2) + '-' + ('0' + date.getUTCDate()).slice(-2) + 'T' + ('0' + date.getUTCHours()).slice(-2) + ":" + ('0' + date.getUTCMinutes()).slice(-2) + ":" + ('0' + date.getUTCSeconds()).slice(-2) + "Z";
};

AuthnRequest IssueInstant is off by 2 hrs

I see that saml.generateInstant() adds 2 hours to the return of 'getUTCHours'. For this reason the saml authentication fails for two hours every day. Did you have a specific reason why you did that?

HTTP POST Binding in passport-saml

Hi,
I've to use passport-saml in HTTP POST Binding. Would you please help me to find a way to add this implementation to this module? Is there a pre-existent module doing this?

Thanks

Cannot use dynamic values for entryPoint and cert

So currently, the lib requires you to specify the entry point on the app load but onelogin requires the url to be dynamic like https://app.onelogin.com/trust/saml2/http-post/sso/{{random_id_generated}}. Thoughts on how to do this currently because I might just be doing it wrong but this seems like a common use case where there are multiple companies.

passport.use(new SamlStrategy({
    issuer: 'someone',
  }, function(profile, done) {
    console.log('Auth with', profile);
    if (!profile.nameID ) {
      return done(new Error('No email found'), null);
    }
    return done(null, null)
  }))
  app.get('/saml/auth', function (req, res, next){
    return passport.authenticate('saml', { 
       entryPoint:  req.company.entryPoint,
       cert:  req.company.cert
    })(req, res, next)
  }, authentication.samlAuth)

Shibboleth update

These are the steps I performed to try to connect our Node.JS app with a Shibboleth IdP

Setup

  1. Register our node app as a Service Provider with the Identity Provider.

I used testshib.org to test our setup. I copied the metadata.xml from a standard SP (running under Apache with mod_shib which in turn talks to shibd) and significantly slimmed it down to

<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" ID="_957cf08a6730ac2e70ce094b8262cdf79ce25120" entityID="https://oae.cam.ac.uk/shibboleth">

  <md:Extensions xmlns:alg="urn:oasis:names:tc:SAML:metadata:algsupport">
    <alg:SigningMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
  </md:Extensions>

  <md:SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
    <md:KeyDescriptor>
      <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:KeyName>linux-5z8i.site</ds:KeyName>
        <ds:X509Data>
          <ds:X509SubjectName>CN=linux-5z8i.site</ds:X509SubjectName>
          <ds:X509Certificate>MIIC9DCCAdygAwIBAgIJAJPgjeqQYMniMA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNV
BAMTD2xpbnV4LTV6OGkuc2l0ZTAeFw0xMzAyMDgxODQ5MzlaFw0yMzAyMDYxODQ5
MzlaMBoxGDAWBgNVBAMTD2xpbnV4LTV6OGkuc2l0ZTCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAOoq83FgLTaOMqFMjsrmKk80S4kDpixN9ajKdBjTD+9f
iOUIr5x8a/xdE8OkDGWZsMTRJzAK3Mj1xY/d5NrGLCyKnb1v5ylLUd41NdpECRhl
GZvonbqrB6usdm+Bs01NOdyerjvhyLovQddtv/eFvi51bwtKr9JhH+H6Nh9Y0u/V
5Sjq+5DWug8QgA4+BHXSxYsKVhrAqxLHNPUCFzIqggF/Ncc4V8To3laH8YotF2uo
AnQKs7qpIvDxpWYnWBIFFZsemozW8IE6gxY/WiAnTOOHULCMe49RUDu12fIyQOwd
FrmsRncU7kMkvgFJpDQj6Hs6gff+4CzlwItB+O5tD7sCAwEAAaM9MDswGgYDVR0R
BBMwEYIPbGludXgtNXo4aS5zaXRlMB0GA1UdDgQWBBStENAKttjMN3gopEzHNHSz
gEurazANBgkqhkiG9w0BAQUFAAOCAQEAYpVMAZkxyf0MQNI0BOrMj4ufvqxF8Phh
kpN4m/qa/Bz741W2oXYWRRuziQemho7LFeSutcj05uL9UoYSGl9Uf+gNJyVNqIwX
HZ4rbetphzrxoQpR8/ykIf8px70Af38bv0v8iNPyyaiW4uAj8b6rUNV2Q1BSyZKk
CqLh5BUnKaw8atgFgMyulqZ/QqPXzMp+MvLMf8eykBtvM85RyNbbtkDOIEmugCFL
eJBy/J977I8UjVG3NaSG6PW1TSt/UumfnDNPKORYDlvpqq/RhJPp1bA3JxZWYaEu
+mgippboa2s6KL7xFO3X7b+Tr8OympTngHY/HzlWsa0G5MR3Op5RSg==
</ds:X509Certificate>
        </ds:X509Data>
      </ds:KeyInfo>
      <md:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/>
    </md:KeyDescriptor>
    <md:AssertionConsumerService Location="https://oae.cam.ac.uk/api/auth/saml2/callback" index="1" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" />
    <md:AssertionConsumerService Location="https://oae.cam.ac.uk/api/auth/saml2/callback" index="5" Binding="urn:oasis:names:tc:SAML:1.0:profiles:browser-post" />
  </md:SPSSODescriptor>

</md:EntityDescriptor>

As you can see our SP only supports HTTP-POST and browser-post and a very small subset of signing/encryption mechanismes.

  1. Setup passport-saml
    I used the following node code to register the SAML strategy. (slimmed down for brevity)
    var strategy = new SamlStrategy({
        'path': '/api/auth/saml2/callback',
        'entryPoint': 'https://idp.testshib.org/idp/profile/SAML2/Redirect/SSO',  // Use the redirect option
        'issuer':  'https://oae.cam.ac.uk/shibboleth',  // The entity ID we used to register our SP with
        'cert':  'MIIEDjCCAvagAwIBAgIBADANBgkqhkiG9w0 ....',  // The public key from the testshib.org IdP
        'privateCert': 'MII... ', // Our SP private key that matches the public one.
        'identifierFormat': null 
    }, function(profile, done) {
          // Verify function
         // get or create user
         // ...
    });
    passport.use('saml2', strategy);

...

//  `server` is the express server.

// Redirect the user to the configured SAML2 compatible IdP. When complete,
// the IdP will redirect the user back to the application at
// /api/auth/saml2/callback
server.get('/api/auth/saml2', function(req, res, next) {
     // Some custom logic which isn't important in this context
     passport.authenticate('saml2')(req, res, _handlePassportError(req, res, next));
});

// The IdP will redirect the user to this URL after approval.
server.post('/api/auth/saml2/callback', function(req, res, next) {
     // Some custom logic which isn't important in this context
    passport.authenticate('saml2', {'successRedirect': '/', 'failureRedirect': '/'})(req, res, next);
});

That's about it regarding setup.

Testing

  1. Browse to /api/auth/saml2
    This gets picked up by the passport-saml strategy and results in the following SAML object
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="_2331765beede7e5acda2" Version="2.0" IssueInstant="2013-02-11T17:03:18Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" AssertionConsumerServiceURL="https://oae.cam.ac.uk/api/auth/saml2/callback"
Destination="https://idp.testshib.org/idp/profile/SAML2/Redirect/SSO">
    <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">https://oae.cam.ac.uk/shibboleth</saml:Issuer>
    <samlp:RequestedAuthnContext xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Comparison="exact">
        <saml:AuthnContextClassRef xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef>
    </samlp:RequestedAuthnContext>
</samlp:AuthnRequest>

Which gets succesfully turned into a suitable URL (ie: the XML gets base64'ed and the proper idp URL gets generated)

  1. My browser takes me to the shib IdP where I can log in with on the test accounts
  2. I check the IdP logs and see the incoming request.
  3. The IdP verifies my PW and generates a SAML response which it signs and encrypts and POSTs to my /api/auth/saml2/callback endpoint
    This is the point where passport-saml blows up.
    The XML it receives from the shibboleth IdP looks like
<?xml version="1.0" encoding="UTF-8" ?>
<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" Destination="https://oae.cam.ac.uk/api/auth/saml2/callback" ID="_fa84b84c92664434e0844485fbde6326" InResponseTo="_2331765beede7e5acda2" IssueInstant="2013-02-11T17:03:45.590Z" Version="2.0">
    <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">https://idp.testshib.org/idp/shibboleth</saml2:Issuer>
    <saml2p:Status>
        <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" /></saml2p:Status>
    <saml2:EncryptedAssertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
        <xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="_f10fa6b20292f7cc337ee32e5ecf17ad" Type="http://www.w3.org/2001/04/xmlenc#Element">
            <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" />
            <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
                <xenc:EncryptedKey Id="_b1e6d0ed4ce24daa0c018b90f715b43d" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
                    <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
                        <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" />
                    </xenc:EncryptionMethod>
                    <ds:KeyInfo>
                        <ds:X509Data>
                            <ds:X509Certificate>MIIC9DCCAdygAwIBAgIJAJPgjeqQYMniMA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNVBAMTD2xpbnV4 LTV6OGkuc2l0ZTAeFw0xMzAyMDgxODQ5MzlaFw0yMzAyMDYxODQ5MzlaMBoxGDAWBgNVBAMTD2xp bnV4LTV6OGkuc2l0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOoq83FgLTaOMqFM jsrmKk80S4kDpixN9ajKdBjTD+9fiOUIr5x8a/xdE8OkDGWZsMTRJzAK3Mj1xY/d5NrGLCyKnb1v
                                5ylLUd41NdpECRhlGZvonbqrB6usdm+Bs01NOdyerjvhyLovQddtv/eFvi51bwtKr9JhH+H6Nh9Y 0u/V5Sjq+5DWug8QgA4+BHXSxYsKVhrAqxLHNPUCFzIqggF/Ncc4V8To3laH8YotF2uoAnQKs7qp IvDxpWYnWBIFFZsemozW8IE6gxY/WiAnTOOHULCMe49RUDu12fIyQOwdFrmsRncU7kMkvgFJpDQj 6Hs6gff+4CzlwItB+O5tD7sCAwEAAaM9MDswGgYDVR0RBBMwEYIPbGludXgtNXo4aS5zaXRlMB0G
                                A1UdDgQWBBStENAKttjMN3gopEzHNHSzgEurazANBgkqhkiG9w0BAQUFAAOCAQEAYpVMAZkxyf0M QNI0BOrMj4ufvqxF8PhhkpN4m/qa/Bz741W2oXYWRRuziQemho7LFeSutcj05uL9UoYSGl9Uf+gN JyVNqIwXHZ4rbetphzrxoQpR8/ykIf8px70Af38bv0v8iNPyyaiW4uAj8b6rUNV2Q1BSyZKkCqLh 5BUnKaw8atgFgMyulqZ/QqPXzMp+MvLMf8eykBtvM85RyNbbtkDOIEmugCFLeJBy/J977I8UjVG3
                                NaSG6PW1TSt/UumfnDNPKORYDlvpqq/RhJPp1bA3JxZWYaEu+mgippboa2s6KL7xFO3X7b+Tr8Oy mpTngHY/HzlWsa0G5MR3Op5RSg==</ds:X509Certificate>
                        </ds:X509Data>
                    </ds:KeyInfo>
                    <xenc:CipherData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
                        <xenc:CipherValue>FTEOGQ+iQaVmqnt5KvAKVr4BRGkhT67AuH6ElMgHdwkJewsytpDj2KLkkKjEtkrIC3ldzkpty1KlsT00CPeXUdOh/ucHHJlBZ97wN6zDI4Lv6iefVoZiCF565AeBMPU1AxhwxDQ3JqGWwli0cYmCcNbrthPC3soqlbZRxMObHzzsPtDLgs+VDj0fO794bSJ51x4lrY6GsL0JqSCLLalYtELI45PTt0mvR1/GwEj85EAt2wFb6IU94bUtesNHv3aVG/oKF0kcGfqF+NND2oK1BgGYd2ISICujKeBDSc+EHehmwgH5dTvfKSmAy6A6ilj39eRZDwCERN+SOU2VYqyuRw==</xenc:CipherValue>
                    </xenc:CipherData>
                </xenc:EncryptedKey>
            </ds:KeyInfo>
            <xenc:CipherData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
                <xenc:CipherValue>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</xenc:CipherValue>
            </xenc:CipherData>
        </xenc:EncryptedData>
    </saml2:EncryptedAssertion>
</saml2p:Response>

This is the step where SAML blows up (not illogical as it probably doesn't expect encrypted SAML assertions.)

Now, AFAICT the only thing that needs to happen is implement the 'decryption' step. I'm not entirely sure if it's feasible to implement all the supported encryption algorithms, but it might be worth the attempt to try a couple?
I'd be interested in hearing your input.

How to add signature on AuthnRequest

Hello,
I'm trying to add signature on my AuthnRequest.
I've tried to add some configuration to SamlStrategy but nothing appens on AuthnRequest XML.
Do i need to use another module like XML-Crypto ? If yes, how??

This is the configuration for Strategy :

passport: {
            strategy : 'saml',
            saml : {
                entryPoint : 'https://idp.idp.it/samlsso',
                issuer : 'http://111.111.11.111:8000',
                callbackUrl : 'http://111.111.11.111:8000/login/callback',
                identifierFormat: 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient',
                decryptionPvk: fs.readFileSync('./config/saml.key'),
                cert:'MII....Q==',
                validateInResponseTo :true,
                authnContext : 'urn:oasis:names:tc:SAML:2.0:ac:classes:name1',
                protocol: 'http://',
                attributeConsumingServiceIndex:0
            }
        }

This how route the login request, but i don't know how to add signature on it

app.get("/login",
        passport.authenticate(config.passport.strategy,
        {
            successRedirect : "/",
            failureRedirect : "/login",
        })
    );

    app.post('/login/callback',
        passport.authenticate(config.passport.strategy,
            {
                failureRedirect: '/',
                failureFlash: true
            }),
        function(req, res) {
            res.redirect('/');
        }
    );

This is the SAML AuthnRequest xml :

<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
                    ID="_6eefdebac845aec3b311"
                    Version="2.0"
                    IssueInstant="2015-03-30T09:47:12.835Z"
                    ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
                    AssertionConsumerServiceURL="http://111.111.11.111:8000/login/callback"
                    Destination="https://idp.idp.it/samlsso"
                    >
    <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">http://111.111.11.111:8000</saml:Issuer>
    <samlp:NameIDPolicy xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
                        Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
                        AllowCreate="true"
                        />
    <samlp:RequestedAuthnContext xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
                                 Comparison="exact"
                                 >
        <saml:AuthnContextClassRef xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">urn:oasis:names:tc:SAML:2.0:ac:classes:name1</saml:AuthnContextClassRef>
    </samlp:RequestedAuthnContext>
</samlp:AuthnRequest>

"Invalid RSAES-OAEP padding" Error

Here's my SAML Configuration:

var samlStrategy = new saml.Strategy({
    callbackUrl: 'https://myServer.rit.edu/login/callback',
    entryPoint: 'https://shibboleth.main.ad.rit.edu/idp/profile/SAML2/Redirect/SSO',
    issuer: 'https://myServer.rit.edu/shibboleth',
    identifierFormat: null,
    decryptionPvk: fs.readFileSync('/var/www/saml/key.pem', 'utf8'),
    cert: 'MIIDV......'
}, function(profile, done) {
    return done(null, profile);
});

Routes:

app.get('/',
  passport.authenticate('saml', {failureRedirect: '/login/fail'}),
  function(req, res) {
    res.send('Authenticated');
  }
);

app.post('/login/callback',
   passport.authenticate('saml', { failureRedirect: '/login/fail' }),
  function(req, res) {
    res.redirect('/');
  }
);

General error catcher:

app.use(function(err, req, res, next){
    console.log('Express error!');
    console.log("the error: " + JSON.stringify(err));
    next(err);
});

Shibboleth processes the request and a SAMLResponse is present in the header of callback route, /login/callback.

An error is thrown at passport.authenticate('saml', {failureRedirect: '/login/fail'}) in the / route.
Console log:

Express error!
the error: {"message":"Invalid RSAES-OAEP padding."}

Any ideas?

NOTE: reactivating project, new maintainer

This project has been dormant for a while since Henri has moved on to other things. I just wanted to let everyone know I am now taking over maintenance of the project and will be publishing a new version in npm shortly.

Pull requests welcome. :-)

cheers,

peter

Adding HTTP headers

Is there a way to add http headers to the request to the Authorization server? For instance, I have a consumer key that needs to be included in the Authorization header.

How to prevent replay of SAML responses?

The issue I'm seeing is that the browser (in this case IE9) is storing the 302 request for the /saml/consume route in the browser history (this request contains the SAML response data in the body).

This means that a user hitting the back button, when they hit 'back' to this entry, a request will be sent to the node server and passport-saml module will interpret the SAML response supplied with the request and generate a valid passport session.

This is undesirable as a user can log out (and we delete the passport session), and then simply by hitting the back button, can be logged in again (or maybe logged in as a different user).

I think the solution to this problem is to have support in passport-saml to prevent replaying the SAML response, or supporting the OnBefore or NotOnOrAfter attributes in the response.

Is this kind of support available? Any suggestions on implementing this?

it seems like maybe this problem goes away if both the service provider and IDP are running under SSL - is that assumption correct?

Here's a stackoverflow question with an answer that I think hits on the possible solutions. Can anyone with some expertise in this area confirm that my thinking is correct?

thanks!

Change in documentation

Additional configs states that setting samlFallback to 'getAuthorizeUrl' will cause a redirect when really it is set samlFallback to 'login-request'

Validating SLO responses

I can generate a SLO request like this:

strategy.logout({
  ...
}, function createdLogoutUrl(error, requestUrl) {
  reply.redirect(requestUrl);
});

The user gets redirected to the SAML IdP which then redirects them back to the URL defined in the Location attribute of the SingleLogoutService element in the SP's metadata file, so far, so good, but the GET redirection from the IdP contains a SAMLResponse as part of the query string.

I can see there's a validatePostResponse method on the SAML class - how would I go about validating a GET response?

passport-saml debug

Hey do you have a clue, how to debug passport-saml.
My app:
app.post ('/callback' , passport.authenticate('saml', {failureRedirect: '/', failureFlash: true}), function(req,res){
res.redirect('/');
});
if I do the following:
args.app.post ('/callback' , /*passport.authenticate('saml', {failureRedirect: '/', failureFlash: true}), */ function(req,res){
res.redirect('/');
});
it works totally fine.

It is in a loop and redirects me to the login page again and again. I am looking for a way how to debug it (on linux).

Getting to work with Salesforce IDP...

This code works properly as long as I don't supply the cert option to do signature validation. When I add the cert value, I get this (having dug into xml-crypto stuff):

'invalid signature: for uri #_fab050762cee2d1ead90663534fa1ea71351722430313 calculated digest is pBBC3Gm4+/cvi4Q2xu0KaNbk+gA= but the xml to validate supplies digest mxsu5Cr0qZH+6ZBj4SkDJTP0QUA='

Im lost at this point... Any suggestions for how to troubleshoot this?

Support id attribute variations?

As seen here, xml-crypto allows for an element's id attribute to be specified as "Id" or "ID". But I noticed here and here that passport-saml only supports "ID". Possible to make it support "Id" as well? (Not sure what the implications are, if any)

How to change callbackURL?

Hi Dear

I am trying on your sample passport-saml-example.
I found IE always will be redirect to fixed-url "localhost:3000" after logo on  Feide openIdP.

I tried to set param "callbackUrl" with full url but no luck.

Could you please tell me how to change hostname&port of callbackURL?
Thanks in advance!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.