OpenID 工具库

dev-master 2024-09-19 11:24 UTC

This package is auto-updated.

Last update: 2024-09-19 11:24:38 UTC


README

警告:此库正处于积极开发中,不应在生产环境中使用!

此库提供了一些在处理 OpenID 规范族时可能有用的通用工具。

安装

可以使用 Composer 安装此库

composer require simplesamlphp/openid

OpenID 联邦

库的初始功能围绕 OpenID 联邦规范。要使用它,请创建 \SimpleSAML\OpenID\Federation 类的一个实例

<?php

declare(strict_types=1);

namespace Your\Super\App;

use SimpleSAML\OpenID\Algorithms\SignatureAlgorithmBag;
use SimpleSAML\OpenID\Algorithms\SignatureAlgorithmEnum;
use SimpleSAML\OpenID\SupportedAlgorithms;
use Psr\SimpleCache\CacheInterface;
use Psr\Log\LoggerInterface;
use SimpleSAML\OpenID\Federation;
use Symfony\Component\HttpFoundation\Response;

class Test
{
    public function __construct(
        protected CacheInterface $cache,
        protected LoggerInterface $logger,
    ) {
    }
    
    public function __invoke(): Response
    {
        // Instantiation example by using default options.
        // * 'RS256' as supported algorithm
        // * no caching support (not recommended for production environment)
        // * no logging support
        $federationTools = new Federation();
        
        // Instantiation example by injecting some of the dependencies 
        // Define the supported signature algorithms:
        $supportedAlgorithms = new SupportedAlgorithms(
            new SignatureAlgorithmBag(
                SignatureAlgorithmEnum::RS256,
                // ... if needed, add other supported signature algorithms here
            )
        );
        
        // Define the maximum cache TTL for federation artifacts. This will be used together with 'exp'
        // claim to resolve the maximum cache time for trust chains, entity statements, etc.
        $maxCacheDuration = new DateInterval('PT6H');
        
        // Instantiate by injecting own options / dependencies:
        $federationTools = new Federation(
            supportedAlgorithms: $supportedAlgorithms,
            maxCacheDuration: $maxCacheDuration,
            cache: $this->cache, // \Psr\SimpleCache\CacheInterface
            logger: $this->logger, // \Psr\Log\LoggerInterface
        );
        
        // Continue with using available tools ...
        
        return new Response();
    }
}

信任链解析器

一旦实例化了 \SimpleSAML\OpenID\Federation,您就可以继续使用可用的工具。我们将首先查看的是信任链解析器工具。此工具可用于尝试解决给定叶实体(主题)和受信任锚点的(最短)信任链

// ... 

try {
    /** @var \SimpleSAML\OpenID\Federation $federationTools */
    /** @var \SimpleSAML\OpenID\Federation\TrustChain $trustChain */
    $trustChain = $federationTools->trustChainResolver()->for(
        'https://leaf-entity-id.example.org/', // Trust chain subject (leaf entity).
        [
            'https://trust-achor-id.example.org/', // List of valid trust anchors.
        ],
    );
} catch (\Throwable $exception) {
    $this->loggerService->error('Could not resolve trust chain: ' . $exception->getMessage())
    return;
}

如果成功解决了信任链,这将返回一个 \SimpleSAML\OpenID\Federation\TrustChain 实例。否则,将抛出异常。

一旦您有了信任链,您可以尝试获取特定实体类型的解析元数据。解析元数据意味着所有中间的元数据策略都已成功应用。这里有一个尝试获取 OpenID RP 元数据的示例,它将返回一个数组(如果给定实体类型没有元数据则返回 null)

// ... 

$entityType = \SimpleSAML\OpenID\Codebooks\EntityTypesEnum::OpenIdRelyingParty;

try {
    /** @var \SimpleSAML\OpenID\Federation\TrustChain $trustChain */
    $metadata = $trustChain->getResolvedMetadata($entityType);
} catch (\Throwable $exception) {
    $this->loggerService->error(
        sprintf(
            'Error resolving metadata for entity type %s. Error: %s.',
            $entityType->value,
            $exception->getMessage(),        
        ),   
    );
    return;
}

if (is_null($metadata)) {
    $this->loggerService->error(
        sprintf(
            'No metadata available for entity type %s.',
            $entityType->value,      
        ),
    );
    return;
}

如果获取元数据导致异常,则认为元数据无效,应予以丢弃。

签名附加验证

整个信任链(每个实体声明)已使用配置/从属声明中的 JWKS 声明的公钥进行验证。根据规范建议,您还可以使用您以某种安全方式获得的信任锚点公钥(JWKS)验证信任链配置声明的签名(这样在获取信任锚点配置声明时不仅依赖于 TLS 保护)

// ... 

// Get entity statement for the resolved Trust Anchor:
/** @var \SimpleSAML\OpenID\Federation\TrustChain $trustChain */
$trustAnchorConfigurationStatement = $trustChain->getResolvedTrustAnchor();
// Get data that you need to prepare appropriate public keys, for example, the entity ID:
$trustAnchorEntityId = $trustAnchorConfigurationStatement->getIssuer();

// Prepare JWKS array containing Trust Anchor public keys that you have acquired in secure out-of-band way ...
/** @var array $trustAnchorJwks */

try {    
    $trustAnchorConfigurationStatement->verifyWithKeySet($trustAnchorJwks);
} catch (\Throwable $exception) {
    $this->loggerService->error('Could not verify trust anchor configuration statement signature: ' .
    $exception->getMessage());
    return;
}