如何在基于SimpleSAMLphp的IdP中使用属性替换NameId的值?

3
我正在尝试设置SimpleSAMLphp IdP以向我的本地开发服务器发送SAML响应(在这种情况下是SP-initiated流程)。该IdP基于https://hub.docker.com/r/kristophjunge/test-saml-idp/的Docker镜像(我相信是版本1.15)。
整个设置是为了模拟我拥有的类似环境,其中G Suite IdP针对同一本地dev SP使用 - 最终尝试消除我的本地dev环境中的云依赖性,并用等效的SimpleSAMLphp替换它。
我遇到的问题是Google在其SAML响应中将NameId发送为:
<saml2:Subject> 
    <saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">a.b@c.com</saml2:NameID> 
                  <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> 
                     <saml2:SubjectConfirmationData InResponseTo="ONELOGIN_88ebd953f02c07d01b19714cd70133827ff1228e" NotOnOrAfter="2018-05-07T20:21:25.433Z" .                         Recipient="https://ee0138c4.ngrok.io/saml/?acs" /> 
</saml2:SubjectConfirmation>
</saml2:Subject>

但是SimpleSAMLphp发送的格式是这样的:
<saml:Subject> 
<saml:NameID SPNameQualifier="https://ee0138c4.ngrok.io/saml/metadata" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">_69d05500bd6e797de3674df0165facbfa0af699589</saml:NameID> 
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml:SubjectConfirmationData NotOnOrAfter="2018-05-09T17:47:57Z" Recipient="https://ee0138c4.ngrok.io/saml/?acs" InResponseTo="ONELOGIN_170bb7a0ff82100318ba498583e8e59cdae8607b" /> 
</saml:SubjectConfirmation> 
</saml:Subject>

我需要它作为属性值

a.b@c.com 而不是 _69d05500bd6e797de3674df0165facbfa0af699589

这样我就可以在我的SP逻辑中获取它,而不是发送一些随机数,我假设它是一个瞬态ID。

以下是我的配置:

要启动Docker容器:

docker run --name=testsamlidp_idp \
-p 8080:8080 \
-p 8443:8443 \
-e SIMPLESAMLPHP_SP_ENTITY_ID=https://ee0138c4.ngrok.io/saml/metadata \
-e SIMPLESAMLPHP_SP_ASSERTION_CONSUMER_SERVICE=https://ee0138c4.ngrok.io/saml/?acs  \
-e SIMPLESAMLPHP_SP_SINGLE_LOGOUT_SERVICE=http://localhost/simplesaml/module.php/saml/sp/saml2-logout.php/test-sp \
-v $(pwd)/users.php:/var/www/simplesamlphp/config/authsources.php \
-v $(pwd)/_saml20-sp-remote.php:/var/www/simplesamlphp/config/saml20-sp-remote.php \
-d kristophjunge/test-saml-idp

其中 users.php 包含:

<?php
$config = array(
    'admin' => array(
        'core:AdminPassword',
    ),
    'example-userpass' => array(
        'exampleauth:UserPass',
        'user1:user1pass' => array(
            'uid' => array('1'),
            'Groups' => array('group1','group2', 'group3'),
            'email' => 'user1@example.com',
        ),
        'user2:user2pass' => array(
            'uid' => array('2'),
            'Groups' => array('group2', 'group4', 'group5'),
            'email' => 'user2@example.com',
        ),
    ),
);

_saml20-sp-remote.php是:

<?php
/**
 * SAML 2.0 remote SP metadata for SimpleSAMLphp.
 *
 * See: https://simplesamlphp.org/docs/stable/simplesamlphp-reference-sp-remote
 */
$metadata[getenv('SIMPLESAMLPHP_SP_ENTITY_ID')] = array(

    'AssertionConsumerService' => getenv('SIMPLESAMLPHP_SP_ASSERTION_CONSUMER_SERVICE'),
    'SingleLogoutService' => getenv('SIMPLESAMLPHP_SP_SINGLE_LOGOUT_SERVICE'),

    #'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:persistent',
      #'simplesaml.nameidattribute' => 'email',
      #'simplesaml.attributes' => FALSE,

    'authproc.idp' => array(
            /* Filter to create a NameID with the "unspecified" format. */
            3 => array(
                'class' => 'saml:AtrributeNameID',
                'attribute' => 'email',
                'Format' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
            ),
        ),
        /* Select the unspecified NameID format by default. */
        'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified',

);

