fei/connect-client

Yoctu Connect Client - 服务提供商


README

GitHub licensecontinuousphpGitHub issues

Connect-Client 的作用是将 SAML 标准协议集成到您的应用程序中。

它将允许您使用单点登录 (SSO) 设备验证用户的身份验证,获取有关他的特定信息,并通过断言定义他的授权。

有关 SAML 标准协议的更多信息,请参阅 connect-idp 文档。

安装与先决条件

Connect-Client 需要 PHP 5.5 或更高版本,并且需要启用 mcrypt 扩展才能正确运行。

您需要使用 composer require fei/connect-client 将其集成到您的项目中。

集成

以下是一个示例,说明其工作原理(请参阅 /example 文件夹)

$metadata = new Metadata();

// Configure your metadata... (See next chapter)

$config = (new Config())
    ->setDefaultTargetPath('/resource.php')
    ->setLogoutTargetPath('/');

$connect = new Connect(new Saml($metadata), $config);
$connect->handleRequest($_SERVER['REQUEST_URI'], $_SERVER['REQUEST_METHOD'])->emit();

在创建一个新的 Metadata 实例并对其进行配置(参见图 设置您的元数据)后,创建一个新的 Connect 对象,该对象将接受两个参数

  • 一个新的 SAML 实例(允许您使用所有 SAML 方法),该实例将使用我们的元数据作为参数
  • 一个需要填写的 Config
    • defaultTargetPath 是用户将被重定向到的 URI,如果登录响应不包含一个
    • logoutTargetPath 将用于在用户注销后重定向用户

两个设置器的默认路径都是 /

最后,使用新 Connect 对象的 handleRequest 方法将验证(或不会验证)请求,并将用户重定向。

设置您的元数据

要填充 Metadata 实例,需要两个对象:身份提供者(Identity Provider)和服务提供商(Service Provider)描述符。

$metadata->setIdentityProvider(
    (new IdpSsoDescriptor())
        ->setID('http://idp.dev:8080')
        ->setWantAuthnRequestsSigned(true)
        ->addSingleSignOnService(
            new SingleSignOnService('http://idp.dev:8080/sso', SamlConstants::BINDING_SAML2_HTTP_REDIRECT)
        )
        ->addSingleLogoutService(
            new SingleLogoutService('http://idp.dev:8080/logout', SamlConstants::BINDING_SAML2_HTTP_POST)
        )
        ->addKeyDescriptor(new KeyDescriptor(
            KeyDescriptor::USE_SIGNING,
            X509Certificate::fromFile(__DIR__ . '/keys/idp/idp.crt')
        ))
)->setServiceProvider(
    (new SpSsoDescriptor())
        ->setID('http://' . $_SERVER['HTTP_HOST'])
        ->addAssertionConsumerService(
            new AssertionConsumerService(
                'http://' . $_SERVER['HTTP_HOST'] . '/acs.php',
                SamlConstants::BINDING_SAML2_HTTP_POST
            )
        )
        ->addSingleLogoutService(
            new SingleLogoutService(
                'http://' . $_SERVER['HTTP_HOST'] . '/logout.php',
                SamlConstants::BINDING_SAML2_HTTP_POST
            )
        )
        ->addKeyDescriptor(new KeyDescriptor(
            KeyDescriptor::USE_SIGNING,
            X509Certificate::fromFile(__DIR__ . '/keys/sp.crt')
        ))
        ->addKeyDescriptor(new KeyDescriptor(
            KeyDescriptor::USE_ENCRYPTION,
            X509Certificate::fromFile(__DIR__ . '/keys/sp.crt')
        )),
    file_get_contents(__DIR__ . '/keys/sp.pem')
);

身份提供者

