Passed
Pull Request — master (#39)
by Tim
03:06
created

ManageToken::setAuthState()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
rs 10
nc 1
nop 1
cc 1
1
<?php
2
3
namespace SimpleSAML\Module\webauthn\Controller;
4
5
use Datetime;
6
use Exception;
7
use SimpleSAML\Auth;
8
use SimpleSAML\Configuration;
9
use SimpleSAML\Error;
10
use SimpleSAML\HTTP\RunnableResponse;
11
use SimpleSAML\Logger;
12
use SimpleSAML\Module;
13
use SimpleSAML\Module\webauthn\WebAuthn\StaticProcessHelper;
14
use SimpleSAML\Session;
15
use SimpleSAML\Utils;
16
use Symfony\Component\HttpFoundation\Request;
17
18
/**
19
 * Controller class for the webauthn module.
20
 *
21
 * This class serves the different views available in the module.
22
 *
23
 * @package SimpleSAML\Module\webauthn
24
 */
25
class ManageToken
26
{
27
    /** @var \SimpleSAML\Configuration */
28
    protected $config;
29
30
    /** @var \SimpleSAML\Session */
31
    protected $session;
32
33
    /**
34
     * @var \SimpleSAML\Auth\State|string
35
     * @psalm-var \SimpleSAML\Auth\State|class-string
36
     */
37
    protected $authState = Auth\State::class;
38
39
    /**
40
     * @var \SimpleSAML\Logger|string
41
     * @psalm-var \SimpleSAML\Logger|class-string
42
     */
43
    protected $logger = Logger::class;
44
45
46
    /**
47
     * Controller constructor.
48
     *
49
     * It initializes the global configuration and session for the controllers implemented here.
50
     *
51
     * @param \SimpleSAML\Configuration              $config The configuration to use by the controllers.
52
     * @param \SimpleSAML\Session                    $session The session to use by the controllers.
53
     *
54
     * @throws \Exception
55
     */
56
    public function __construct(
57
        Configuration $config,
58
        Session $session
59
    ) {
60
        $this->config = $config;
61
        $this->session = $session;
62
    }
63
64
65
    /**
66
     * Inject the \SimpleSAML\Auth\State dependency.
67
     *
68
     * @param \SimpleSAML\Auth\State $authState
69
     */
70
    public function setAuthState(Auth\State $authState): void
71
    {
72
        $this->authState = $authState;
73
    }
74
75
76
    /**
77
     * Inject the \SimpleSAML\Logger dependency.
78
     *
79
     * @param \SimpleSAML\Logger $logger
80
     */
81
    public function setLogger(Logger $logger): void
82
    {
83
        $this->logger = $logger;
84
    }
85
86
87
    /**
88
     * @param \Symfony\Component\HttpFoundation\Request $request
89
     * @return \SimpleSAML\HTTP\RunnableResponse  A Symfony Response-object.
90
     */
91
    public function main(Request $request): RunnableResponse
92
    {
93
        $this->logger::info('FIDO2 - Accessing WebAuthn token management');
94
95
        $stateId = $request->query->get('StateId');
96
        if ($stateId === null) {
97
            throw new Error\BadRequest('Missing required StateId query parameter.');
98
        }
99
100
        /** @var array $state */
101
        $state = $this->authState::loadState($stateId, 'webauthn:request');
102
103
        if ($state['FIDO2AuthSuccessful'] === false) {
104
            throw new Exception("Attempt to access the token management page unauthenticated.");
105
        }
106
107
        switch ($request->request->get('submit')) {
108
            case "NEVERMIND":
109
                $response = new RunnableResponse([Auth\ProcessingChain::class, 'resumeProcessing'], [$state]);
110
                break;
111
            case "DELETE":
112
                $credId = $request->request->get('credId');
113
                if ($state['FIDO2AuthSuccessful'] == $credId) {
114
                    throw new Exception("Attempt to delete the currently used credential despite UI preventing this.");
115
                }
116
117
                $store = $state['webauthn:store'];
118
                $store->deleteTokenData($credId);
119
120
                if (array_key_exists('Registration', $state)) {
121
                    foreach ($state['FIDO2Tokens'] as $key => $value) {
122
                        if ($state['FIDO2Tokens'][$key][0] == $credId) {
123
                            unset($state['FIDO2Tokens'][$key]);
124
                            break;
125
                        }
126
                    }
127
128
                    $response = new RunnableResponse([StaticProcessHelper::class, 'saveStateAndRedirect'], [&$state]);
129
                } else {
130
                    $response = new RunnableResponse([Auth\ProcessingChain::class, 'resumeProcessing'], [$state]);
131
                }
132
                break;
133
            default:
134
                throw new Exception("Unknown submit button state.");
135
        }
136
137
        $response->headers->set('Expires', 'Thu, 19 Nov 1981 08:52:00 GMT');
138
        $response->headers->set('Cache-Control', 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
139
        $response->headers->set('Pragma', 'no-cache');
140
141
        /** Symfony 5 style */
142
        /**
143
        $response->setCache([
144
            'must_revalidate'  => true,
145
            'no_cache'         => true,
146
            'no_store'         => true,
147
            'no_transform'     => false,
148
            'public'           => false,
149
            'private'          => false,
150
        ]);
151
        $response->setExpires(new DateTime('Thu, 19 Nov 1981 08:52:00 GMT'));
152
        */
153
154
        return $response;
155
    }
156
}
157