otevrenamesta/simplesamlphp-saml2-eidas

围绕simplesamlphp/saml2的PHP库,为eIDAS相关集成提供辅助工具

v1.0 2019-12-02 15:56 UTC

This package is auto-updated.

Last update: 2024-09-11 00:35:16 UTC


README

GitHub license Build Status codecov Scrutinizer Code Quality

关于

这个库旨在简化需要eIDAS SAML集成的PHP应用程序的开发,特别是基于基于simplesamlphp/saml2库的用户身份验证,该库是SimpleSAMLphp项目的基础,但对于通常的应用程序来说过于庞大,难以集成

要求

  • PHP >= 7.2(这是由底层的simplesamlphp/saml2库提供的)
  • PHP扩展DOM、Zlib、OpenSSL

用法

  • (1) 了解底层库 simplesamlphp/saml2
  • (2) 使用composer安装库 composer require otevrenamesta/simplesamlphp-saml2-eidas
  • (3) 实现你的容器(重要方法包括generateId以及根据你的环境,文件存储方法和日志接口)
// sample generic container implementation

use SAML2\Compat\AbstractContainer;
use Psr\Log\LoggerInterface;
use Psr\Log\Test\TestLogger;

class CustomContainerInterface extends AbstractContainer {
    public function getLogger(): LoggerInterface
    {
        return new TestLogger();
    }
                               
    public function generateId(): string
    {
        return uniqid('_');
    }
                               
    public function debugMessage($message, string $type): void
    {
        $this->getLogger()->debug($message, [$type]);
    }
                               
    public function redirect(string $url, array $data = []): void
    {
        // provide your own redirect method with GET QUERY data
    }
                               
    public function postRedirect(string $url, array $data = []): void
    {
        // provide your own code to do redirect with POST data
    }
                               
    public function getTempDir(): string
    {
        // very simple solution
        return sys_get_temp_dir();
    }
                               
    public function writeFile(string $filename, string $data, int $mode = null): void
    {
        // put contents into file in temporary directory
        $file = tempnam($this->getTempDir(), $filename);
        $handle = fopen($file, $mode === null ? 0600 : $mode);
        fwrite($handle, $data);
        fclose($handle);
    }
}
  • (4.a) 使用此库创建带有eIDAS RequestedAttributes和SPType的签名AuthRequest
use OMSAML2\OMSAML2;
use OMSAML2\SamlpExtensions;
use SAML2\Constants;

OMSAML2::setOwnPrivateKeyData("-----BEGIN RSA PRIVATE KEY----- pem key data -----END RSA PRIVATE KEY-----");
OMSAML2::setOwnCertificatePublicKey("-----BEGIN CERTIFICATE----- pem certificate data -----END CERTIFICATE-----");
OMSAML2::setIdPMetadataUrl("https://tnia.eidentita.cz/FPSTS/FederationMetadata/2007-06/FederationMetadata.xml");

$request = OMSAML2::generateAuthRequest(
            new CustomContainerInterface(),
            'https://sep.example.com', // SeP issuer value
            'https://sep.example.com/assertion_consumer_service', // SeP ACS URL, url to redirect user after authentication
            OMSAML2::extractSSOLoginUrls()[Constants::BINDING_HTTP_REDIRECT], // retrieve SSO redirect url from IdP metadata 
            OMSAML2::LOA_LOW, // require minimal level-of-assurance (LoA), ie. authentication methods, that do not guarantee user identity exists in real world
            'minimum'
        );

