使用 passport-saml 注销:req.logout() 或 Strategy.logout(),或两者兼而有之?

Posted

技术标签:

【中文标题】使用 passport-saml 注销:req.logout() 或 Strategy.logout(),或两者兼而有之?【英文标题】:Logging out using passport-saml: req.logout() or Strategy.logout(), or both? 【发布时间】:2014-10-05 22:07:55 【问题描述】:

我有一个关于在使用 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】:

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

    要启用注销,您应该在策略中配置 logoutURL 选项

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

      );
  );
    您还必须为注销回调创建一个端点:

应在 IdP 配置的 SP 元数据中配置此 URL。注销完成后,IdP 将重定向到该 URL。

在您的路线中:

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

在您的护照配置中:

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

【讨论】:

我在登录回发中没有它们!我在哪里可以找到 nameID 和 nameIDFormat?! @DaNeSh 你在策略回调的 profile 参数中有它 对我来说它适用于任何 nameIDFormat,它不应该为空! 这对我有用,但有人可以详细说明Strategylogout 函数实际上是做什么的吗?我在任何地方都找不到文档。我只能在req.logout() 上找到信息。 嗨@bpavot 你能提供一些链接吗,我无法让它工作?

以上是关于使用 passport-saml 注销:req.logout() 或 Strategy.logout(),或两者兼而有之?的主要内容,如果未能解决你的问题,请参考以下文章

如何用passport-saml修复SLO,它在第一次注销时有效,但在以后的注销中不起作用

WSO2IS + node.js passport-saml 集成错误

将大型 JSON 文件存储到 Oracle 数据库中

护照-saml 和 SAML 加密

PLSQL解析JSON,并保存到数据库

终极会员注销无法使用 WPML