【问题标题】:SimpleSMLphp Custom Module Authentication Triggering TwiceSimpleSMLphp 自定义模块身份验证触发两次
【发布时间】:2020-04-15 19:51:18
【问题描述】:

背景:我正在尝试为用户设置单点登录 (SSO),以便他们可以对我的网站进行身份验证,而不必再次对我们的第三方 MSP 网站进行身份验证。理想情况下,用户单击我们网站上的链接并被带到已经登录并登陆仪表板的第三方网站(如果帐户不存在,则在此步骤中创建)。我们没有使用 SAML 作为安全功能进行身份验证,因此我们需要 SAML 代码的只是生成 cookie,以防止用户在访问我们供应商的站点时必须再次登录。此第三方 MSP 不支持通过 API 或 Web 服务进行身份验证,因此我的任务是实施 SAML,这是他们唯一支持的 SSO 方法。我是 SAML(但不是 PHP 或开发)的新手,并且一直在学习。我被告知它将支持上述目标。

我最初尝试使用 LDAP 作为身份验证源,因为这是我用于对我的网站进行身份验证的方式,但这导致我被定向到登录页面,而没有明显的方法可以将参数传递给 SimpleSAMLphp 来告诉它“用户已经通过身份验证,我需要你做的就是给我有效的 cookie,这样我就可以通过第三方网站的身份验证检查”。

所以我转而编写自定义身份验证模块。我打开了 SimpleSAMLphp 的 GitHub,并使用“UserPassBase”类作为示例来创建我自己的身份验证模块,该模块继承自“Source”类。因为我不需要再次针对 LDAP 重新验证用户,因为他们已经登录到我们的网站,所以我创建了一个简单的“验证”函数,它只设置 $state['Attributes'] 数组。

这是我的自定义模块的代码:

<?php
namespace SimpleSAML\Module\productauth\Auth\Source;
use SimpleSAML\Auth;

/**
        Author: Joey
        Class developed to be used as a custom authentication module for simpleSAMLphp. This class will take an existing session from a product website and use it to create a SAML session and redirect to a website.
**/
class ProductAuth extends \SimpleSAML\Auth\Source {
        const STAGEID = '\SimpleSAML\Module\productauth\Auth\ProductAuth.state';
        const AUTHID = '\SimpleSAML\Module\productauth\Auth\ProductAuth.AuthId';

        private $user;

        public function __construct($info, $config) { // parameters aren't used, just filler from base class
                $info = array("AuthId" => "productauth");
                parent::__construct($info, $config);
        }

        public function login($user, $redirectURL) {
                $this->user = $user; // normally I'd set this in the constructor, but the overload has my hands tied as far as function definitions go
                $this->initLogin($redirectURL); // calls authenticate function and then, if no exceptions, parent::loginCompleted which redirects to the given URL
        }

        public function authenticate(&$state) { // called by parent::initLogin
                $state[self::AUTHID] = $this->authId;
                $state['Attributes'] = [
                        'uid' => [$this->user->uid],
                        'givenName' => [$this->user->givenName],
                        'sn' => [$this->user->sn],
                        'mail' => [$this->user->mail]
                ];
                $id = Auth\State::saveState($state, self::STAGEID);
        }
}
?>

我从我网站上的控制器类调用它:

private function goToTrainingSite() {
                require_once("../third-party-libs/simplesamlphp/_include.php");
                global $TRAINING_URL;
                $user = $_SESSION['subject']->user;
                $samlObj = new SimpleSAML\Module\productauth\Auth\Source\ProductAuth(array(), array());
                $samlObj->login($user, $TRAINING_URL);
        }

我模仿了“UserPassBase”类 (https://github.com/simplesamlphp/simplesamlphp/blob/master/modules/core/lib/Auth/UserPassBase.php) 的流程,但似乎尽管我的所有身份验证都在工作并设置了 SimpleSAMLAuth cookie,但当“Source”类中的 parent::loginCompleted 函数 (@ 987654322@) 运行,它将我重定向到第三方站点。然后我在日志中看到以下内容:

SAML2.0 - IdP.SSOService:传入的身份验证请求:[已编辑数据]

会话:“productauth”无效,因为我们未通过身份验证。

我已经尝试了 3 天来弄清楚为什么尽管设置 SimpleSAML 会话 cookie 并完成了成功的身份验证,但在收到来自 SP 的身份验证请求后,我的 SimpleSAMLphp 代码只是假装不知道完成身份验证并尝试再次进行身份验证...但是因为它不是从我的代码中调用的,所以它无权访问 $user 变量,该变量包含我在用户进行身份验证时需要放置在用户身上的所有属性到这个第三方网站。似乎当它收到身份验证请求时,我的 SimpleSAMLphp 安装会启动一个新会话并尝试全新的身份验证。

我已经深入研究了 SimpleSAMLphp 的大量代码并试图了解发生了什么,但似乎没有合理的方法通过从 PHP 代码调用身份验证源并能够跳过 SP 来进行身份验证- 发起的认证。我试过了:

  • 使用 SimpleSAML API (https://simplesamlphp.org/docs/stable/simplesamlphp-sp-api) 调用我的身份验证源,但似乎无法传递我需要属性的 $user 变量。
  • 尝试在“Session”类检查有效会话时加载 cookie...但我的代码启动的成功身份验证会话中的 cookie 似乎消失了,无处可寻。李>

【问题讨论】:

    标签: php single-sign-on saml simplesamlphp


    【解决方案1】:

    我决定不再专注于尝试获取 $user 变量和第二次身份验证所需的数据,而是专注于为什么会发生第二次身份验证。我查看了 cookie 并考虑了如何检索数据,并做出正确的预感,即我们的应用程序的自定义会话处理程序可能因 SimpleSAMLphp 无法识别第一次身份验证而出错。我们的自定义会话处理程序将我们的会话存储在数据库中,但 SimpleSAMLphp 期望使用默认的 PHP 会话处理程序来管理其会话。因此,我的第一个身份验证被发送到数据库,当 SimpleSAMLphp 开始寻找它通常存储 PHP 会话的位置时,它没有看到它并认为它需要从头开始另一个身份验证会话。

    使用SimpleSAMLphp's documentation for service providers 和我自己的大量调试,我更改了控制器中的函数,如下所示:

    private function goToTrainingSite() {
            require_once ("../third-party-libs/simplesamlphp/_include.php");
            global $TRAINING_URL;
            $joeySiteSession = $_SESSION;
            $user = $_SESSION ['subject']->user;  // save user to variable before the Joey's Site session is closed
            session_write_close (); // close Joey's Site session to allow SimpleSAMLphp session to open
            session_set_save_handler ( new SessionHandler (), true ); // stop using SessionHandlerJoey and use default PHP handler for SimpleSAMLphp
            $samlObj = new SimpleSAML\Module\joeysiteauth\Auth\Source\JoeySiteAuth ( array (), array () );
            $samlObj->login ( $user, function () { return;} ); // use custom authentication module to set atttributes and everything SimpleSAMLphp needs in the auth session/cookie         
            $session = \SimpleSAML\Session::getSessionFromRequest (); 
            $session->cleanup (); // must call this function when we are done with SimpleSAMLphp session and intend to use our Joey's Site session again
            session_write_close (); 
            $_SESSION = $joeySiteSession; // restore Joey's Site session
            header ( "Location: {$TRAINING_URL}" );
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-02
      • 2020-07-27
      • 2020-04-01
      • 2022-12-10
      • 2020-04-08
      • 2014-05-05
      • 2021-01-09
      • 2018-09-26
      相关资源
      最近更新 更多