NameIdDecryptionTransformer::setIdentityProvider()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\SAML2\Assertion\Transformer;
6
7
use Exception;
8
use Psr\Log\LoggerInterface;
9
use SimpleSAML\SAML2\Assert\Assert;
10
use SimpleSAML\SAML2\Assertion\Exception\NotDecryptedException;
11
use SimpleSAML\SAML2\Certificate\PrivateKeyLoader;
12
use SimpleSAML\SAML2\Configuration\IdentityProvider;
13
use SimpleSAML\SAML2\Configuration\IdentityProviderAware;
14
use SimpleSAML\SAML2\Configuration\ServiceProvider;
15
use SimpleSAML\SAML2\Configuration\ServiceProviderAware;
16
use SimpleSAML\SAML2\XML\saml\Assertion;
17
use SimpleSAML\SAML2\XML\saml\EncryptedID;
18
use SimpleSAML\SAML2\XML\saml\IdentifierInterface;
19
use SimpleSAML\SAML2\XML\saml\Subject;
20
21
use function get_class;
22
use function sprintf;
23
24
final class NameIdDecryptionTransformer implements
25
    TransformerInterface,
26
    IdentityProviderAware,
27
    ServiceProviderAware
28
{
29
    /**
30
     * @var \SimpleSAML\SAML2\Configuration\IdentityProvider
31
     */
32
    private IdentityProvider $identityProvider;
33
34
    /**
35
     * @var \SimpleSAML\SAML2\Configuration\ServiceProvider
36
     */
37
    private ServiceProvider $serviceProvider;
38
39
40
    /**
41
     * Constructor for NameIdDecryptionTransformer
42
     *
43
     * @param \Psr\Log\LoggerInterface $logger
44
     * @param \SimpleSAML\SAML2\Certificate\PrivateKeyLoader $privateKeyLoader
45
     */
46
    public function __construct(
47
        private LoggerInterface $logger,
48
        private PrivateKeyLoader $privateKeyLoader,
49
    ) {
50
        $this->logger = $logger;
51
        $this->privateKeyLoader = $privateKeyLoader;
52
    }
53
54
55
    /**
56
     * @param \SimpleSAML\SAML2\XML\saml\Assertion $assertion
57
     * @throws \Exception
58
     * @return \SimpleSAML\SAML2\XML\saml\Assertion
59
     */
60
    public function transform(Assertion $assertion): Assertion
61
    {
62
        $subject = $assertion->getSubject();
63
        if ($subject === null) {
64
            return $assertion;
65
        }
66
67
        $identifier = $subject->getIdentifier();
68
        if (!($identifier instanceof EncryptedID)) {
69
            return $assertion;
70
        }
71
72
        $decryptionKeys  = $this->privateKeyLoader->loadDecryptionKeys($this->identityProvider, $this->serviceProvider);
73
74
        $decrypted = null;
75
        foreach ($decryptionKeys as $index => $key) {
76
            try {
77
                $decrypted = $identifier->decrypt($key);
78
                $this->logger->debug(sprintf('Decrypted assertion NameId with key "#%d"', $index));
79
                break;
80
            } catch (Exception $e) {
81
                $this->logger->debug(sprintf(
82
                    'Decrypting assertion NameId with key "#%d" failed, "%s" thrown: "%s"',
83
                    $index,
84
                    get_class($e),
85
                    $e->getMessage(),
86
                ));
87
            }
88
        }
89
90
        if ($decrypted === null) {
91
            throw new NotDecryptedException(
92
                'Could not decrypt the assertion NameId with the configured keys, see the debug log for information',
93
            );
94
        }
95
        Assert::implementsInterface($decrypted, IdentifierInterface::class);
96
97
        return new Assertion(
98
            $assertion->getIssuer(),
99
            $assertion->getIssueInstant(),
100
            $assertion->getId(),
101
            new Subject($decrypted, $subject->getSubjectConfirmation()),
0 ignored issues
show
Bug introduced by
$decrypted of type SimpleSAML\XML\SerializableElementInterface is incompatible with the type SimpleSAML\SAML2\XML\saml\IdentifierInterface|null expected by parameter $identifier of SimpleSAML\SAML2\XML\saml\Subject::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

101
            new Subject(/** @scrutinizer ignore-type */ $decrypted, $subject->getSubjectConfirmation()),
Loading history...
102
            $assertion->getConditions(),
103
            $assertion->getStatements(),
104
        );
105
    }
106
107
108
    /**
109
     * @param \SimpleSAML\SAML2\Configuration\IdentityProvider $identityProvider
110
     */
111
    public function setIdentityProvider(IdentityProvider $identityProvider): void
112
    {
113
        $this->identityProvider = $identityProvider;
114
    }
115
116
117
    /**
118
     * @param \SimpleSAML\SAML2\Configuration\ServiceProvider $serviceProvider
119
     */
120
    public function setServiceProvider(ServiceProvider $serviceProvider): void
121
    {
122
        $this->serviceProvider = $serviceProvider;
123
    }
124
}
125