Passed
Push — master ( f07e2d...f5be48 )
by Stefan
11:00 queued 08:45
created

PushbackUserPass::setAuthState()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 2
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\Module\webauthn\Controller;
6
7
use DateTime;
8
use Exception;
9
use SimpleSAML\Auth;
10
use SimpleSAML\Auth\Source;
11
use SimpleSAML\Configuration;
12
use SimpleSAML\Error;
13
use SimpleSAML\HTTP\RunnableResponse;
14
use SimpleSAML\Logger;
15
use SimpleSAML\Module;
16
use SimpleSAML\Module\webauthn\WebAuthn\WebAuthnAbstractEvent;
17
use SimpleSAML\Module\webauthn\WebAuthn\WebAuthnAuthenticationEvent;
18
use SimpleSAML\Session;
19
use SimpleSAML\Utils;
20
use SimpleSAML\XHTML\Template;
21
use Symfony\Component\HttpFoundation\Request;
22
use Symfony\Component\HttpFoundation\RedirectResponse;
23
use Symfony\Component\HttpFoundation\Response;
24
25
/**
26
 * Controller class for the webauthn module.
27
 *
28
 * This class serves the different views available in the module.
29
 *
30
 * @package SimpleSAML\Module\webauthn
31
 */
32
class PushbackUserPass {
33
34
    /** @var \SimpleSAML\Configuration */
35
    protected Configuration $config;
36
37
    /** @var \SimpleSAML\Session */
38
    protected Session $session;
39
40
    /**
41
     * @var \SimpleSAML\Auth\State|string
42
     * @psalm-var \SimpleSAML\Auth\State|class-string
43
     */
44
    protected $authState = Auth\State::class;
45
46
    /**
47
     * @var \SimpleSAML\Logger|string
48
     * @psalm-var \SimpleSAML\Logger|class-string
49
     */
50
    protected $logger = Logger::class;
51
52
    /**
53
     * Controller constructor.
54
     *
55
     * It initializes the global configuration and session for the controllers implemented here.
56
     *
57
     * @param \SimpleSAML\Configuration              $config The configuration to use by the controllers.
58
     * @param \SimpleSAML\Session                    $session The session to use by the controllers.
59
     *
60
     * @throws \Exception
61
     */
62
    public function __construct(
63
            Configuration $config,
64
            Session $session
65
    ) {
66
        $this->config = $config;
67
        $this->session = $session;
68
    }
69
70
    /**
71
     * Inject the \SimpleSAML\Auth\State dependency.
72
     *
73
     * @param \SimpleSAML\Auth\State $authState
74
     */
75
    public function setAuthState(Auth\State $authState): void {
76
        $this->authState = $authState;
77
    }
78
79
    /**
80
     * Inject the \SimpleSAML\Logger dependency.
81
     *
82
     * @param \SimpleSAML\Logger $logger
83
     */
84
    public function setLogger(Logger $logger): void {
85
        $this->logger = $logger;
86
    }
87
88
    /**
89
     * @param \Symfony\Component\HttpFoundation\Request $request
90
     * @return (
0 ignored issues
show
Documentation Bug introduced by
The doc comment ( at position 1 could not be parsed: the token is null at position 1.
Loading history...
91
     *   \Symfony\Component\HttpFoundation\RedirectResponse|
92
     *   \SimpleSAML\HTTP\RunnableResponse
93
     * ) A Symfony Response-object.
94
     */
95
    public function main(Request $request): Response {
96
        $this->logger::info('FIDO2 Supercharged - Redirecting to username/password validation');
97
98
        $stateId = $request->query->get('StateId');
99
        if ($stateId === null) {
100
            throw new Error\BadRequest('Missing required StateId query parameter.');
101
        }
102
103
        $moduleConfig = Configuration::getOptionalConfig('module_webauthn.php');
104
        $authsources = Configuration::getConfig('authsources.php')->toArray();
105
        $authsourceString = $moduleConfig->getString('password_authsource');
106
        $classname = get_class(Source::getById($authsourceString));
107
        switch ($classname) {
108
            case 'SimpleSAML\Module\radius\Auth\Source\Radius':
109
                $overrideSource = new class(['AuthId' => $authsourceString], $authsources[$authsourceString]) extends \SimpleSAML\Module\radius\Auth\Source\Radius {
0 ignored issues
show
Bug introduced by
The type SimpleSAML\Module\radius\Auth\Source\Radius was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
110
                    public function loginOverload(string $username, string $password): array {
111
                        return $this->login($username, $password);
112
                    }
113
                };
114
                break;
115
            case 'SimpleSAML\Module\radius\Auth\Source\Ldap':
116
                $overrideSource = new class(['AuthId' => $authsourceString], $authsources[$authsourceString]) extends \SimpleSAML\Module\ldap\Auth\Source\Ldap {
0 ignored issues
show
Bug introduced by
The type SimpleSAML\Module\ldap\Auth\Source\Ldap was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
117
                    public function loginOverload(string $username, string $password): array {
118
                        return $this->login($username, $password);
119
                    }
120
                };
121
                break;
122
            default:
123
                throw new Exception("Unable to pushback authentication to source :$classname:");
124
        }
125
126
127
        $attribs = $overrideSource->loginOverload($request->request->get("username"), $request->request->get("password"));
0 ignored issues
show
Unused Code introduced by
The assignment to $attribs is dead and can be removed.
Loading history...
128
        
129
        $state = $this->authState::loadState($stateId, 'webauthn:request');
130
        
131
        // this is the confirmed username, we store it just like the Passwordless
132
        // one would have been
133
        
134
        $state['Attributes'][$state['FIDO2AttributeStoringUsername']] = [ $request->request->get("username") ];
135
136
        // we deliberately do not store any additional attributes - these have
137
        // to be retrieved from the same authproc that would retrieve them
138
        // in Passwordless mode
139
140
        // now properly return our final state to the framework
141
        Source::completeAuth($state);
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return Symfony\Component\HttpFoundation\Response. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
Bug introduced by
It seems like $state can also be of type null; however, parameter $state of SimpleSAML\Auth\Source::completeAuth() 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

141
        Source::completeAuth(/** @scrutinizer ignore-type */ $state);
Loading history...
142
        
143
    }
144
145
    public function login(string $username, string $password): array {
146
        throw new Exception("Ugh ($username, $password).");
147
    }
148
149
}
150