node-saml / passport-saml

SAML 2.0 authentication with Passport

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[BUG]

nagarajanceg opened this issue · comments

The application using single sign on flow in Azure AD using the npm package passport-saml.

Application built in nodejs express framework.

passport saml Configuration looks like this snippet:

filename - config.js

passport: {
    strategy: 'saml',
    saml: {
        path: process.env.SAML_PATH ,
        entryPoint: process.env.SAML_ENTRY_POINT || 'https://login.microsoftonline.com/tenant/saml2',
        issuer: 'app id',
        cert: process.env.SAML_CERT,
        callbackUrl: "https://application_url/login/callback",
        logoutUrl: 'https://login.microsoftonline.com/tenant/saml2',
    }
}

In the above config entry point & logoutUrl is same. 1) Is it possible to have same URL for both logout & login(entry point) in passpor-saml?

Code snippet for express app which consumes passport SAML strategy to connect Azure AD.

filename - connect.js:

const SamlStrategy = require('passport-saml').Strategy;
const config = require('./config.js');

app.use(passport.initialize())
passport.serializeUser((user, done) => {
        done(null, user);
    });
passport.deserializeUser((user, done) => {
        done(null, user);
    });

passport.use(new SamlStrategy(config.passport.saml,
function (req, token, refreshToken, profile, done) {
    
}
))

/*express app router*/

app.get("/login", (req, res, next) => {
     passport.authenticate(config.passport.strategy, { failureRedirect: "/" })(req, res, next);
})

app.post('/login/callback', (req, res, next)=> {
 /*processing logic after the successful auth from Azure AD SAML*/
})

Up to this point it's possible to do SAML auth in Azure AD and received the login callback as well. Note: Login callback properly configured in Redirect URI's of Azure AD application.

Moving on, having a problem in performing logout on an express app router.

LogoutUrl is configured in Azure AD application settings
Azure logout-url screenshot

Whenever app hits movelogout route and it needs to logout Azure Ad session. 2) How it's possible to issue a logout request to Azure AD inside this route using passport-saml strategy?

Code continues
filename: connect.js

  app.get('/movelogout', (req, res, next)=> {
     req.logout(); // is it sufficient to do logout in passport ?  
    //How to issue logout request ?
      
 })

/*Callback for successful logout in Azure AD*/
app.post('/logout', (req, res, next) => {
     //Do post logout operation
})

In the nutshell, I have been trying to accomplish Azure Single sign out SAML protocol using passport-saml. The link having SAML logout request and it's not having explanation in javascript way of issuing SAML request.

I am not quite sure with relation between logoutUrl in config & front-end logout Url in Azure setting. During login passport.authenticate method does all the SAML to (Identity provider) IDP. Even though logout url is configured in passport-saml and it's not sure when it needs to be used to issue logout request to IDP.

Any suggestions or solutions to perform Azure AD session logout manually are much appreciated!

Environment:
Node 10V
passport-saml : 2.0.1

commented

@nagarajanceg sorry, not going to go through how to trigger LogoutRequest from your service to IdP because:

Big picture seems to be that you want to have fully functional SAML SLO meaning that you want to have also handling of LogoutRequest sent by IdP to your service and responding to IdP with proper LogoutResponse.

IdP sends LogoutRequest to your service if your service is one of those services to whome IdP - Azure AD - broadcasts LogoutRequest as a result of end user initiating SLO from some other SP which participates to same SSO session … see the picture in the azure document that you linked to your issue report.

After your question about how to trigger SLO process would be solved the next question would be how to send LogoutResponse from passport-saml to IdP. Short answer to that question would be that passport-saml's LogoutRequest handling has known and unsolved security related issue which pretty much makes passport-saml's current SLO implementation unusable/unsecure and you would probably start to seek an another solution (like placing your service behind Shibboleth SP or Keycloak or switching from saml to oidc and start to investigate whether oidc libraries support SLO).

More information about aforementioned passport-saml's SLO issue can be found from #419 and #622

BTW. maybe you are already in a process of starting to use oidc because code snippet that you posted shows that you are configuring SamlStrategy with verify function which ”fingerprint” contains oauth2/oidc related concepts like ”token” and ”refreshToken”. Quote from your issue report:

passport.use(new SamlStrategy(config.passport.saml,
function (req, token, refreshToken, profile, done) {
   
}
))

BTW2. you mentioned that you use passport-saml: 2.0.1. Consider upgrading to 3.1.2 due xmldom (one of the dependencies) related security issue which makes it possible to bypass authentication.

commented

@srd90, we have tried to upgrade to 3.1.2 for the xmldom security update you mention, but we have run into this issue:
#637

commented

@nagarajanceg just one random side note:
based on code snippet that you posted to this bug report (quote from report):

saml: {
    path: process.env.SAML_PATH ,
    entryPoint: process.env.SAML_ENTRY_POINT || 'https://login.microsoftonline.com/tenant/saml2',
    issuer: 'app id',
    cert: process.env.SAML_CERT,
    callbackUrl: "https://application_url/login/callback",
    logoutUrl: 'https://login.microsoftonline.com/tenant/saml2',
}

you have not enabled audience validation meaning that your service is/would be open to authentication bypass vulnerability. If someone replays against your service an authnresponse which was originally sent to some other SP which uses same IdP as your service and if/when IdP uses same key to sign responses to all SPs then your service would consume replayed message as validly signed authentication response (even though actual audience was some other SP). For more information see #137 (comment) and passport-saml documentation ( @ 04ee9415).

Also in the future consider providing proper title to bug reports. Now title says just "[BUG]" (and this particular bug report you provided was more like a question which could have been asked at discussions section).

(ping @trmpowell I'm not quite sure whether your answer meant that you are working on same project/codebase but if you are then you ought to be notified also about aforementioned audience validation stuff)