我猜测这可能是后一个文件的某种配置错误,也许有人可以帮助我找到问题的根源。
提前感谢您的帮助。

我不知道idp发起的流程是如何工作的,但你是否在向Google和你的测试IdP发送相同的SAML请求?如果你正在尝试弄清为什么两个IdP发送不同的响应,并且你没有同时向两者发送相同的请求,或者你没有在两者(或者都没有)上指定首选nameid格式,这并不无关紧要。 - Anthony
是的,这些请求是由相同的代码生成的,因此它们是相同的。实际上,我尝试在我的SP配置中指定NameIdFormat,但并没有产生任何区别。该SP基于Python开发。在这种情况下,IdP是基于Docker的PHP,在Google的情况下是一个云端的,无论他们内部使用什么。 - Simeon Leyzerzon
例如,如果您将 <samlp:NameIDPolicy Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" /> 添加到 SAML 请求中,您会在响应中得到什么? - Anthony
嗯,我没有手动将其添加到请求中的能力,因为我正在使用一个框架,但正如我所提到的,配置该框架以实现这个效果的设置似乎没有起作用。 - Simeon Leyzerzon
嘿,好运! - Anthony
显示剩余2条评论
1个回答

5
以下设置对我有效:

Docker启动脚本:

docker run --name=testsamlidp_idp \
-p 8080:8080 \
-p 8443:8443 \
-e SIMPLESAMLPHP_SP_ENTITY_ID=https://ee0138c4.ngrok.io/saml/metadata \
-e SIMPLESAMLPHP_SP_ASSERTION_CONSUMER_SERVICE=https://ee0138c4.ngrok.io/saml/?acs  \
-e SIMPLESAMLPHP_SP_SINGLE_LOGOUT_SERVICE=http://localhost/simplesaml/module.php/saml/sp/saml2-logout.php/test-sp \
-v $(pwd)/users.php:/var/www/simplesamlphp/config/authsources.php \
-v $(pwd)/saml20-idp-hosted.php:/var/www/simplesamlphp/metadata/saml20-idp-hosted.php \
-d kristophjunge/test-saml-idp

saml20-idp-hosted.php 在 Docker 容器中的路径为 /var/www/simplesamlphp/metadata/saml20-idp-hosted.php

<?php

$metadata['__DYNAMIC:1__'] = array(
    /*
     * The hostname of the server (VHOST) that will use this SAML entity.
     *
     * Can be '__DEFAULT__', to use this entry by default.
     */
    'host' => '__DEFAULT__',
    // X.509 key and certificate. Relative to the cert directory.
    'privatekey' => 'server.pem',
    'certificate' => 'server.crt',
    /*
     * Authentication source to use. Must be one that is configured in
     * 'config/authsources.php'.
     */
    'auth' => 'example-userpass',

  'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',


// refer to https://simplesamlphp.org/docs/stable/saml:nameid
'authproc' => array(
  3 => array(
          'class' => 'saml:AttributeNameID',
          'attribute' => 'email',
          'Format' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
      ),
  ),

);

NameIDFormatFormat都是必需的。 email应该对应于Docker容器中/var/www/simplesamlphp/config/authsources.php中指定的属性。

/var/www/simplesamlphp/config/authsources.php中的内容:

<?php
$config = array(
    'admin' => array(
        'core:AdminPassword',
    ),
    'example-userpass' => array(
        'exampleauth:UserPass',
        'user1:user1pass' => array(
            'uid' => array('1'),
            'Groups' => array('group1','group2', 'group3'),
            'email' => 'user1@example.com',
        ),
        'user2:user2pass' => array(
            'uid' => array('2'),
            'Groups' => array('group2', 'group4', 'group5'),
            'email' => 'user2@example.com',
        ),
    ),
);

大致的想法是有点记录下来,但是文档不适合新手,当然也欢迎对为什么事情是这样的原理进行讨论。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接