// create eIDAS samlp:Extensions with 
$extensions = new SamlpExtensions();
// single RequestedAttribute Name="email" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="false" without AttributeValue
$extensions->addRequestedAttributeParams('email');
// single RequestedAttribute Name="http://www.stork.gov.eu/1.0/age" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" isRequired="true" without AttributeValue
$extensions->addRequestedAttributeParams('http://www.stork.gov.eu/1.0/age', 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri', true);
// you do not have to do this, public is default type of SeP within this library, allowed values are 'public' or 'private'
$extensions->setSPType('public');

// sign the samlp:AuthnRequest using private key set  in the beginning
$request_signed = OMSAML2::signDocument($extensions->toXML($request->toUnsignedXML()));
// generate final user redirect URL with embedded SAMLRequest containing signed AuthnRequest
$sso_redirect_url = OMSAML2::getSSORedirectUrl($request_signed);
// example result of this action is url like this:
// https://tnia.eidentita.cz/FPSTS/saml2/basic?SAMLRequest=1ZhtU%2BI6FMff%2BymY%2BtKBtMhjR9gpIAgCYnm4ypud0KZtpE1qkkLx09%2B0PIjuenXv7s6uM844PT3n5JeTk39SLr7EgZ9ZIcYxJTVFy6nKl%2FrJBYeBH%2BpGJDxioscIcZGRfoTr6YuaEjGiU8gx1wkMENeFpY%2BNQV%2FP51Q9ZFRQi%2FrKUch%2FR0DOERMSQMl0WzXla9FGRW2hFh3t3NGUzGxPJ32lB%2BcR6hIuIBHSpGrVrJbPqvmJVtDVqvybK5mWBMYEijTKEyLkOgCCYJhD2EZEYAFz1hNoj8aTMUj48mAh2SwlY%2BxRmpTwKEBsjNgKW2hq9p8zcRTmUAyD0Ec5iwbgwP%2FV2kV95dswpZ6WUk%2BhWf2NBBfg2OnC5voYuxI%2FYmhXQ5tvR5ex6%2FU6tz7PUeaCvKqqQK0C6WNz7J4q9ZNMZh%2BO7C5xaJqtCQkl2II%2BfkprMkDCo3bG8F3KsPCCN3JrQFOT3FkUW1lLK5BTBSQjPI%2BRIn44m1rYk2YDytAp4zDLPZgvlrZ5k6wmchBDxEKZqdmtKaeveiGdzoRBwh3KAv7y8V2EF8VCZIV8GiI7y%2FczkRg%2FlvC7FboA3zK2sCtb8gcrJctweqjPc5YZ9CNUb%2BYr7aezZbfs%2Bi1RHZad3qyydorXnp8fmZFlDy7pw3DWEPOgUEuJjoNTw6HU28dXPXNY3m0EPveGdwGfmP60nS9fgvNZ%2BQ6dG2sKqA%2BqgIjBw6x7NkePTbhwy0HQWore7Ea4jnnFz9TxvAVjNS7dDx9KMXDd8rCjRVcjz5jdr%2BebASuu2pVLc1OMbNskXqft3JubsluZPWLA85vuVX45Lrhq0Mj742p7OLuf3Xi9cWU%2BabnmZn6vGcbYwuGN02CDXmkuunewMyPanagsL9kmnjTu7zyGmw21OhJMvbGK%2Fcb5w%2FXUfpoUr8Z24QY9hIulof0DkRaXOl7BNUrjzm2MjTh%2BKoTqukr60bRBysOGWer1wxbE4fVVxyFWMdaum6umNbn0V%2BSxbziV2%2FnqCfeM6Zq1W2zkUGqui41O17FKZ3HR8JaN6ePtZtSDLV65mlO3VjuU%2FqjWJy%2BN9Z0a74QY2aksS30SKBaZJg1CyDBPlC7ABAdRsBedY7%2BmL0VKrnh913FSByHPoYjRUIpiBPrUAD5d75Tou5Hbd29w7CEvY4FIotZ8p1zpQIdGfz1sEiQ3zz5Gkqce%2Bng02YTo%2F6UIo4WPrQtwnGmf95ldCIYXkUA%2Fx%2FltvsxQHm8vNjYXlC1zLl0lieQBC6CLlAzmSSxmyK4pDvS5NCWRbSkZULxzXMqxEmvWSZ31iOFEIH6CyKIREWzTpDaSuwgz4f05wNelh4eVAul%2BgH4o7wOUgGbEpHwJw7YZ4vzzALdhgP1NkuLzMHfwCpFPgtyC4s938Xe3GRpA7P9lTJgbLrqRHwC%2FnGuPdaDZnm5aZS%2FNr17szd9O45e3yCj9100%2FBRz8G%2Bb%2B4TXhloeCBPr4u0TejjGXN0GtBHbmDbB8iAMun0kULD4XsZAH8OfhFQwmBwrE9t%2FDvHmHOfQoQX%2B6MT6%2B%2B3xo%2FU6FflNH%2BOEO%2B3xNPZiOf%2Byon%2FwL&param=2
  • (4.b) 使用此库验证IdP元数据或SAMLResponse
use OMSAML2\OMSAML2;
use SAML2\DOMDocumentFactory;
use SAML2\Response;

// validate SAMLResponse
$responseData = base64_decode($_POST['SAMLResponse'], true);
$response_dom = DOMDocumentFactory::fromString($responseData);
$response = new Response($response_dom->documentElement);

OMSAML2::validateSignature(OMSAML2::getPublicKeyFromCertificate("https://nia.otevrenamesta.cz/tnia.crt"), $response);

// validate IdP Metadata signature by pinning certificate
OMSAML2::setIdPMetadataUrl("https://tnia.eidentita.cz/FPSTS/FederationMetadata/2007-06/FederationMetadata.xml");
OMSAML2::validateSignature(OMSAML2::getPublicKeyFromCertificate("https://nia.otevrenamesta.cz/tnia.crt"));

还有更多,如果你需要灵感,请查看测试

免责声明

此库是在针对捷克共和国IdP NIA开发和测试的,可能与其他IdP或eIDAS节点不兼容

鸣谢

此库由Otevřená Města z.s.开发