Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
99.04% covered (success)
99.04%
103 / 104
66.67% covered (warning)
66.67%
2 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
Index
99.04% covered (success)
99.04%
103 / 104
66.67% covered (warning)
66.67%
2 / 3
19
0.00% covered (danger)
0.00%
0 / 1
 readResponse
97.44% covered (success)
97.44%
38 / 39
0.00% covered (danger)
0.00%
0 / 1
8
 testLogin
100.00% covered (success)
100.00%
57 / 57
100.00% covered (success)
100.00%
1 / 1
6
 getProviderList
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
5
1<?php
2
3/**
4 * @package Zmsadmin
5 * @copyright BerlinOnline Stadtportal GmbH & Co. KG
6 **/
7
8namespace BO\Zmsadmin;
9
10use BO\Zmsclient\ModuleAccess;
11use BO\Zmsentities\Useraccount;
12use BO\Zmsentities\Workstation;
13use BO\Zmsadmin\Helper\LoginForm;
14use BO\Mellon\Validator;
15
16class Index extends BaseController
17{
18    /**
19     * @SuppressWarnings(Param)
20     * @return \Psr\Http\Message\ResponseInterface
21     */
22    #[\Override]
23    public function readResponse(
24        \Psr\Http\Message\RequestInterface $request,
25        \Psr\Http\Message\ResponseInterface $response,
26        array $args
27    ): \Psr\Http\Message\ResponseInterface {
28        try {
29            $workstation = \App::$http->readGetResult('/workstation/')->getEntity();
30        } catch (\Exception $workstationexception) {
31            $workstation = null;
32        }
33        $config = \App::$http->readGetResult('/config/', [], \App::CONFIG_SECURE_TOKEN)->getEntity();
34        $input = $request->getParsedBody();
35        $oidclogin = $request->getAttribute('validator')->getParameter('oidclogin')->isString()->getValue();
36        if ($request->getMethod() === 'POST') {
37            $loginData = $this->testLogin($input);
38            if ($loginData instanceof Workstation && $loginData->offsetExists('authkey')) {
39                \BO\Zmsclient\Auth::setKey($loginData->authkey, time() + \App::SESSION_DURATION);
40                return ModuleAccess::rejectWrongModuleAccess(ModuleAccess::MODULE_ADMIN, $loginData, $response)
41                    ?? \BO\Slim\Render::redirect('workstationSelect', array(), array());
42            }
43            return \BO\Slim\Render::withHtml(
44                $response,
45                'page/index.twig',
46                array(
47                'title' => 'Anmeldung gescheitert',
48                'loginfailed' => true,
49                'workstation' => null,
50                'exception' => $loginData,
51                'showloginform' => true,
52                'oidcproviderlist' => $this->getProviderList($config)
53                )
54            );
55        }
56        if ($workstation instanceof Workstation && $workstation->hasId()) {
57            if ($wrongModuleResponse = ModuleAccess::rejectWrongModuleAccess(ModuleAccess::MODULE_ADMIN, $workstation, $response)) {
58                return $wrongModuleResponse;
59            }
60        }
61
62        return \BO\Slim\Render::withHtml(
63            $response,
64            'page/index.twig',
65            array(
66                'title' => 'Anmeldung',
67                'config' => $config,
68                'workstation' => $workstation,
69                'oidcproviderlist' => $this->getProviderList($config),
70                'oidclogin' => $oidclogin,
71                'showloginform' => (! $oidclogin)
72            )
73        );
74    }
75
76    protected function testLogin($input)
77    {
78        $userAccount = new Useraccount(array(
79            'id' => $input['loginName'],
80            'password' => $input['password'],
81            'departments' => array('id' => 0) // required in schema validation
82        ));
83        try {
84            $workstation = \App::$http->readPostResult('/workstation/login/', $userAccount)->getEntity();
85
86            $sessionHash = hash('sha256', $workstation->authkey);
87            \App::$log->info('Login successful', [
88                'event' => 'auth_login_success',
89                'timestamp' => date('c'),
90                'username' => $userAccount->id,
91                'hashed_session_token' => $sessionHash,
92                'application' => 'zmsadmin'
93            ]);
94
95            return $workstation;
96        } catch (\BO\Zmsclient\Exception $exception) {
97            $template = Helper\TwigExceptionHandler::getExceptionTemplate($exception);
98            if ('BO\Zmsentities\Exception\SchemaValidation' == $exception->template) {
99                $exceptionData = [
100                  'template' => 'exception/bo/zmsapi/exception/useraccount/invalidcredentials.twig'
101                ];
102                $exceptionData['data']['password']['messages'] = [
103                    'Der Nutzername oder das Passwort wurden falsch eingegeben'
104                ];
105                \App::$log->info('Login failed - invalid credentials', [
106                    'event' => 'auth_login_failed',
107                    'timestamp' => date('c'),
108                    'username' => $userAccount->id,
109                    'error_type' => 'invalid_credentials',
110                    'application' => 'zmsadmin'
111                ]);
112            } elseif ('BO\Zmsapi\Exception\Useraccount\UserAlreadyLoggedIn' == $exception->template) {
113                \BO\Zmsclient\Auth::setKey($exception->data['authkey'], time() + \App::SESSION_DURATION);
114                \App::$log->info('User already logged in - reusing existing session', [
115                    'event' => 'auth_session_reuse',
116                    'timestamp' => date('c'),
117                    'username' => $userAccount->id,
118                    'hashed_session_token' => hash('sha256', $exception->data['authkey']),
119                    'application' => 'zmsadmin'
120                ]);
121                throw $exception;
122            } elseif (
123                '' != $exception->template
124                && \App::$slim->getContainer()->get('view')->getLoader()->exists($template)
125            ) {
126                $exceptionData = [
127                  'template' => $template,
128                  'data' => $exception->data
129                ];
130                \App::$log->info('Login failed - other error', [
131                    'event' => 'auth_login_failed',
132                    'timestamp' => date('c'),
133                    'username' => $userAccount->id,
134                    'error_type' => 'other',
135                    'error_message' => $exception->getMessage(),
136                    'application' => 'zmsadmin'
137                ]);
138            } else {
139                throw $exception;
140            }
141        }
142        return $exceptionData;
143    }
144
145    protected function getProviderList($config)
146    {
147        $allowedProviderList = explode(',', $config->getPreference('oidc', 'provider') ?? '');
148        $oidcproviderlist = [];
149        foreach (\BO\Slim\Middleware\OAuthMiddleware::$authInstances as $provider => $authInstance) {
150            if (
151                0 < count($allowedProviderList) &&
152                class_exists($authInstance) &&
153                in_array($provider, $allowedProviderList)
154            ) {
155                $oidcproviderlist[] = $provider;
156            }
157        }
158        return $oidcproviderlist;
159    }
160}