使用passport-saml:req.logout()或Strategy.logout()或两者注销?

时间:2014-08-12 18:00:33

标签: node.js passport.js saml-2.0

我对使用passport-saml进行身份验证时注销用户的正确方法有疑问。

带有passport-saml的示例脚本显示如下:

app.get('/logout', function(req, res){
  req.logout();
  res.redirect('/');
});

据我所知,这将结束本地护照会话,但它似乎没有向SAML IdP发送注销请求。当用户进行另一次登录时,它会重定向到IdP,但会立即重新定向到经过身份验证的用户。有没有办法使用IdP注销,以便用户在登录我的网站时必须再次输入密码?我见过其他使用我们IdP的网站都这样做,所以我认为这是可能的。

我在passport-saml代码中注意到在passport-saml策略对象上有一个logout()方法,req.logout()似乎没有调用它。所以我尝试将代码切换到:

app.get('/logout', function(req, res) {
    //strategy is a ref to passport-saml Strategy instance 
    strategy.logout(req, function(){
        req.logout();
        res.redirect('/');
    });
});

但是我在XMLNode.js中深深地得到了这个错误

Error: Could not create any elements with: [object Object]
   at XMLElement.module.exports.XMLNode.element (/.../node_modules/passport-saml/node_modules/xmlbuilder/lib/XMLNode.js:74:15)
   at XMLElement.module.exports.XMLNode.element (/.../node_modules/passport-saml/node_modules/xmlbuilder/lib/XMLNode.js:54:25)
   at XMLElement.module.exports.XMLNode.element (/.../node_modules/passport-saml/node_modules/xmlbuilder/lib/XMLNode.js:54:25)
   at new XMLBuilder (/.../node_modules/passport-saml/node_modules/xmlbuilder/lib/XMLBuilder.js:27:19)
   at Object.module.exports.create (/.../node_modules/passport-saml/node_modules/xmlbuilder/lib/index.js:11:12)
   at SAML.generateLogoutRequest (/.../node_modules/passport-saml/lib/passport-saml/saml.js:169:21)

我没有正确地调用此方法吗?或者我不应该直接调用此方法并调用其他方法吗?

我在generateLogoutRequest()中看到它指的是req.user上的两个我不确定的属性:

  'saml:NameID' : {
    '@Format': req.user.nameIDFormat,
    '#text': req.user.nameID
  }

如果这些属性不存在,会导致此错误吗?如果是这样,我想我可能需要确保将这些属性添加到从验证回调函数返回的用户对象中?

感谢任何人可能提供的任何帮助。

1 个答案:

答案 0 :(得分:7)

是将nameIDFormat和nameID添加到用户将解决问题。

  1. 要启用注销,您应在策略中配置logoutURL选项
  2. logoutUrl: 'http://example.org/simplesaml/saml2/idp/SingleLogoutService.php',

    策略中的注销方法实际上并不发送任何请求。使用请求作为参数调用回调函数。

    启动注销过程:

    passport.logoutSaml = function(req, res) {
        //Here add the nameID and nameIDFormat to the user if you stored it someplace.
        req.user.nameID = req.user.saml.nameID;
        req.user.nameIDFormat = req.user.saml.nameIDFormat;
    
    
        samlStrategy.logout(req, function(err, request){
            if(!err){
                //redirect to the IdP Logout URL
                res.redirect(request);
            }
        });
    };
    

    编辑:nameId和nameIdFormat必须在成功登录时保存在某处

    var samlStrategy = new SamlStrategy(
      {
        callbackUrl: 'https://mydomain/auth/saml/callback',
        entryPoint: 'https://authprovider/endpoint',
        logoutUrl: 'https://authprovider/logoutEndPoint',
        issuer: 'passport-saml'
      },
      function(profile, done) {
    
          //Here save the nameId and nameIDFormat somewhere
          user.saml = {};
          user.saml.nameID = profile.nameID;
          user.saml.nameIDFormat = profile.nameIDFormat;
    
          //Do save
    
          });
      });
    
    1. 您还必须为注销回调创建一个终点:
    2. 应在IdP配置中的SP元数据中配置此URL。注销完成后,IdP将重定向到该URL。

      在您的路线中:

      app.post('/auth/saml/logout/callback', passport.logoutSamlCallback);
      

      在护照配置中:

      passport.logoutSamlCallback = function(req, res){
          req.logout();
          res.redirect('/');
      }