Passed
Pull Request — master (#31)
by Tim
02:10
created

WebAuthn::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 2
c 1
b 0
f 0
dl 0
loc 6
rs 10
nc 1
nop 2
cc 1
1
<?php
2
3
namespace SimpleSAML\Module\webauthn\Controller;
4
5
use SimpleSAML\Auth;
6
use SimpleSAML\Configuration;
7
use SimpleSAML\Error;
8
use SimpleSAML\Logger;
9
use SimpleSAML\Module;
10
use SimpleSAML\Session;
11
use SimpleSAML\Utils;
12
use SimpleSAML\XHTML\Template;
13
use Symfony\Component\HttpFoundation\Request;
14
15
/**
16
 * Controller class for the webauthn module.
17
 *
18
 * This class serves the different views available in the module.
19
 *
20
 * @package SimpleSAML\Module\webauthn
21
 */
22
class WebAuthn
23
{
24
    /** @var \SimpleSAML\Configuration */
25
    protected $config;
26
27
    /** @var \SimpleSAML\Session */
28
    protected $session;
29
30
    /**
31
     * @var \SimpleSAML\Auth\State|string
32
     * @psalm-var \SimpleSAML\Auth\State|class-string
33
     */
34
    protected $authState = Auth\State::class;
35
36
    /**
37
     * @var \SimpleSAML\Logger|string
38
     * @psalm-var \SimpleSAML\Logger|class-string
39
     */
40
    protected $logger = Logger::class;
41
42
43
    /**
44
     * Controller constructor.
45
     *
46
     * It initializes the global configuration and session for the controllers implemented here.
47
     *
48
     * @param \SimpleSAML\Configuration              $config The configuration to use by the controllers.
49
     * @param \SimpleSAML\Session                    $session The session to use by the controllers.
50
     *
51
     * @throws \Exception
52
     */
53
    public function __construct(
54
        Configuration $config,
55
        Session $session
56
    ) {
57
        $this->config = $config;
58
        $this->session = $session;
59
    }
60
61
62
    /**
63
     * Inject the \SimpleSAML\Auth\State dependency.
64
     *
65
     * @param \SimpleSAML\Auth\State $authState
66
     */
67
    public function setAuthState(Auth\State $authState): void
68
    {
69
        $this->authState = $authState;
70
    }
71
72
73
    /**
74
     * Inject the \SimpleSAML\Logger dependency.
75
     *
76
     * @param \SimpleSAML\Logger $logger
77
     */
78
    public function setLogger(Logger $logger): void
79
    {
80
        $this->logger = $logger;
81
    }
82
83
84
    /**
85
     * @param \Symfony\Component\HttpFoundation\Request $request
86
     * @return \SimpleSAML\XHTML\Template  A Symfony Response-object.
87
     */
88
    public function main(Request $request): Template
89
    {
90
        $this->logger::info('FIDO2 - Accessing WebAuthn interface');
91
92
        $stateId = $request->query->get('StateId');
93
        if ($stateId === null) {
94
            throw new Error\BadRequest('Missing required StateId query parameter.');
95
        }
96
97
        $state = $this->authState::loadState($stateId, 'webauthn:request');
98
99
        // Make, populate and layout consent form
100
        $t = new Template($this->config, 'webauthn:authentication.twig');
101
        $t->data['UserID'] = $state['FIDO2Username'];
102
        $t->data['FIDO2Tokens'] = $state['FIDO2Tokens'];
103
104
        $challenge = str_split($state['FIDO2SignupChallenge'], 2);
105
        $username = str_split(
106
            hash('sha512', $state['FIDO2Username'] . '|' . Utils\Config::getSecretSalt() . '|' . $state['Source']['entityid']),
107
            2
108
        );
109
110
        $challengeEncoded = [];
111
        foreach ($challenge as $oneChar) {
112
            $challengeEncoded[] = hexdec($oneChar);
113
        }
114
115
        $credentialIdEncoded = [];
116
        foreach ($state['FIDO2Tokens'] as $number => $token) {
117
            $idSplit = str_split($token[0], 2);
118
            $credentialIdEncoded[$number] = [];
119
            foreach ($idSplit as $credIdBlock) {
120
                $credentialIdEncoded[$number][] = hexdec($credIdBlock);
121
            }
122
        }
123
124
        $usernameEncoded = [];
125
        foreach ($username as $oneChar) {
126
            $usernameEncoded[] = hexdec($oneChar);
127
        }
128
129
        $frontendData = [];
130
        $frontendData['challengeEncoded'] = $challengeEncoded;
131
        $frontendData['state'] = [];
132
        foreach (['Source', 'FIDO2Scope','FIDO2Username','FIDO2Displayname','requestTokenModel'] as $stateItem) {
133
            $frontendData['state'][$stateItem] = $state[$stateItem];
134
        }
135
136
        $t->data['showExitButton'] = !array_key_exists('Registration', $state);
0 ignored issues
show
Bug introduced by
It seems like $state can also be of type null; however, parameter $search of array_key_exists() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

136
        $t->data['showExitButton'] = !array_key_exists('Registration', /** @scrutinizer ignore-type */ $state);
Loading history...
137
        $frontendData['usernameEncoded'] = $usernameEncoded;
138
        $frontendData['attestation'] = $state['requestTokenModel'] ? "indirect" : "none";
139
        $frontendData['credentialIdEncoded'] = $credentialIdEncoded;
140
        $t->data['frontendData'] = json_encode($frontendData);
141
142
        $t->data['FIDO2AuthSuccessful'] = $state['FIDO2AuthSuccessful'];
143
        if (
144
            count($state['FIDO2Tokens']) == 0 ||
145
            ($state['FIDO2WantsRegister'] === true && $state['FIDO2AuthSuccessful'] !== false)
146
        ) {
147
            $t->data['regURL'] = Module::getModuleURL('webauthn/regprocess.php?StateId=' . urlencode($stateId));
148
            $t->data['delURL'] = Module::getModuleURL('webauthn/managetoken.php?StateId=' . urlencode($stateId));
149
        }
150
151
        $t->data['authForm'] = "";
152
        if (
153
            count($state['FIDO2Tokens']) > 0 &&
154
            ($state['FIDO2WantsRegister'] !== true || $state['FIDO2AuthSuccessful'] === false)
155
        ) {
156
            $t->data['authURL'] = Module::getModuleURL('webauthn/authprocess.php?StateId=' . urlencode($stateId));
157
        }
158
159
        // dynamically generate the JS code needed for token registration
160
        return $t;
161
    }
162
}
163