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