AuthenticatorAttestationResponseValidator::check()   A
last analyzed

Complexity

Conditions 4
Paths 1

Size

Total Lines 58
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 22
nc 1
nop 3
dl 0
loc 58
rs 9.568
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * The MIT License (MIT)
7
 *
8
 * Copyright (c) 2014-2018 Spomky-Labs
9
 *
10
 * This software may be modified and distributed under the terms
11
 * of the MIT license.  See the LICENSE file for details.
12
 */
13
14
namespace U2FAuthentication\Fido2;
15
16
use Assert\Assertion;
17
use U2FAuthentication\Fido2\AttestationStatement\AttestationStatementSupportManager;
18
19
class AuthenticatorAttestationResponseValidator
20
{
21
    private $attestationStatementSupportManager;
22
    private $credentialRepository;
23
24
    public function __construct(AttestationStatementSupportManager $attestationStatementSupportManager, CredentialRepository $credentialRepository)
25
    {
26
        $this->attestationStatementSupportManager = $attestationStatementSupportManager;
27
        $this->credentialRepository = $credentialRepository;
28
    }
29
30
    /**
31
     * @see https://www.w3.org/TR/webauthn/#registering-a-new-credential
32
     */
33
    public function check(AuthenticatorAttestationResponse $authenticatorAttestationResponse, PublicKeyCredentialCreationOptions $publicKeyCredentialCreationOptions, ?string $rpId = null): void
34
    {
35
        /** @see 7.1.1 */
36
        //Nothing to do
37
38
        /** @see 7.1.2 */
39
        $C = $authenticatorAttestationResponse->getClientDataJSON();
40
41
        /* @see 7.1.3 */
42
        Assertion::eq('webauthn.create', $C->getType(), 'The client data type is not "webauthn.create".');
43
44
        /* @see 7.1.4 */
45
        Assertion::true(hash_equals($publicKeyCredentialCreationOptions->getChallenge(), $C->getChallenge()), 'Invalid challenge.');
46
47
        /** @see 7.1.5 */
48
        $rpId = $rpId ?? $publicKeyCredentialCreationOptions->getRp()->getId();
49
        Assertion::notNull($rpId, 'No rpId.');
50
51
        $parsedRelyingPartyId = parse_url($C->getOrigin());
52
        Assertion::true(array_key_exists('host', $parsedRelyingPartyId) && \is_string($parsedRelyingPartyId['host']), 'Invalid origin rpId.');
53
54
        Assertion::false(null !== $rpId && $parsedRelyingPartyId['host'] !== $rpId, 'rpId mismatch.');
55
56
        /* @see 7.1.6 */
57
        Assertion::null($C->getTokenBinding(), 'Token binding not supported.');
58
59
        /** @see 7.1.7 */
60
        $getClientDataJSONHash = hash('sha256', $authenticatorAttestationResponse->getClientDataJSON()->getRawData(), true);
61
62
        /** @see 7.1.8 */
63
        $attestationObject = $authenticatorAttestationResponse->getAttestationObject();
64
65
        /** @see 7.1.9 */
66
        $rpIdHash = hash('sha256', $rpId, true);
67
        Assertion::true(hash_equals($rpIdHash, $attestationObject->getAuthData()->getRpIdHash()), 'rpId hash mismatch.');
68
69
        /* @see 7.1.10 */
70
        Assertion::true($attestationObject->getAuthData()->isUserPresent(), 'User was not present');
71
72
        /* @see 7.1.11 */
73
        Assertion::false(AuthenticatorSelectionCriteria::USER_VERIFICATION_REQUIREMENT_REQUIRED === $publicKeyCredentialCreationOptions->getAuthenticatorSelection()->getUserVerification() && !$attestationObject->getAuthData()->isUserVerified(), 'User authentication required.');
74
75
        /* @see 7.1.12 */
76
        Assertion::null($attestationObject->getAuthData()->getExtensions(), 'Extensions not supported.');
77
78
        /** @see 7.1.13 */
79
        $fmt = $attestationObject->getAttStmt()->getFmt();
80
        Assertion::true($this->attestationStatementSupportManager->has($fmt), 'Unsuppoorted attestation statement format.');
81
82
        /** @see 7.1.14 */
83
        $attestationStatementSupport = $this->attestationStatementSupportManager->get($fmt);
84
        Assertion::true($attestationStatementSupport->isValid($getClientDataJSONHash, $attestationObject->getAttStmt(), $attestationObject->getAuthData()), 'Invalid attestation statement.');
85
86
        /** @see 7.1.15 */
87
        /** @see 7.1.16 */
88
        /** @see 7.1.17 */
89
        $credentialId = $attestationObject->getAuthData()->getAttestedCredentialData()->getCredentialId();
90
        Assertion::false($this->credentialRepository->has($credentialId), 'The credential ID already exists.');
91
92
        /* @see 7.1.18 */
93
        /* @see 7.1.19 */
94
    }
95
}
96