如上图所示,我们需要使用几个指令填写一个 IdpSsoDescriptor

  • setID 设置与在 Connect-IDP 中创建的身份提供者相对应的唯一 ID

  • setWantAuthnRequestsSigned 接受一个布尔参数,并指示我们是否希望服务提供商为每个发送的 AuthnRequests 签名

  • addSingleSignOnService 接受一个单点登录服务作为参数,该参数有两个属性

    • 将处理请求的端点
    • 一个常量,用于描述请求将如何发送
  • addSingleLogoutServicesetSingleSignOnService 的工作方式相同,但使用单点登出服务,实例化一个端点和一个常量,用于指示请求将如何发送。

  • addKeyDescriptor 用于将证书与 SsoDescriptor 关联。这些证书将用于

    • 对 AuthnRequest 签名。
    • 解密断言。

    第一个 addKeyDescriptor 参数是包含在 KeyDescriptor 中的常量,描述了密钥的用法,第二个参数指示使用的证书的路径(通过 X509Certificate fromFile() 静态方法)

服务提供商

服务提供商设置器有两个参数

第一个参数SpSsoDescriptor第二个参数 是用于签名的 AuthnRequests 的私钥。

IdpSsoDescriptor 一样,SpSsoDescriptor 必须填写不同的属性

  • setID 设置与在 Connect-IDP 中创建的服务提供商相对应的唯一 ID
  • addAssertionConsumerService 接受一个断言消费者服务作为参数,该参数有两个属性
    • 第一个描述了一个端点,告诉客户端应该在何处监听IDP响应
    • 描述请求绑定的常量
  • addSingleLogoutService函数接受一个SingleLogoutService参数,它有两个属性
    • 描述客户端应监听以接收注销请求的端点
    • 描述请求绑定的常量(如上述示例中的POST)
  • addKeyDescriptor 用于将证书与 SsoDescriptor 关联。这些证书将用于
    • 对 AuthnRequest 签名。
    • 解密断言。

配置文件关联

您可以使用Config::registerProfileAssociation(callable $callback, $profileAssociationPath = '/connect/profile-association')注册配置文件关联回调,用于处理Connect-IDP提供的要求。回调必须有一个参数,该参数必须实现Fei\Service\Connect\Common\ProfileAssociation\Message\RequestMessageInterface接口,并必须返回一个Fei\Service\Connect\Common\ProfileAssociation\Message\ResponseMessageInterface实例

$config = (new Config())
    ->registerProfileAssociation(
        function (UsernamePasswordMessage $message) {
            if ($message->getUsername() != 'test' || $message->getPassword() != 'test') {
                throw new ProfileAssociationException('Profile not found', 400);
            }

            // Get allowed roles
            $roles = $message->getRoles();

            return (new ResponseMessage())->setRole('USER');
        },
        '/connect-profile-association'
    );

关联配置文件消息必须设置的角色由RequestMessage提供。如果返回的角色无效(不是由RequestMessage提供的),将抛出\LogicException异常。

如果您决定来自Connect-IDP的请求无效,您必须抛出一个带有消息和HTTP错误代码的Fei\Service\Connect\Common\ProfileAssociation\Exception\ProfileAssociationException实例,这些错误代码将被传递到Connect-IPD。

Connect-IPD与您的Connect客户端集成之间的所有消息都是加密的,因此您必须使用元数据配置指令设置IDP和您的服务提供商的私钥和公钥。

获取角色和本地用户名

如果客户端通过Client::getUser()方法提供的当前用户是配置文件关联的结果,您可以使用Client::getLocalUsername()Client::getRole()分别获取本地用户名和角色。

创建和验证令牌

使用Connect客户端,您可以创建和验证令牌。令牌是一种简单且安全的方式来在消耗Connect-Client服务的服务之间传输Connect授权。

创建令牌

// Create a Connect client instance
$connect = new Connect(new Saml($metadata), $config);

// Create a Token client instance
$client = new Token([Connect::OPTION_BASEURL => 'http://idp.dev:8080']);

// Create a Token
$token = $client->createToken($connect);

// Use the token...

验证令牌

// Create a Token client instance
$client = new Token([Connect::OPTION_BASEURL => 'http://idp.dev:8080']);

// Validate a Token

try {
    $user = $client->validate($token);
} catch (\Exception $e) {
    // Handle exception
}

链接到文档

示例

您可以通过文件夹examples轻松测试此客户端

在UserAdmin类中存在几个方法,以下表格中列出了所有方法