首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ExpressJS/Passport-SAML单次注销直接重新登录

ExpressJS/Passport-SAML单次注销直接重新登录
EN

Stack Overflow用户
提问于 2019-12-05 19:38:37
回答 2查看 1.3K关注 0票数 0

目前,我正在开发NodeJS应用程序中的passport-saml实现。这样做的原因是让我们的客户能够连接到他们的AD FS系统并利用SingleSignOn(单点登录)。

因为我们还想提供注销功能,所以我正在研究这一逻辑。然而,我似乎不能让这个简单的功能工作。我已经用谷歌搜索了很多,尝试了很多变体和配置,但不幸的是,它不起作用。

我想给我们的客户提供同时由SP和IdP驱动的SingleLogOut的可能性。这是我的起点。在调试和开发过程中,我已经后退了一步,并试图杀死本地会话,但这似乎是不可能的。

以下是我为SAML配置的路由中的相关代码:

代码语言:javascript
复制
const isAuthenticated = (req, res, next) => {
    if (req.isAuthenticated()) {
      // User logged in, pass on to next middleware
      console.info('User authenticated');
      return next();
    }
    // User not logged in, redirect to login page
    console.info('User not authenticated');
    return res.redirect('/login');
  };

// GET-routes
  app.get('/',
    isAuthenticated,
    (req, res) => {
      res.send('Authenticated');
    });

  app.get('/login',
    passport.authenticate('saml', {
      successRedirect: '/',
      failureRedirect: '/login/fail',
    }));

  app.get('/logout',
    (req, res) => {
      passport._strategy('saml').logout(req, (err, url) => {
        return res.redirect(url);
      });
    });

// POST-routes
  app.post('/adfs/callback',
    (req, res, next) => {
      passport.authenticate('saml', (err, user) => {
        // If error occurred redirect to failure URL
        if (err) return res.redirect('/login/fail');
        // If no user could be found, redirect to failure URL
        if (!user) return res.redirect('/login/fail');
        // User found, handle registration of user on request
        req.logIn(user, (loginErr) => {
          if (loginErr) return res.status(400).send(err);
          // Request session set, put in store
          store.set(req.sessionID, req.session, (storeErr) => {
            if (storeErr) return res.status(400).send(storeErr);
            return res.redirect('/');
          });
        });
      })(req, res, next);
    });

  app.post('/logout/callback', (req, res) => {
    // Destroy session and cookie
    store.destroy(req.sessionID, async (err) => {
      req.logout();
      return res.redirect('/');
    });
  });

可以看出,我控制了会话存储的处理(设置和销毁会话,但如果这是不明智的,请建议)。实现的会话存储是MemoryStore (https://www.npmjs.com/package/memorystore)。

发生的情况是,当用户登录时,一切工作正常。然后,一个请求被发送到路由/logout,然后发生了一些事情,我可以看到会话发生了变化,会话ID以及passport-saml (nameID,sessionIndex)的相关参数也发生了变化,然后用户被重路由到“/”。

但是,该用户将被视为未通过身份验证,并重新路由到“/login”。有人会争辩说它就到此为止,因为必须重新输入凭据。情况并非如此,因为用户直接再次登录,而无需重新输入凭据,我不知道如何防止这种情况。

我真的希望任何人都知道发生了什么:)如果需要更多的信息,我很乐意听到。

EN

回答 2

Stack Overflow用户

发布于 2020-02-04 15:51:28

因此,经过大量的研究和调查,我确实找到了这个问题的解决方案。诀窍在于passport-saml包的定义,特别是authncontext参数。

因此,之前我将SamlStrategy选项定义为:

代码语言:javascript
复制
{
  // URL that should be configured inside the AD FS as return URL for authentication requests
  callbackUrl: `<URL>`,
  // URL on which the AD FS should be reached
  entryPoint: <URL>,
  // Identifier for the CIR-COO application in the AD FS
  issuer: <identifier>,
  identifierFormat: null,
  // CIR-COO private certificate
  privateCert: <private_cert_path>,
  // Identity Provider's public key
  cert: <cert_path>,
  authnContext: ["urn:federation:authentication:windows"],
  // AD FS signature hash algorithm with which the response is encrypted
  signatureAlgorithm: <algorithm>,
  // Single Log Out URL AD FS
  logoutUrl: <URL>,
  // Single Log Out callback URL
  logoutCallbackUrl: `<URL>`,
}

但经过大量研究后,我意识到这一点:windows选项是罪魁祸首,所以我将其更改为:

代码语言:javascript
复制
{
  // URL that should be configured inside the AD FS as return URL for authentication requests
  callbackUrl: `<URL>`,
  // URL on which the AD FS should be reached
  entryPoint: <URL>,
  // Identifier for the CIR-COO application in the AD FS
  issuer: <identifier>,
  identifierFormat: null,
  // CIR-COO private certificate
  privateCert: <private_cert_path>,
  // Identity Provider's public key
  cert: <cert_path>,
  authnContext: ["urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport",
    "urn:federation:authentication:windows"],
  // AD FS signature hash algorithm with which the response is encrypted
  signatureAlgorithm: <algorithm>,
  // Single Log Out URL AD FS
  logoutUrl: <URL>,
  // Single Log Out callback URL
  logoutCallbackUrl: `<URL>`,
},

这基本上意味着它不会检索默认登录到系统的用户的Windows凭据,从而重定向到ADFS服务器的登录屏幕。

票数 2
EN

Stack Overflow用户

发布于 2020-09-18 06:07:35

在会话设置中使用authnContext:"urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport“将在注销后再次显示用户名和密码页面。

注销已达到https://adfs-url/adfs/ls/?wa=wsignout1.0

重新登录后会创建一个新的session-id。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59194317

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档