YubikeyService::verify()   B
last analyzed

Complexity

Conditions 7
Paths 8

Size

Total Lines 45
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 7
eloc 27
nc 8
nop 1
dl 0
loc 45
rs 8.5546
c 2
b 0
f 0
1
<?php
2
3
declare(strict_types = 1);
4
5
/**
6
 * Copyright 2014 SURFnet bv
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
0 ignored issues
show
Coding Style introduced by
PHP version not specified
Loading history...
Coding Style introduced by
Missing @category tag in file comment
Loading history...
Coding Style introduced by
Missing @package tag in file comment
Loading history...
Coding Style introduced by
Missing @author tag in file comment
Loading history...
Coding Style introduced by
Missing @license tag in file comment
Loading history...
Coding Style introduced by
Missing @link tag in file comment
Loading history...
20
21
namespace Surfnet\StepupSelfService\SelfServiceBundle\Service;
22
23
use GuzzleHttp\Client;
24
use Psr\Log\LoggerInterface;
25
use Surfnet\StepupBundle\Http\JsonHelper;
26
use Surfnet\StepupSelfService\SelfServiceBundle\Command\VerifyYubikeyOtpCommand;
27
use RuntimeException;
28
29
class YubikeyService implements YubikeyServiceInterface
0 ignored issues
show
Coding Style introduced by
Missing doc comment for class YubikeyService
Loading history...
30
{
31
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
Parameter $logger should have a doc-comment as per coding-style.
Loading history...
32
     * @param Client $guzzleClient A Guzzle client configured with the Yubikey API base URL and authentication.
33
     */
34
    public function __construct(private readonly Client $guzzleClient, private readonly LoggerInterface $logger)
35
    {
36
    }
37
38
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
Coding Style introduced by
Parameter $command should have a doc-comment as per coding-style.
Loading history...
39
     * @return YubikeyVerificationResult
40
     */
41
    public function verify(VerifyYubikeyOtpCommand $command): YubikeyVerificationResult
42
    {
43
        $this->logger->info('Verifying Yubikey OTP');
44
45
        $body = [
46
            'requester' => ['institution' => $command->institution, 'identity' => $command->identity],
47
            'otp' => ['value' => $command->otp],
48
        ];
49
        $response = $this->guzzleClient->post('api/verify-yubikey', ['json' => $body, 'http_errors' => false]);
50
        $statusCode = $response->getStatusCode();
51
52
        if ($statusCode != 200) {
53
            $type = $statusCode >= 400 && $statusCode < 500 ? 'client' : 'server';
54
            $this->logger->info(sprintf(
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
55
                'Yubikey OTP verification failed; %s error; HTTP/%d %s',
56
                $type,
57
                $statusCode,
58
                $response->getReasonPhrase()
59
            ));
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
60
            $this->logger->warning((string) $response->getBody());
61
62
            return new YubikeyVerificationResult(true, false);
63
        }
64
65
        try {
66
            $result = JsonHelper::decode((string) $response->getBody());
67
        } catch (RuntimeException) {
68
            $this->logger->error('Yubikey OTP verification failed; server responded with malformed JSON.');
69
70
            return new YubikeyVerificationResult(false, true);
71
        }
72
73
        if (!isset($result['status'])) {
74
            $this->logger->error('Yubikey OTP verification failed; server responded without status report.');
75
76
            return new YubikeyVerificationResult(false, true);
77
        }
78
79
        if ($result['status'] !== 'OK') {
80
            $this->logger->error('Yubikey OTP verification failed; server responded with non-OK status report.');
81
82
            return new YubikeyVerificationResult(false, true);
83
        }
84
85
        return new YubikeyVerificationResult(false, false);
86
    }
87
}
88