CollectedClientData::getChallenge()   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 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
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 Base64Url\Base64Url;
18
19
class CollectedClientData
20
{
21
    private $rawData;
22
    private $data;
23
    private $type;
24
    private $challenge;
25
    private $origin;
26
    private $tokenBinding;
27
28
    public function __construct(string $rawData, array $data)
29
    {
30
        $validators = $this->dataValidators();
31
        foreach ($validators as $parameter => $validator) {
32
            $this->$parameter = $validator($data);
33
        }
34
        $this->rawData = $rawData;
35
        $this->data = $data;
36
    }
37
38
    public static function createFormJson(string $data): self
39
    {
40
        $rawData = Base64Url::decode($data);
41
        $json = \Safe\json_decode($rawData, true);
42
        Assertion::isArray($json, 'Invalid collected client data');
43
44
        return new self($rawData, $json);
45
    }
46
47
    public function getType(): string
48
    {
49
        return $this->type;
50
    }
51
52
    public function getChallenge(): string
53
    {
54
        return $this->challenge;
55
    }
56
57
    public function getOrigin(): string
58
    {
59
        return $this->origin;
60
    }
61
62
    public function getTokenBinding(): ?TokenBinding
63
    {
64
        return $this->tokenBinding ? TokenBinding::createFormArray($this->tokenBinding) : null;
65
    }
66
67
    public function getRawData(): string
68
    {
69
        return $this->rawData;
70
    }
71
72
    /**
73
     * @return string[]
74
     */
75
    public function all(): array
76
    {
77
        return array_keys($this->data);
78
    }
79
80
    public function has(string $key): bool
81
    {
82
        return array_key_exists($key, $this->data);
83
    }
84
85
    public function get(string $key)
86
    {
87
        if (!$this->has($key)) {
88
            throw new \InvalidArgumentException(\Safe\sprintf('The key "%s" is missing', $key));
89
        }
90
91
        return $this->data[$key];
92
    }
93
94
    /**
95
     * @return callable[]
96
     */
97
    private function dataValidators(): array
98
    {
99
        return [
100
            'type' => $this->requiredData('type'),
101
            'challenge' => $this->requiredData('challenge', true),
102
            'origin' => $this->requiredData('origin'),
103
            'tokenBinding' => $this->optionalData('tokenBinding'),
104
        ];
105
    }
106
107
    private function requiredData($key, bool $isB64 = false): callable
108
    {
109
        return function ($json) use ($key, $isB64) {
110
            if (!array_key_exists($key, $json)) {
111
                throw new \InvalidArgumentException(\Safe\sprintf('The key "%s" is missing', $key));
112
            }
113
114
            return $isB64 ? Base64Url::decode($json[$key]) : $json[$key];
115
        };
116
    }
117
118
    private function optionalData($key): callable
119
    {
120
        return function ($json) use ($key) {
121
            if (!array_key_exists($key, $json)) {
122
                return;
123
            }
124
125
            return $json[$key];
126
        };
127
    }
128
}
129