Completed
Pull Request — master (#2424)
by Blizzz
33:28
created
core/Controller/LoginController.php 2 patches
Indentation   +245 added lines, -245 removed lines patch added patch discarded remove patch
@@ -49,277 +49,277 @@
 block discarded – undo
49 49
 use OC\Hooks\PublicEmitter;
50 50
 
51 51
 class LoginController extends Controller {
52
-	/** @var IUserManager */
53
-	private $userManager;
54
-	/** @var IConfig */
55
-	private $config;
56
-	/** @var ISession */
57
-	private $session;
58
-	/** @var IUserSession|Session */
59
-	private $userSession;
60
-	/** @var IURLGenerator */
61
-	private $urlGenerator;
62
-	/** @var Manager */
63
-	private $twoFactorManager;
64
-	/** @var Throttler */
65
-	private $throttler;
52
+    /** @var IUserManager */
53
+    private $userManager;
54
+    /** @var IConfig */
55
+    private $config;
56
+    /** @var ISession */
57
+    private $session;
58
+    /** @var IUserSession|Session */
59
+    private $userSession;
60
+    /** @var IURLGenerator */
61
+    private $urlGenerator;
62
+    /** @var Manager */
63
+    private $twoFactorManager;
64
+    /** @var Throttler */
65
+    private $throttler;
66 66
 
67
-	/**
68
-	 * @param string $appName
69
-	 * @param IRequest $request
70
-	 * @param IUserManager $userManager
71
-	 * @param IConfig $config
72
-	 * @param ISession $session
73
-	 * @param IUserSession $userSession
74
-	 * @param IURLGenerator $urlGenerator
75
-	 * @param Manager $twoFactorManager
76
-	 * @param Throttler $throttler
77
-	 */
78
-	function __construct($appName,
79
-						 IRequest $request,
80
-						 IUserManager $userManager,
81
-						 IConfig $config,
82
-						 ISession $session,
83
-						 IUserSession $userSession,
84
-						 IURLGenerator $urlGenerator,
85
-						 Manager $twoFactorManager,
86
-						 Throttler $throttler) {
87
-		parent::__construct($appName, $request);
88
-		$this->userManager = $userManager;
89
-		$this->config = $config;
90
-		$this->session = $session;
91
-		$this->userSession = $userSession;
92
-		$this->urlGenerator = $urlGenerator;
93
-		$this->twoFactorManager = $twoFactorManager;
94
-		$this->throttler = $throttler;
95
-	}
67
+    /**
68
+     * @param string $appName
69
+     * @param IRequest $request
70
+     * @param IUserManager $userManager
71
+     * @param IConfig $config
72
+     * @param ISession $session
73
+     * @param IUserSession $userSession
74
+     * @param IURLGenerator $urlGenerator
75
+     * @param Manager $twoFactorManager
76
+     * @param Throttler $throttler
77
+     */
78
+    function __construct($appName,
79
+                            IRequest $request,
80
+                            IUserManager $userManager,
81
+                            IConfig $config,
82
+                            ISession $session,
83
+                            IUserSession $userSession,
84
+                            IURLGenerator $urlGenerator,
85
+                            Manager $twoFactorManager,
86
+                            Throttler $throttler) {
87
+        parent::__construct($appName, $request);
88
+        $this->userManager = $userManager;
89
+        $this->config = $config;
90
+        $this->session = $session;
91
+        $this->userSession = $userSession;
92
+        $this->urlGenerator = $urlGenerator;
93
+        $this->twoFactorManager = $twoFactorManager;
94
+        $this->throttler = $throttler;
95
+    }
96 96
 
97
-	/**
98
-	 * @NoAdminRequired
99
-	 * @UseSession
100
-	 *
101
-	 * @return RedirectResponse
102
-	 */
103
-	public function logout() {
104
-		$loginToken = $this->request->getCookie('nc_token');
105
-		if (!is_null($loginToken)) {
106
-			$this->config->deleteUserValue($this->userSession->getUser()->getUID(), 'login_token', $loginToken);
107
-		}
108
-		$this->userSession->logout();
97
+    /**
98
+     * @NoAdminRequired
99
+     * @UseSession
100
+     *
101
+     * @return RedirectResponse
102
+     */
103
+    public function logout() {
104
+        $loginToken = $this->request->getCookie('nc_token');
105
+        if (!is_null($loginToken)) {
106
+            $this->config->deleteUserValue($this->userSession->getUser()->getUID(), 'login_token', $loginToken);
107
+        }
108
+        $this->userSession->logout();
109 109
 
110
-		return new RedirectResponse($this->urlGenerator->linkToRouteAbsolute('core.login.showLoginForm'));
111
-	}
110
+        return new RedirectResponse($this->urlGenerator->linkToRouteAbsolute('core.login.showLoginForm'));
111
+    }
112 112
 
113
-	/**
114
-	 * @PublicPage
115
-	 * @NoCSRFRequired
116
-	 * @UseSession
117
-	 *
118
-	 * @param string $user
119
-	 * @param string $redirect_url
120
-	 * @param string $remember_login
121
-	 *
122
-	 * @return TemplateResponse|RedirectResponse
123
-	 */
124
-	public function showLoginForm($user, $redirect_url, $remember_login) {
125
-		if ($this->userSession->isLoggedIn()) {
126
-			return new RedirectResponse(OC_Util::getDefaultPageUrl());
127
-		}
113
+    /**
114
+     * @PublicPage
115
+     * @NoCSRFRequired
116
+     * @UseSession
117
+     *
118
+     * @param string $user
119
+     * @param string $redirect_url
120
+     * @param string $remember_login
121
+     *
122
+     * @return TemplateResponse|RedirectResponse
123
+     */
124
+    public function showLoginForm($user, $redirect_url, $remember_login) {
125
+        if ($this->userSession->isLoggedIn()) {
126
+            return new RedirectResponse(OC_Util::getDefaultPageUrl());
127
+        }
128 128
 
129
-		$parameters = array();
130
-		$loginMessages = $this->session->get('loginMessages');
131
-		$errors = [];
132
-		$messages = [];
133
-		if (is_array($loginMessages)) {
134
-			list($errors, $messages) = $loginMessages;
135
-		}
136
-		$this->session->remove('loginMessages');
137
-		foreach ($errors as $value) {
138
-			$parameters[$value] = true;
139
-		}
129
+        $parameters = array();
130
+        $loginMessages = $this->session->get('loginMessages');
131
+        $errors = [];
132
+        $messages = [];
133
+        if (is_array($loginMessages)) {
134
+            list($errors, $messages) = $loginMessages;
135
+        }
136
+        $this->session->remove('loginMessages');
137
+        foreach ($errors as $value) {
138
+            $parameters[$value] = true;
139
+        }
140 140
 
141
-		$parameters['messages'] = $messages;
142
-		if (!is_null($user) && $user !== '') {
143
-			$parameters['loginName'] = $user;
144
-			$parameters['user_autofocus'] = false;
145
-		} else {
146
-			$parameters['loginName'] = '';
147
-			$parameters['user_autofocus'] = true;
148
-		}
149
-		if (!empty($redirect_url)) {
150
-			$parameters['redirect_url'] = $redirect_url;
151
-		}
141
+        $parameters['messages'] = $messages;
142
+        if (!is_null($user) && $user !== '') {
143
+            $parameters['loginName'] = $user;
144
+            $parameters['user_autofocus'] = false;
145
+        } else {
146
+            $parameters['loginName'] = '';
147
+            $parameters['user_autofocus'] = true;
148
+        }
149
+        if (!empty($redirect_url)) {
150
+            $parameters['redirect_url'] = $redirect_url;
151
+        }
152 152
 
153
-		$parameters['canResetPassword'] = true;
154
-		$parameters['resetPasswordLink'] = $this->config->getSystemValue('lost_password_link', '');
155
-		if (!$parameters['resetPasswordLink']) {
156
-			if (!is_null($user) && $user !== '') {
157
-				$userObj = $this->userManager->get($user);
158
-				if ($userObj instanceof IUser) {
159
-					$parameters['canResetPassword'] = $userObj->canChangePassword();
160
-				}
161
-			}
162
-		}
153
+        $parameters['canResetPassword'] = true;
154
+        $parameters['resetPasswordLink'] = $this->config->getSystemValue('lost_password_link', '');
155
+        if (!$parameters['resetPasswordLink']) {
156
+            if (!is_null($user) && $user !== '') {
157
+                $userObj = $this->userManager->get($user);
158
+                if ($userObj instanceof IUser) {
159
+                    $parameters['canResetPassword'] = $userObj->canChangePassword();
160
+                }
161
+            }
162
+        }
163 163
 
164
-		$parameters['alt_login'] = OC_App::getAlternativeLogIns();
165
-		$parameters['rememberLoginState'] = !empty($remember_login) ? $remember_login : 0;
164
+        $parameters['alt_login'] = OC_App::getAlternativeLogIns();
165
+        $parameters['rememberLoginState'] = !empty($remember_login) ? $remember_login : 0;
166 166
 
167
-		if (!is_null($user) && $user !== '') {
168
-			$parameters['loginName'] = $user;
169
-			$parameters['user_autofocus'] = false;
170
-		} else {
171
-			$parameters['loginName'] = '';
172
-			$parameters['user_autofocus'] = true;
173
-		}
167
+        if (!is_null($user) && $user !== '') {
168
+            $parameters['loginName'] = $user;
169
+            $parameters['user_autofocus'] = false;
170
+        } else {
171
+            $parameters['loginName'] = '';
172
+            $parameters['user_autofocus'] = true;
173
+        }
174 174
 
175
-		return new TemplateResponse(
176
-			$this->appName, 'login', $parameters, 'guest'
177
-		);
178
-	}
175
+        return new TemplateResponse(
176
+            $this->appName, 'login', $parameters, 'guest'
177
+        );
178
+    }
179 179
 
180
-	/**
181
-	 * @param string $redirectUrl
182
-	 * @return RedirectResponse
183
-	 */
184
-	private function generateRedirect($redirectUrl) {
185
-		if (!is_null($redirectUrl) && $this->userSession->isLoggedIn()) {
186
-			$location = $this->urlGenerator->getAbsoluteURL(urldecode($redirectUrl));
187
-			// Deny the redirect if the URL contains a @
188
-			// This prevents unvalidated redirects like ?redirect_url=:[email protected]
189
-			if (strpos($location, '@') === false) {
190
-				return new RedirectResponse($location);
191
-			}
192
-		}
193
-		return new RedirectResponse(OC_Util::getDefaultPageUrl());
194
-	}
180
+    /**
181
+     * @param string $redirectUrl
182
+     * @return RedirectResponse
183
+     */
184
+    private function generateRedirect($redirectUrl) {
185
+        if (!is_null($redirectUrl) && $this->userSession->isLoggedIn()) {
186
+            $location = $this->urlGenerator->getAbsoluteURL(urldecode($redirectUrl));
187
+            // Deny the redirect if the URL contains a @
188
+            // This prevents unvalidated redirects like ?redirect_url=:[email protected]
189
+            if (strpos($location, '@') === false) {
190
+                return new RedirectResponse($location);
191
+            }
192
+        }
193
+        return new RedirectResponse(OC_Util::getDefaultPageUrl());
194
+    }
195 195
 
196
-	/**
197
-	 * @PublicPage
198
-	 * @UseSession
199
-	 * @NoCSRFRequired
200
-	 *
201
-	 * @param string $user
202
-	 * @param string $password
203
-	 * @param string $redirect_url
204
-	 * @param boolean $remember_login
205
-	 * @param string $timezone
206
-	 * @param string $timezone_offset
207
-	 * @return RedirectResponse
208
-	 */
209
-	public function tryLogin($user, $password, $redirect_url, $remember_login = false, $timezone = '', $timezone_offset = '') {
210
-		if(!is_string($user)) {
211
-			throw new \InvalidArgumentException('Username must be string');
212
-		}
213
-		$currentDelay = $this->throttler->getDelay($this->request->getRemoteAddress(), 'login');
214
-		$this->throttler->sleepDelay($this->request->getRemoteAddress(), 'login');
196
+    /**
197
+     * @PublicPage
198
+     * @UseSession
199
+     * @NoCSRFRequired
200
+     *
201
+     * @param string $user
202
+     * @param string $password
203
+     * @param string $redirect_url
204
+     * @param boolean $remember_login
205
+     * @param string $timezone
206
+     * @param string $timezone_offset
207
+     * @return RedirectResponse
208
+     */
209
+    public function tryLogin($user, $password, $redirect_url, $remember_login = false, $timezone = '', $timezone_offset = '') {
210
+        if(!is_string($user)) {
211
+            throw new \InvalidArgumentException('Username must be string');
212
+        }
213
+        $currentDelay = $this->throttler->getDelay($this->request->getRemoteAddress(), 'login');
214
+        $this->throttler->sleepDelay($this->request->getRemoteAddress(), 'login');
215 215
 
216
-		// If the user is already logged in and the CSRF check does not pass then
217
-		// simply redirect the user to the correct page as required. This is the
218
-		// case when an user has already logged-in, in another tab.
219
-		if(!$this->request->passesCSRFCheck()) {
220
-			return $this->generateRedirect($redirect_url);
221
-		}
216
+        // If the user is already logged in and the CSRF check does not pass then
217
+        // simply redirect the user to the correct page as required. This is the
218
+        // case when an user has already logged-in, in another tab.
219
+        if(!$this->request->passesCSRFCheck()) {
220
+            return $this->generateRedirect($redirect_url);
221
+        }
222 222
 
223
-		if ($this->userManager instanceof PublicEmitter) {
224
-			$this->userManager->emit('\OC\User', 'preLogin', array($user, $password));
225
-		}
223
+        if ($this->userManager instanceof PublicEmitter) {
224
+            $this->userManager->emit('\OC\User', 'preLogin', array($user, $password));
225
+        }
226 226
 
227
-		$originalUser = $user;
228
-		// TODO: Add all the insane error handling
229
-		/* @var $loginResult IUser */
230
-		$loginResult = $this->userManager->checkPassword($user, $password);
231
-		if ($loginResult === false) {
232
-			$users = $this->userManager->getByEmail($user);
233
-			// we only allow login by email if unique
234
-			if (count($users) === 1) {
235
-				$user = $users[0]->getUID();
236
-				$loginResult = $this->userManager->checkPassword($user, $password);
237
-			}
238
-		}
239
-		if ($loginResult === false) {
240
-			$this->throttler->registerAttempt('login', $this->request->getRemoteAddress(), ['user' => $originalUser]);
241
-			if($currentDelay === 0) {
242
-				$this->throttler->sleepDelay($this->request->getRemoteAddress(), 'login');
243
-			}
244
-			$this->session->set('loginMessages', [
245
-				['invalidpassword'], []
246
-			]);
247
-			// Read current user and append if possible - we need to return the unmodified user otherwise we will leak the login name
248
-			$args = !is_null($user) ? ['user' => $originalUser] : [];
249
-			return new RedirectResponse($this->urlGenerator->linkToRoute('core.login.showLoginForm', $args));
250
-		}
251
-		// TODO: remove password checks from above and let the user session handle failures
252
-		// requires https://github.com/owncloud/core/pull/24616
253
-		$this->userSession->completeLogin($loginResult, ['loginName' => $user, 'password' => $password]);
254
-		$this->userSession->createSessionToken($this->request, $loginResult->getUID(), $user, $password, (int)$remember_login);
227
+        $originalUser = $user;
228
+        // TODO: Add all the insane error handling
229
+        /* @var $loginResult IUser */
230
+        $loginResult = $this->userManager->checkPassword($user, $password);
231
+        if ($loginResult === false) {
232
+            $users = $this->userManager->getByEmail($user);
233
+            // we only allow login by email if unique
234
+            if (count($users) === 1) {
235
+                $user = $users[0]->getUID();
236
+                $loginResult = $this->userManager->checkPassword($user, $password);
237
+            }
238
+        }
239
+        if ($loginResult === false) {
240
+            $this->throttler->registerAttempt('login', $this->request->getRemoteAddress(), ['user' => $originalUser]);
241
+            if($currentDelay === 0) {
242
+                $this->throttler->sleepDelay($this->request->getRemoteAddress(), 'login');
243
+            }
244
+            $this->session->set('loginMessages', [
245
+                ['invalidpassword'], []
246
+            ]);
247
+            // Read current user and append if possible - we need to return the unmodified user otherwise we will leak the login name
248
+            $args = !is_null($user) ? ['user' => $originalUser] : [];
249
+            return new RedirectResponse($this->urlGenerator->linkToRoute('core.login.showLoginForm', $args));
250
+        }
251
+        // TODO: remove password checks from above and let the user session handle failures
252
+        // requires https://github.com/owncloud/core/pull/24616
253
+        $this->userSession->completeLogin($loginResult, ['loginName' => $user, 'password' => $password]);
254
+        $this->userSession->createSessionToken($this->request, $loginResult->getUID(), $user, $password, (int)$remember_login);
255 255
 
256
-		// User has successfully logged in, now remove the password reset link, when it is available
257
-		$this->config->deleteUserValue($loginResult->getUID(), 'core', 'lostpassword');
256
+        // User has successfully logged in, now remove the password reset link, when it is available
257
+        $this->config->deleteUserValue($loginResult->getUID(), 'core', 'lostpassword');
258 258
 
259
-		$this->session->set('last-password-confirm', $loginResult->getLastLogin());
259
+        $this->session->set('last-password-confirm', $loginResult->getLastLogin());
260 260
 
261
-		if ($timezone_offset !== '') {
262
-			$this->config->setUserValue($loginResult->getUID(), 'core', 'timezone', $timezone);
263
-			$this->session->set('timezone', $timezone_offset);
264
-		}
261
+        if ($timezone_offset !== '') {
262
+            $this->config->setUserValue($loginResult->getUID(), 'core', 'timezone', $timezone);
263
+            $this->session->set('timezone', $timezone_offset);
264
+        }
265 265
 
266
-		if ($this->twoFactorManager->isTwoFactorAuthenticated($loginResult)) {
267
-			$this->twoFactorManager->prepareTwoFactorLogin($loginResult, $remember_login);
266
+        if ($this->twoFactorManager->isTwoFactorAuthenticated($loginResult)) {
267
+            $this->twoFactorManager->prepareTwoFactorLogin($loginResult, $remember_login);
268 268
 
269
-			$providers = $this->twoFactorManager->getProviders($loginResult);
270
-			if (count($providers) === 1) {
271
-				// Single provider, hence we can redirect to that provider's challenge page directly
272
-				/* @var $provider IProvider */
273
-				$provider = array_pop($providers);
274
-				$url = 'core.TwoFactorChallenge.showChallenge';
275
-				$urlParams = [
276
-					'challengeProviderId' => $provider->getId(),
277
-				];
278
-			} else {
279
-				$url = 'core.TwoFactorChallenge.selectChallenge';
280
-				$urlParams = [];
281
-			}
269
+            $providers = $this->twoFactorManager->getProviders($loginResult);
270
+            if (count($providers) === 1) {
271
+                // Single provider, hence we can redirect to that provider's challenge page directly
272
+                /* @var $provider IProvider */
273
+                $provider = array_pop($providers);
274
+                $url = 'core.TwoFactorChallenge.showChallenge';
275
+                $urlParams = [
276
+                    'challengeProviderId' => $provider->getId(),
277
+                ];
278
+            } else {
279
+                $url = 'core.TwoFactorChallenge.selectChallenge';
280
+                $urlParams = [];
281
+            }
282 282
 
283
-			if (!is_null($redirect_url)) {
284
-				$urlParams['redirect_url'] = $redirect_url;
285
-			}
283
+            if (!is_null($redirect_url)) {
284
+                $urlParams['redirect_url'] = $redirect_url;
285
+            }
286 286
 
287
-			return new RedirectResponse($this->urlGenerator->linkToRoute($url, $urlParams));
288
-		}
287
+            return new RedirectResponse($this->urlGenerator->linkToRoute($url, $urlParams));
288
+        }
289 289
 
290
-		if ($remember_login) {
291
-			$this->userSession->createRememberMeToken($loginResult);
292
-		}
290
+        if ($remember_login) {
291
+            $this->userSession->createRememberMeToken($loginResult);
292
+        }
293 293
 
294
-		return $this->generateRedirect($redirect_url);
295
-	}
294
+        return $this->generateRedirect($redirect_url);
295
+    }
296 296
 
297
-	/**
298
-	 * @NoAdminRequired
299
-	 * @UseSession
300
-	 *
301
-	 * @license GNU AGPL version 3 or any later version
302
-	 *
303
-	 * @param string $password
304
-	 * @return DataResponse
305
-	 */
306
-	public function confirmPassword($password) {
307
-		$currentDelay = $this->throttler->getDelay($this->request->getRemoteAddress(), 'sudo');
308
-		$this->throttler->sleepDelay($this->request->getRemoteAddress(), 'sudo');
297
+    /**
298
+     * @NoAdminRequired
299
+     * @UseSession
300
+     *
301
+     * @license GNU AGPL version 3 or any later version
302
+     *
303
+     * @param string $password
304
+     * @return DataResponse
305
+     */
306
+    public function confirmPassword($password) {
307
+        $currentDelay = $this->throttler->getDelay($this->request->getRemoteAddress(), 'sudo');
308
+        $this->throttler->sleepDelay($this->request->getRemoteAddress(), 'sudo');
309 309
 
310
-		$loginName = $this->userSession->getLoginName();
311
-		$loginResult = $this->userManager->checkPassword($loginName, $password);
312
-		if ($loginResult === false) {
313
-			$this->throttler->registerAttempt('sudo', $this->request->getRemoteAddress(), ['user' => $loginName]);
314
-			if ($currentDelay === 0) {
315
-				$this->throttler->sleepDelay($this->request->getRemoteAddress(), 'sudo');
316
-			}
310
+        $loginName = $this->userSession->getLoginName();
311
+        $loginResult = $this->userManager->checkPassword($loginName, $password);
312
+        if ($loginResult === false) {
313
+            $this->throttler->registerAttempt('sudo', $this->request->getRemoteAddress(), ['user' => $loginName]);
314
+            if ($currentDelay === 0) {
315
+                $this->throttler->sleepDelay($this->request->getRemoteAddress(), 'sudo');
316
+            }
317 317
 
318
-			return new DataResponse([], Http::STATUS_FORBIDDEN);
319
-		}
318
+            return new DataResponse([], Http::STATUS_FORBIDDEN);
319
+        }
320 320
 
321
-		$confirmTimestamp = time();
322
-		$this->session->set('last-password-confirm', $confirmTimestamp);
323
-		return new DataResponse(['lastLogin' => $confirmTimestamp], Http::STATUS_OK);
324
-	}
321
+        $confirmTimestamp = time();
322
+        $this->session->set('last-password-confirm', $confirmTimestamp);
323
+        return new DataResponse(['lastLogin' => $confirmTimestamp], Http::STATUS_OK);
324
+    }
325 325
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -207,7 +207,7 @@  discard block
 block discarded – undo
207 207
 	 * @return RedirectResponse
208 208
 	 */
209 209
 	public function tryLogin($user, $password, $redirect_url, $remember_login = false, $timezone = '', $timezone_offset = '') {
210
-		if(!is_string($user)) {
210
+		if (!is_string($user)) {
211 211
 			throw new \InvalidArgumentException('Username must be string');
212 212
 		}
213 213
 		$currentDelay = $this->throttler->getDelay($this->request->getRemoteAddress(), 'login');
@@ -216,7 +216,7 @@  discard block
 block discarded – undo
216 216
 		// If the user is already logged in and the CSRF check does not pass then
217 217
 		// simply redirect the user to the correct page as required. This is the
218 218
 		// case when an user has already logged-in, in another tab.
219
-		if(!$this->request->passesCSRFCheck()) {
219
+		if (!$this->request->passesCSRFCheck()) {
220 220
 			return $this->generateRedirect($redirect_url);
221 221
 		}
222 222
 
@@ -238,7 +238,7 @@  discard block
 block discarded – undo
238 238
 		}
239 239
 		if ($loginResult === false) {
240 240
 			$this->throttler->registerAttempt('login', $this->request->getRemoteAddress(), ['user' => $originalUser]);
241
-			if($currentDelay === 0) {
241
+			if ($currentDelay === 0) {
242 242
 				$this->throttler->sleepDelay($this->request->getRemoteAddress(), 'login');
243 243
 			}
244 244
 			$this->session->set('loginMessages', [
@@ -251,7 +251,7 @@  discard block
 block discarded – undo
251 251
 		// TODO: remove password checks from above and let the user session handle failures
252 252
 		// requires https://github.com/owncloud/core/pull/24616
253 253
 		$this->userSession->completeLogin($loginResult, ['loginName' => $user, 'password' => $password]);
254
-		$this->userSession->createSessionToken($this->request, $loginResult->getUID(), $user, $password, (int)$remember_login);
254
+		$this->userSession->createSessionToken($this->request, $loginResult->getUID(), $user, $password, (int) $remember_login);
255 255
 
256 256
 		// User has successfully logged in, now remove the password reset link, when it is available
257 257
 		$this->config->deleteUserValue($loginResult->getUID(), 'core', 'lostpassword');
Please login to merge, or discard this patch.
lib/private/Log.php 1 patch
Indentation   +298 added lines, -298 removed lines patch added patch discarded remove patch
@@ -49,302 +49,302 @@
 block discarded – undo
49 49
 
50 50
 class Log implements ILogger {
51 51
 
52
-	/** @var string */
53
-	private $logger;
54
-
55
-	/** @var SystemConfig */
56
-	private $config;
57
-
58
-	/** @var boolean|null cache the result of the log condition check for the request */
59
-	private $logConditionSatisfied = null;
60
-
61
-	/** @var Normalizer */
62
-	private $normalizer;
63
-
64
-	protected $methodsWithSensitiveParameters = [
65
-		// Session/User
66
-		'completeLogin',
67
-		'login',
68
-		'checkPassword',
69
-		'loginWithPassword',
70
-		'updatePrivateKeyPassword',
71
-		'validateUserPass',
72
-
73
-		// TokenProvider
74
-		'getToken',
75
-		'isTokenPassword',
76
-		'getPassword',
77
-		'decryptPassword',
78
-		'logClientIn',
79
-		'generateToken',
80
-		'validateToken',
81
-
82
-		// TwoFactorAuth
83
-		'solveChallenge',
84
-		'verifyChallenge',
85
-
86
-		//ICrypto
87
-		'calculateHMAC',
88
-		'encrypt',
89
-		'decrypt',
90
-
91
-		//LoginController
92
-		'tryLogin',
93
-		'confirmPassword',
94
-	];
95
-
96
-	/**
97
-	 * @param string $logger The logger that should be used
98
-	 * @param SystemConfig $config the system config object
99
-	 * @param null $normalizer
100
-	 */
101
-	public function __construct($logger=null, SystemConfig $config=null, $normalizer = null) {
102
-		// FIXME: Add this for backwards compatibility, should be fixed at some point probably
103
-		if($config === null) {
104
-			$config = \OC::$server->getSystemConfig();
105
-		}
106
-
107
-		$this->config = $config;
108
-
109
-		// FIXME: Add this for backwards compatibility, should be fixed at some point probably
110
-		if($logger === null) {
111
-			$logType = $this->config->getValue('log_type', 'file');
112
-			$this->logger = static::getLogClass($logType);
113
-			call_user_func(array($this->logger, 'init'));
114
-		} else {
115
-			$this->logger = $logger;
116
-		}
117
-		if ($normalizer === null) {
118
-			$this->normalizer = new Normalizer();
119
-		} else {
120
-			$this->normalizer = $normalizer;
121
-		}
122
-
123
-	}
124
-
125
-	/**
126
-	 * System is unusable.
127
-	 *
128
-	 * @param string $message
129
-	 * @param array $context
130
-	 * @return void
131
-	 */
132
-	public function emergency($message, array $context = array()) {
133
-		$this->log(Util::FATAL, $message, $context);
134
-	}
135
-
136
-	/**
137
-	 * Action must be taken immediately.
138
-	 *
139
-	 * Example: Entire website down, database unavailable, etc. This should
140
-	 * trigger the SMS alerts and wake you up.
141
-	 *
142
-	 * @param string $message
143
-	 * @param array $context
144
-	 * @return void
145
-	 */
146
-	public function alert($message, array $context = array()) {
147
-		$this->log(Util::ERROR, $message, $context);
148
-	}
149
-
150
-	/**
151
-	 * Critical conditions.
152
-	 *
153
-	 * Example: Application component unavailable, unexpected exception.
154
-	 *
155
-	 * @param string $message
156
-	 * @param array $context
157
-	 * @return void
158
-	 */
159
-	public function critical($message, array $context = array()) {
160
-		$this->log(Util::ERROR, $message, $context);
161
-	}
162
-
163
-	/**
164
-	 * Runtime errors that do not require immediate action but should typically
165
-	 * be logged and monitored.
166
-	 *
167
-	 * @param string $message
168
-	 * @param array $context
169
-	 * @return void
170
-	 */
171
-	public function error($message, array $context = array()) {
172
-		$this->log(Util::ERROR, $message, $context);
173
-	}
174
-
175
-	/**
176
-	 * Exceptional occurrences that are not errors.
177
-	 *
178
-	 * Example: Use of deprecated APIs, poor use of an API, undesirable things
179
-	 * that are not necessarily wrong.
180
-	 *
181
-	 * @param string $message
182
-	 * @param array $context
183
-	 * @return void
184
-	 */
185
-	public function warning($message, array $context = array()) {
186
-		$this->log(Util::WARN, $message, $context);
187
-	}
188
-
189
-	/**
190
-	 * Normal but significant events.
191
-	 *
192
-	 * @param string $message
193
-	 * @param array $context
194
-	 * @return void
195
-	 */
196
-	public function notice($message, array $context = array()) {
197
-		$this->log(Util::INFO, $message, $context);
198
-	}
199
-
200
-	/**
201
-	 * Interesting events.
202
-	 *
203
-	 * Example: User logs in, SQL logs.
204
-	 *
205
-	 * @param string $message
206
-	 * @param array $context
207
-	 * @return void
208
-	 */
209
-	public function info($message, array $context = array()) {
210
-		$this->log(Util::INFO, $message, $context);
211
-	}
212
-
213
-	/**
214
-	 * Detailed debug information.
215
-	 *
216
-	 * @param string $message
217
-	 * @param array $context
218
-	 * @return void
219
-	 */
220
-	public function debug($message, array $context = array()) {
221
-		$this->log(Util::DEBUG, $message, $context);
222
-	}
223
-
224
-
225
-	/**
226
-	 * Logs with an arbitrary level.
227
-	 *
228
-	 * @param mixed $level
229
-	 * @param string $message
230
-	 * @param array $context
231
-	 * @return void
232
-	 */
233
-	public function log($level, $message, array $context = array()) {
234
-		$minLevel = min($this->config->getValue('loglevel', Util::WARN), Util::FATAL);
235
-		$logCondition = $this->config->getValue('log.condition', []);
236
-
237
-		array_walk($context, [$this->normalizer, 'format']);
238
-
239
-		if (isset($context['app'])) {
240
-			$app = $context['app'];
241
-
242
-			/**
243
-			 * check log condition based on the context of each log message
244
-			 * once this is met -> change the required log level to debug
245
-			 */
246
-			if(!empty($logCondition)
247
-				&& isset($logCondition['apps'])
248
-				&& in_array($app, $logCondition['apps'], true)) {
249
-				$minLevel = Util::DEBUG;
250
-			}
251
-
252
-		} else {
253
-			$app = 'no app in context';
254
-		}
255
-		// interpolate $message as defined in PSR-3
256
-		$replace = array();
257
-		foreach ($context as $key => $val) {
258
-			$replace['{' . $key . '}'] = $val;
259
-		}
260
-
261
-		// interpolate replacement values into the message and return
262
-		$message = strtr($message, $replace);
263
-
264
-		/**
265
-		 * check for a special log condition - this enables an increased log on
266
-		 * a per request/user base
267
-		 */
268
-		if($this->logConditionSatisfied === null) {
269
-			// default to false to just process this once per request
270
-			$this->logConditionSatisfied = false;
271
-			if(!empty($logCondition)) {
272
-
273
-				// check for secret token in the request
274
-				if(isset($logCondition['shared_secret'])) {
275
-					$request = \OC::$server->getRequest();
276
-
277
-					// if token is found in the request change set the log condition to satisfied
278
-					if($request && hash_equals($logCondition['shared_secret'], $request->getParam('log_secret', ''))) {
279
-						$this->logConditionSatisfied = true;
280
-					}
281
-				}
282
-
283
-				// check for user
284
-				if(isset($logCondition['users'])) {
285
-					$user = \OC::$server->getUserSession()->getUser();
286
-
287
-					// if the user matches set the log condition to satisfied
288
-					if($user !== null && in_array($user->getUID(), $logCondition['users'], true)) {
289
-						$this->logConditionSatisfied = true;
290
-					}
291
-				}
292
-			}
293
-		}
294
-
295
-		// if log condition is satisfied change the required log level to DEBUG
296
-		if($this->logConditionSatisfied) {
297
-			$minLevel = Util::DEBUG;
298
-		}
299
-
300
-		if ($level >= $minLevel) {
301
-			$logger = $this->logger;
302
-			call_user_func(array($logger, 'write'), $app, $message, $level);
303
-		}
304
-	}
305
-
306
-	/**
307
-	 * Logs an exception very detailed
308
-	 *
309
-	 * @param \Exception | \Throwable $exception
310
-	 * @param array $context
311
-	 * @return void
312
-	 * @since 8.2.0
313
-	 */
314
-	public function logException($exception, array $context = array()) {
315
-		$exception = array(
316
-			'Exception' => get_class($exception),
317
-			'Message' => $exception->getMessage(),
318
-			'Code' => $exception->getCode(),
319
-			'Trace' => $exception->getTraceAsString(),
320
-			'File' => $exception->getFile(),
321
-			'Line' => $exception->getLine(),
322
-		);
323
-		$exception['Trace'] = preg_replace('!(' . implode('|', $this->methodsWithSensitiveParameters) . ')\(.*\)!', '$1(*** sensitive parameters replaced ***)', $exception['Trace']);
324
-		$msg = isset($context['message']) ? $context['message'] : 'Exception';
325
-		$msg .= ': ' . json_encode($exception);
326
-		$this->error($msg, $context);
327
-	}
328
-
329
-	/**
330
-	 * @param string $logType
331
-	 * @return string
332
-	 * @internal
333
-	 */
334
-	public static function getLogClass($logType) {
335
-		switch (strtolower($logType)) {
336
-			case 'errorlog':
337
-				return \OC\Log\Errorlog::class;
338
-			case 'syslog':
339
-				return \OC\Log\Syslog::class;
340
-			case 'file':
341
-				return \OC\Log\File::class;
342
-
343
-			// Backwards compatibility for old and fallback for unknown log types
344
-			case 'owncloud':
345
-			case 'nextcloud':
346
-			default:
347
-				return \OC\Log\File::class;
348
-		}
349
-	}
52
+    /** @var string */
53
+    private $logger;
54
+
55
+    /** @var SystemConfig */
56
+    private $config;
57
+
58
+    /** @var boolean|null cache the result of the log condition check for the request */
59
+    private $logConditionSatisfied = null;
60
+
61
+    /** @var Normalizer */
62
+    private $normalizer;
63
+
64
+    protected $methodsWithSensitiveParameters = [
65
+        // Session/User
66
+        'completeLogin',
67
+        'login',
68
+        'checkPassword',
69
+        'loginWithPassword',
70
+        'updatePrivateKeyPassword',
71
+        'validateUserPass',
72
+
73
+        // TokenProvider
74
+        'getToken',
75
+        'isTokenPassword',
76
+        'getPassword',
77
+        'decryptPassword',
78
+        'logClientIn',
79
+        'generateToken',
80
+        'validateToken',
81
+
82
+        // TwoFactorAuth
83
+        'solveChallenge',
84
+        'verifyChallenge',
85
+
86
+        //ICrypto
87
+        'calculateHMAC',
88
+        'encrypt',
89
+        'decrypt',
90
+
91
+        //LoginController
92
+        'tryLogin',
93
+        'confirmPassword',
94
+    ];
95
+
96
+    /**
97
+     * @param string $logger The logger that should be used
98
+     * @param SystemConfig $config the system config object
99
+     * @param null $normalizer
100
+     */
101
+    public function __construct($logger=null, SystemConfig $config=null, $normalizer = null) {
102
+        // FIXME: Add this for backwards compatibility, should be fixed at some point probably
103
+        if($config === null) {
104
+            $config = \OC::$server->getSystemConfig();
105
+        }
106
+
107
+        $this->config = $config;
108
+
109
+        // FIXME: Add this for backwards compatibility, should be fixed at some point probably
110
+        if($logger === null) {
111
+            $logType = $this->config->getValue('log_type', 'file');
112
+            $this->logger = static::getLogClass($logType);
113
+            call_user_func(array($this->logger, 'init'));
114
+        } else {
115
+            $this->logger = $logger;
116
+        }
117
+        if ($normalizer === null) {
118
+            $this->normalizer = new Normalizer();
119
+        } else {
120
+            $this->normalizer = $normalizer;
121
+        }
122
+
123
+    }
124
+
125
+    /**
126
+     * System is unusable.
127
+     *
128
+     * @param string $message
129
+     * @param array $context
130
+     * @return void
131
+     */
132
+    public function emergency($message, array $context = array()) {
133
+        $this->log(Util::FATAL, $message, $context);
134
+    }
135
+
136
+    /**
137
+     * Action must be taken immediately.
138
+     *
139
+     * Example: Entire website down, database unavailable, etc. This should
140
+     * trigger the SMS alerts and wake you up.
141
+     *
142
+     * @param string $message
143
+     * @param array $context
144
+     * @return void
145
+     */
146
+    public function alert($message, array $context = array()) {
147
+        $this->log(Util::ERROR, $message, $context);
148
+    }
149
+
150
+    /**
151
+     * Critical conditions.
152
+     *
153
+     * Example: Application component unavailable, unexpected exception.
154
+     *
155
+     * @param string $message
156
+     * @param array $context
157
+     * @return void
158
+     */
159
+    public function critical($message, array $context = array()) {
160
+        $this->log(Util::ERROR, $message, $context);
161
+    }
162
+
163
+    /**
164
+     * Runtime errors that do not require immediate action but should typically
165
+     * be logged and monitored.
166
+     *
167
+     * @param string $message
168
+     * @param array $context
169
+     * @return void
170
+     */
171
+    public function error($message, array $context = array()) {
172
+        $this->log(Util::ERROR, $message, $context);
173
+    }
174
+
175
+    /**
176
+     * Exceptional occurrences that are not errors.
177
+     *
178
+     * Example: Use of deprecated APIs, poor use of an API, undesirable things
179
+     * that are not necessarily wrong.
180
+     *
181
+     * @param string $message
182
+     * @param array $context
183
+     * @return void
184
+     */
185
+    public function warning($message, array $context = array()) {
186
+        $this->log(Util::WARN, $message, $context);
187
+    }
188
+
189
+    /**
190
+     * Normal but significant events.
191
+     *
192
+     * @param string $message
193
+     * @param array $context
194
+     * @return void
195
+     */
196
+    public function notice($message, array $context = array()) {
197
+        $this->log(Util::INFO, $message, $context);
198
+    }
199
+
200
+    /**
201
+     * Interesting events.
202
+     *
203
+     * Example: User logs in, SQL logs.
204
+     *
205
+     * @param string $message
206
+     * @param array $context
207
+     * @return void
208
+     */
209
+    public function info($message, array $context = array()) {
210
+        $this->log(Util::INFO, $message, $context);
211
+    }
212
+
213
+    /**
214
+     * Detailed debug information.
215
+     *
216
+     * @param string $message
217
+     * @param array $context
218
+     * @return void
219
+     */
220
+    public function debug($message, array $context = array()) {
221
+        $this->log(Util::DEBUG, $message, $context);
222
+    }
223
+
224
+
225
+    /**
226
+     * Logs with an arbitrary level.
227
+     *
228
+     * @param mixed $level
229
+     * @param string $message
230
+     * @param array $context
231
+     * @return void
232
+     */
233
+    public function log($level, $message, array $context = array()) {
234
+        $minLevel = min($this->config->getValue('loglevel', Util::WARN), Util::FATAL);
235
+        $logCondition = $this->config->getValue('log.condition', []);
236
+
237
+        array_walk($context, [$this->normalizer, 'format']);
238
+
239
+        if (isset($context['app'])) {
240
+            $app = $context['app'];
241
+
242
+            /**
243
+             * check log condition based on the context of each log message
244
+             * once this is met -> change the required log level to debug
245
+             */
246
+            if(!empty($logCondition)
247
+                && isset($logCondition['apps'])
248
+                && in_array($app, $logCondition['apps'], true)) {
249
+                $minLevel = Util::DEBUG;
250
+            }
251
+
252
+        } else {
253
+            $app = 'no app in context';
254
+        }
255
+        // interpolate $message as defined in PSR-3
256
+        $replace = array();
257
+        foreach ($context as $key => $val) {
258
+            $replace['{' . $key . '}'] = $val;
259
+        }
260
+
261
+        // interpolate replacement values into the message and return
262
+        $message = strtr($message, $replace);
263
+
264
+        /**
265
+         * check for a special log condition - this enables an increased log on
266
+         * a per request/user base
267
+         */
268
+        if($this->logConditionSatisfied === null) {
269
+            // default to false to just process this once per request
270
+            $this->logConditionSatisfied = false;
271
+            if(!empty($logCondition)) {
272
+
273
+                // check for secret token in the request
274
+                if(isset($logCondition['shared_secret'])) {
275
+                    $request = \OC::$server->getRequest();
276
+
277
+                    // if token is found in the request change set the log condition to satisfied
278
+                    if($request && hash_equals($logCondition['shared_secret'], $request->getParam('log_secret', ''))) {
279
+                        $this->logConditionSatisfied = true;
280
+                    }
281
+                }
282
+
283
+                // check for user
284
+                if(isset($logCondition['users'])) {
285
+                    $user = \OC::$server->getUserSession()->getUser();
286
+
287
+                    // if the user matches set the log condition to satisfied
288
+                    if($user !== null && in_array($user->getUID(), $logCondition['users'], true)) {
289
+                        $this->logConditionSatisfied = true;
290
+                    }
291
+                }
292
+            }
293
+        }
294
+
295
+        // if log condition is satisfied change the required log level to DEBUG
296
+        if($this->logConditionSatisfied) {
297
+            $minLevel = Util::DEBUG;
298
+        }
299
+
300
+        if ($level >= $minLevel) {
301
+            $logger = $this->logger;
302
+            call_user_func(array($logger, 'write'), $app, $message, $level);
303
+        }
304
+    }
305
+
306
+    /**
307
+     * Logs an exception very detailed
308
+     *
309
+     * @param \Exception | \Throwable $exception
310
+     * @param array $context
311
+     * @return void
312
+     * @since 8.2.0
313
+     */
314
+    public function logException($exception, array $context = array()) {
315
+        $exception = array(
316
+            'Exception' => get_class($exception),
317
+            'Message' => $exception->getMessage(),
318
+            'Code' => $exception->getCode(),
319
+            'Trace' => $exception->getTraceAsString(),
320
+            'File' => $exception->getFile(),
321
+            'Line' => $exception->getLine(),
322
+        );
323
+        $exception['Trace'] = preg_replace('!(' . implode('|', $this->methodsWithSensitiveParameters) . ')\(.*\)!', '$1(*** sensitive parameters replaced ***)', $exception['Trace']);
324
+        $msg = isset($context['message']) ? $context['message'] : 'Exception';
325
+        $msg .= ': ' . json_encode($exception);
326
+        $this->error($msg, $context);
327
+    }
328
+
329
+    /**
330
+     * @param string $logType
331
+     * @return string
332
+     * @internal
333
+     */
334
+    public static function getLogClass($logType) {
335
+        switch (strtolower($logType)) {
336
+            case 'errorlog':
337
+                return \OC\Log\Errorlog::class;
338
+            case 'syslog':
339
+                return \OC\Log\Syslog::class;
340
+            case 'file':
341
+                return \OC\Log\File::class;
342
+
343
+            // Backwards compatibility for old and fallback for unknown log types
344
+            case 'owncloud':
345
+            case 'nextcloud':
346
+            default:
347
+                return \OC\Log\File::class;
348
+        }
349
+    }
350 350
 }
Please login to merge, or discard this patch.
lib/private/User/Session.php 2 patches
Indentation   +801 added lines, -801 removed lines patch added patch discarded remove patch
@@ -79,807 +79,807 @@
 block discarded – undo
79 79
  */
80 80
 class Session implements IUserSession, Emitter {
81 81
 
82
-	/** @var IUserManager|PublicEmitter $manager */
83
-	private $manager;
84
-
85
-	/** @var ISession $session */
86
-	private $session;
87
-
88
-	/** @var ITimeFactory */
89
-	private $timeFactory;
90
-
91
-	/** @var IProvider */
92
-	private $tokenProvider;
93
-
94
-	/** @var IConfig */
95
-	private $config;
96
-
97
-	/** @var User $activeUser */
98
-	protected $activeUser;
99
-
100
-	/** @var ISecureRandom */
101
-	private $random;
102
-
103
-	/** @var ILockdownManager  */
104
-	private $lockdownManager;
105
-
106
-	/**
107
-	 * @param IUserManager $manager
108
-	 * @param ISession $session
109
-	 * @param ITimeFactory $timeFactory
110
-	 * @param IProvider $tokenProvider
111
-	 * @param IConfig $config
112
-	 * @param ISecureRandom $random
113
-	 * @param ILockdownManager $lockdownManager
114
-	 */
115
-	public function __construct(IUserManager $manager,
116
-								ISession $session,
117
-								ITimeFactory $timeFactory,
118
-								$tokenProvider,
119
-								IConfig $config,
120
-								ISecureRandom $random,
121
-								ILockdownManager $lockdownManager
122
-	) {
123
-		$this->manager = $manager;
124
-		$this->session = $session;
125
-		$this->timeFactory = $timeFactory;
126
-		$this->tokenProvider = $tokenProvider;
127
-		$this->config = $config;
128
-		$this->random = $random;
129
-		$this->lockdownManager = $lockdownManager;
130
-	}
131
-
132
-	/**
133
-	 * @param IProvider $provider
134
-	 */
135
-	public function setTokenProvider(IProvider $provider) {
136
-		$this->tokenProvider = $provider;
137
-	}
138
-
139
-	/**
140
-	 * @param string $scope
141
-	 * @param string $method
142
-	 * @param callable $callback
143
-	 */
144
-	public function listen($scope, $method, callable $callback) {
145
-		$this->manager->listen($scope, $method, $callback);
146
-	}
147
-
148
-	/**
149
-	 * @param string $scope optional
150
-	 * @param string $method optional
151
-	 * @param callable $callback optional
152
-	 */
153
-	public function removeListener($scope = null, $method = null, callable $callback = null) {
154
-		$this->manager->removeListener($scope, $method, $callback);
155
-	}
156
-
157
-	/**
158
-	 * get the manager object
159
-	 *
160
-	 * @return Manager|PublicEmitter
161
-	 */
162
-	public function getManager() {
163
-		return $this->manager;
164
-	}
165
-
166
-	/**
167
-	 * get the session object
168
-	 *
169
-	 * @return ISession
170
-	 */
171
-	public function getSession() {
172
-		return $this->session;
173
-	}
174
-
175
-	/**
176
-	 * set the session object
177
-	 *
178
-	 * @param ISession $session
179
-	 */
180
-	public function setSession(ISession $session) {
181
-		if ($this->session instanceof ISession) {
182
-			$this->session->close();
183
-		}
184
-		$this->session = $session;
185
-		$this->activeUser = null;
186
-	}
187
-
188
-	/**
189
-	 * set the currently active user
190
-	 *
191
-	 * @param IUser|null $user
192
-	 */
193
-	public function setUser($user) {
194
-		if (is_null($user)) {
195
-			$this->session->remove('user_id');
196
-		} else {
197
-			$this->session->set('user_id', $user->getUID());
198
-		}
199
-		$this->activeUser = $user;
200
-	}
201
-
202
-	/**
203
-	 * get the current active user
204
-	 *
205
-	 * @return IUser|null Current user, otherwise null
206
-	 */
207
-	public function getUser() {
208
-		// FIXME: This is a quick'n dirty work-around for the incognito mode as
209
-		// described at https://github.com/owncloud/core/pull/12912#issuecomment-67391155
210
-		if (OC_User::isIncognitoMode()) {
211
-			return null;
212
-		}
213
-		if (is_null($this->activeUser)) {
214
-			$uid = $this->session->get('user_id');
215
-			if (is_null($uid)) {
216
-				return null;
217
-			}
218
-			$this->activeUser = $this->manager->get($uid);
219
-			if (is_null($this->activeUser)) {
220
-				return null;
221
-			}
222
-			$this->validateSession();
223
-		}
224
-		return $this->activeUser;
225
-	}
226
-
227
-	/**
228
-	 * Validate whether the current session is valid
229
-	 *
230
-	 * - For token-authenticated clients, the token validity is checked
231
-	 * - For browsers, the session token validity is checked
232
-	 */
233
-	protected function validateSession() {
234
-		$token = null;
235
-		$appPassword = $this->session->get('app_password');
236
-
237
-		if (is_null($appPassword)) {
238
-			try {
239
-				$token = $this->session->getId();
240
-			} catch (SessionNotAvailableException $ex) {
241
-				return;
242
-			}
243
-		} else {
244
-			$token = $appPassword;
245
-		}
246
-
247
-		if (!$this->validateToken($token)) {
248
-			// Session was invalidated
249
-			$this->logout();
250
-		}
251
-	}
252
-
253
-	/**
254
-	 * Checks whether the user is logged in
255
-	 *
256
-	 * @return bool if logged in
257
-	 */
258
-	public function isLoggedIn() {
259
-		$user = $this->getUser();
260
-		if (is_null($user)) {
261
-			return false;
262
-		}
263
-
264
-		return $user->isEnabled();
265
-	}
266
-
267
-	/**
268
-	 * set the login name
269
-	 *
270
-	 * @param string|null $loginName for the logged in user
271
-	 */
272
-	public function setLoginName($loginName) {
273
-		if (is_null($loginName)) {
274
-			$this->session->remove('loginname');
275
-		} else {
276
-			$this->session->set('loginname', $loginName);
277
-		}
278
-	}
279
-
280
-	/**
281
-	 * get the login name of the current user
282
-	 *
283
-	 * @return string
284
-	 */
285
-	public function getLoginName() {
286
-		if ($this->activeUser) {
287
-			return $this->session->get('loginname');
288
-		} else {
289
-			$uid = $this->session->get('user_id');
290
-			if ($uid) {
291
-				$this->activeUser = $this->manager->get($uid);
292
-				return $this->session->get('loginname');
293
-			} else {
294
-				return null;
295
-			}
296
-		}
297
-	}
298
-
299
-	/**
300
-	 * set the token id
301
-	 *
302
-	 * @param int|null $token that was used to log in
303
-	 */
304
-	protected function setToken($token) {
305
-		if ($token === null) {
306
-			$this->session->remove('token-id');
307
-		} else {
308
-			$this->session->set('token-id', $token);
309
-		}
310
-	}
311
-
312
-	/**
313
-	 * try to log in with the provided credentials
314
-	 *
315
-	 * @param string $uid
316
-	 * @param string $password
317
-	 * @return boolean|null
318
-	 * @throws LoginException
319
-	 */
320
-	public function login($uid, $password) {
321
-		$this->session->regenerateId();
322
-		if ($this->validateToken($password, $uid)) {
323
-			return $this->loginWithToken($password);
324
-		}
325
-		return $this->loginWithPassword($uid, $password);
326
-	}
327
-
328
-	/**
329
-	 * @param IUser $user
330
-	 * @param array $loginDetails
331
-	 * @param bool $regenerateSessionId
332
-	 * @return bool
333
-	 * @throws LoginException
334
-	 */
335
-	public function completeLogin(IUser $user, array $loginDetails, $regenerateSessionId = true) {
336
-		if (!$user->isEnabled()) {
337
-			// disabled users can not log in
338
-			// injecting l10n does not work - there is a circular dependency between session and \OCP\L10N\IFactory
339
-			$message = \OC::$server->getL10N('lib')->t('User disabled');
340
-			throw new LoginException($message);
341
-		}
342
-
343
-		if($regenerateSessionId) {
344
-			$this->session->regenerateId();
345
-		}
346
-
347
-		$this->setUser($user);
348
-		$this->setLoginName($loginDetails['loginName']);
349
-
350
-		if(isset($loginDetails['token']) && $loginDetails['token'] instanceof IToken) {
351
-			$this->setToken($loginDetails['token']->getId());
352
-			$this->lockdownManager->setToken($loginDetails['token']);
353
-			$firstTimeLogin = false;
354
-		} else {
355
-			$this->setToken(null);
356
-			$firstTimeLogin = $user->updateLastLoginTimestamp();
357
-		}
358
-		$this->manager->emit('\OC\User', 'postLogin', [$user, $loginDetails['password']]);
359
-		if($this->isLoggedIn()) {
360
-			$this->prepareUserLogin($firstTimeLogin);
361
-			return true;
362
-		} else {
363
-			$message = \OC::$server->getL10N('lib')->t('Login canceled by app');
364
-			throw new LoginException($message);
365
-		}
366
-	}
367
-
368
-	/**
369
-	 * Tries to log in a client
370
-	 *
371
-	 * Checks token auth enforced
372
-	 * Checks 2FA enabled
373
-	 *
374
-	 * @param string $user
375
-	 * @param string $password
376
-	 * @param IRequest $request
377
-	 * @param OC\Security\Bruteforce\Throttler $throttler
378
-	 * @throws LoginException
379
-	 * @throws PasswordLoginForbiddenException
380
-	 * @return boolean
381
-	 */
382
-	public function logClientIn($user,
383
-								$password,
384
-								IRequest $request,
385
-								OC\Security\Bruteforce\Throttler $throttler) {
386
-		$currentDelay = $throttler->sleepDelay($request->getRemoteAddress(), 'login');
387
-
388
-		if ($this->manager instanceof PublicEmitter) {
389
-			$this->manager->emit('\OC\User', 'preLogin', array($user, $password));
390
-		}
391
-
392
-		$isTokenPassword = $this->isTokenPassword($password);
393
-		if (!$isTokenPassword && $this->isTokenAuthEnforced()) {
394
-			throw new PasswordLoginForbiddenException();
395
-		}
396
-		if (!$isTokenPassword && $this->isTwoFactorEnforced($user)) {
397
-			throw new PasswordLoginForbiddenException();
398
-		}
399
-		if (!$this->login($user, $password) ) {
400
-			$users = $this->manager->getByEmail($user);
401
-			if (count($users) === 1) {
402
-				return $this->login($users[0]->getUID(), $password);
403
-			}
404
-
405
-			$throttler->registerAttempt('login', $request->getRemoteAddress(), ['uid' => $user]);
406
-			if($currentDelay === 0) {
407
-				$throttler->sleepDelay($request->getRemoteAddress(), 'login');
408
-			}
409
-			return false;
410
-		}
411
-
412
-		if ($isTokenPassword) {
413
-			$this->session->set('app_password', $password);
414
-		} else if($this->supportsCookies($request)) {
415
-			// Password login, but cookies supported -> create (browser) session token
416
-			$this->createSessionToken($request, $this->getUser()->getUID(), $user, $password);
417
-		}
418
-
419
-		return true;
420
-	}
421
-
422
-	protected function supportsCookies(IRequest $request) {
423
-		if (!is_null($request->getCookie('cookie_test'))) {
424
-			return true;
425
-		}
426
-		setcookie('cookie_test', 'test', $this->timeFactory->getTime() + 3600);
427
-		return false;
428
-	}
429
-
430
-	private function isTokenAuthEnforced() {
431
-		return $this->config->getSystemValue('token_auth_enforced', false);
432
-	}
433
-
434
-	protected function isTwoFactorEnforced($username) {
435
-		Util::emitHook(
436
-			'\OCA\Files_Sharing\API\Server2Server',
437
-			'preLoginNameUsedAsUserName',
438
-			array('uid' => &$username)
439
-		);
440
-		$user = $this->manager->get($username);
441
-		if (is_null($user)) {
442
-			$users = $this->manager->getByEmail($username);
443
-			if (empty($users)) {
444
-				return false;
445
-			}
446
-			if (count($users) !== 1) {
447
-				return true;
448
-			}
449
-			$user = $users[0];
450
-		}
451
-		// DI not possible due to cyclic dependencies :'-/
452
-		return OC::$server->getTwoFactorAuthManager()->isTwoFactorAuthenticated($user);
453
-	}
454
-
455
-	/**
456
-	 * Check if the given 'password' is actually a device token
457
-	 *
458
-	 * @param string $password
459
-	 * @return boolean
460
-	 */
461
-	public function isTokenPassword($password) {
462
-		try {
463
-			$this->tokenProvider->getToken($password);
464
-			return true;
465
-		} catch (InvalidTokenException $ex) {
466
-			return false;
467
-		}
468
-	}
469
-
470
-	protected function prepareUserLogin($firstTimeLogin) {
471
-		// TODO: mock/inject/use non-static
472
-		// Refresh the token
473
-		\OC::$server->getCsrfTokenManager()->refreshToken();
474
-		//we need to pass the user name, which may differ from login name
475
-		$user = $this->getUser()->getUID();
476
-		OC_Util::setupFS($user);
477
-
478
-		if ($firstTimeLogin) {
479
-			// TODO: lock necessary?
480
-			//trigger creation of user home and /files folder
481
-			$userFolder = \OC::$server->getUserFolder($user);
482
-
483
-			// copy skeleton
484
-			\OC_Util::copySkeleton($user, $userFolder);
485
-
486
-			// trigger any other initialization
487
-			\OC::$server->getEventDispatcher()->dispatch(IUser::class . '::firstLogin', new GenericEvent($this->getUser()));
488
-		}
489
-	}
490
-
491
-	/**
492
-	 * Tries to login the user with HTTP Basic Authentication
493
-	 *
494
-	 * @todo do not allow basic auth if the user is 2FA enforced
495
-	 * @param IRequest $request
496
-	 * @param OC\Security\Bruteforce\Throttler $throttler
497
-	 * @return boolean if the login was successful
498
-	 */
499
-	public function tryBasicAuthLogin(IRequest $request,
500
-									  OC\Security\Bruteforce\Throttler $throttler) {
501
-		if (!empty($request->server['PHP_AUTH_USER']) && !empty($request->server['PHP_AUTH_PW'])) {
502
-			try {
503
-				if ($this->logClientIn($request->server['PHP_AUTH_USER'], $request->server['PHP_AUTH_PW'], $request, $throttler)) {
504
-					/**
505
-					 * Add DAV authenticated. This should in an ideal world not be
506
-					 * necessary but the iOS App reads cookies from anywhere instead
507
-					 * only the DAV endpoint.
508
-					 * This makes sure that the cookies will be valid for the whole scope
509
-					 * @see https://github.com/owncloud/core/issues/22893
510
-					 */
511
-					$this->session->set(
512
-						Auth::DAV_AUTHENTICATED, $this->getUser()->getUID()
513
-					);
514
-
515
-					// Set the last-password-confirm session to make the sudo mode work
516
-					 $this->session->set('last-password-confirm', $this->timeFactory->getTime());
517
-
518
-					return true;
519
-				}
520
-			} catch (PasswordLoginForbiddenException $ex) {
521
-				// Nothing to do
522
-			}
523
-		}
524
-		return false;
525
-	}
526
-
527
-	/**
528
-	 * Log an user in via login name and password
529
-	 *
530
-	 * @param string $uid
531
-	 * @param string $password
532
-	 * @return boolean
533
-	 * @throws LoginException if an app canceld the login process or the user is not enabled
534
-	 */
535
-	private function loginWithPassword($uid, $password) {
536
-		$user = $this->manager->checkPassword($uid, $password);
537
-		if ($user === false) {
538
-			// Password check failed
539
-			return false;
540
-		}
541
-
542
-		return $this->completeLogin($user, ['loginName' => $uid, 'password' => $password], false);
543
-	}
544
-
545
-	/**
546
-	 * Log an user in with a given token (id)
547
-	 *
548
-	 * @param string $token
549
-	 * @return boolean
550
-	 * @throws LoginException if an app canceled the login process or the user is not enabled
551
-	 */
552
-	private function loginWithToken($token) {
553
-		try {
554
-			$dbToken = $this->tokenProvider->getToken($token);
555
-		} catch (InvalidTokenException $ex) {
556
-			return false;
557
-		}
558
-		$uid = $dbToken->getUID();
559
-
560
-		// When logging in with token, the password must be decrypted first before passing to login hook
561
-		$password = '';
562
-		try {
563
-			$password = $this->tokenProvider->getPassword($dbToken, $token);
564
-		} catch (PasswordlessTokenException $ex) {
565
-			// Ignore and use empty string instead
566
-		}
567
-
568
-		$this->manager->emit('\OC\User', 'preLogin', array($uid, $password));
569
-
570
-		$user = $this->manager->get($uid);
571
-		if (is_null($user)) {
572
-			// user does not exist
573
-			return false;
574
-		}
575
-
576
-		return $this->completeLogin(
577
-			$user,
578
-			[
579
-				'loginName' => $dbToken->getLoginName(),
580
-				'password' => $password,
581
-				'token' => $dbToken
582
-			],
583
-			false);
584
-	}
585
-
586
-	/**
587
-	 * Create a new session token for the given user credentials
588
-	 *
589
-	 * @param IRequest $request
590
-	 * @param string $uid user UID
591
-	 * @param string $loginName login name
592
-	 * @param string $password
593
-	 * @param int $remember
594
-	 * @return boolean
595
-	 */
596
-	public function createSessionToken(IRequest $request, $uid, $loginName, $password = null, $remember = IToken::DO_NOT_REMEMBER) {
597
-		if (is_null($this->manager->get($uid))) {
598
-			// User does not exist
599
-			return false;
600
-		}
601
-		$name = isset($request->server['HTTP_USER_AGENT']) ? $request->server['HTTP_USER_AGENT'] : 'unknown browser';
602
-		try {
603
-			$sessionId = $this->session->getId();
604
-			$pwd = $this->getPassword($password);
605
-			$this->tokenProvider->generateToken($sessionId, $uid, $loginName, $pwd, $name, IToken::TEMPORARY_TOKEN, $remember);
606
-			return true;
607
-		} catch (SessionNotAvailableException $ex) {
608
-			// This can happen with OCC, where a memory session is used
609
-			// if a memory session is used, we shouldn't create a session token anyway
610
-			return false;
611
-		}
612
-	}
613
-
614
-	/**
615
-	 * Checks if the given password is a token.
616
-	 * If yes, the password is extracted from the token.
617
-	 * If no, the same password is returned.
618
-	 *
619
-	 * @param string $password either the login password or a device token
620
-	 * @return string|null the password or null if none was set in the token
621
-	 */
622
-	private function getPassword($password) {
623
-		if (is_null($password)) {
624
-			// This is surely no token ;-)
625
-			return null;
626
-		}
627
-		try {
628
-			$token = $this->tokenProvider->getToken($password);
629
-			try {
630
-				return $this->tokenProvider->getPassword($token, $password);
631
-			} catch (PasswordlessTokenException $ex) {
632
-				return null;
633
-			}
634
-		} catch (InvalidTokenException $ex) {
635
-			return $password;
636
-		}
637
-	}
638
-
639
-	/**
640
-	 * @param IToken $dbToken
641
-	 * @param string $token
642
-	 * @return boolean
643
-	 */
644
-	private function checkTokenCredentials(IToken $dbToken, $token) {
645
-		// Check whether login credentials are still valid and the user was not disabled
646
-		// This check is performed each 5 minutes
647
-		$lastCheck = $dbToken->getLastCheck() ? : 0;
648
-		$now = $this->timeFactory->getTime();
649
-		if ($lastCheck > ($now - 60 * 5)) {
650
-			// Checked performed recently, nothing to do now
651
-			return true;
652
-		}
653
-
654
-		try {
655
-			$pwd = $this->tokenProvider->getPassword($dbToken, $token);
656
-		} catch (InvalidTokenException $ex) {
657
-			// An invalid token password was used -> log user out
658
-			return false;
659
-		} catch (PasswordlessTokenException $ex) {
660
-			// Token has no password
661
-
662
-			if (!is_null($this->activeUser) && !$this->activeUser->isEnabled()) {
663
-				$this->tokenProvider->invalidateToken($token);
664
-				return false;
665
-			}
666
-
667
-			$dbToken->setLastCheck($now);
668
-			return true;
669
-		}
670
-
671
-		if ($this->manager->checkPassword($dbToken->getLoginName(), $pwd) === false
672
-			|| (!is_null($this->activeUser) && !$this->activeUser->isEnabled())) {
673
-			$this->tokenProvider->invalidateToken($token);
674
-			// Password has changed or user was disabled -> log user out
675
-			return false;
676
-		}
677
-		$dbToken->setLastCheck($now);
678
-		return true;
679
-	}
680
-
681
-	/**
682
-	 * Check if the given token exists and performs password/user-enabled checks
683
-	 *
684
-	 * Invalidates the token if checks fail
685
-	 *
686
-	 * @param string $token
687
-	 * @param string $user login name
688
-	 * @return boolean
689
-	 */
690
-	private function validateToken($token, $user = null) {
691
-		try {
692
-			$dbToken = $this->tokenProvider->getToken($token);
693
-		} catch (InvalidTokenException $ex) {
694
-			return false;
695
-		}
696
-
697
-		// Check if login names match
698
-		if (!is_null($user) && $dbToken->getLoginName() !== $user) {
699
-			// TODO: this makes it imposssible to use different login names on browser and client
700
-			// e.g. login by e-mail '[email protected]' on browser for generating the token will not
701
-			//      allow to use the client token with the login name 'user'.
702
-			return false;
703
-		}
704
-
705
-		if (!$this->checkTokenCredentials($dbToken, $token)) {
706
-			return false;
707
-		}
708
-
709
-		$this->tokenProvider->updateTokenActivity($dbToken);
710
-
711
-		return true;
712
-	}
713
-
714
-	/**
715
-	 * Tries to login the user with auth token header
716
-	 *
717
-	 * @param IRequest $request
718
-	 * @todo check remember me cookie
719
-	 * @return boolean
720
-	 */
721
-	public function tryTokenLogin(IRequest $request) {
722
-		$authHeader = $request->getHeader('Authorization');
723
-		if (strpos($authHeader, 'token ') === false) {
724
-			// No auth header, let's try session id
725
-			try {
726
-				$token = $this->session->getId();
727
-			} catch (SessionNotAvailableException $ex) {
728
-				return false;
729
-			}
730
-		} else {
731
-			$token = substr($authHeader, 6);
732
-		}
733
-
734
-		if (!$this->loginWithToken($token)) {
735
-			return false;
736
-		}
737
-		if(!$this->validateToken($token)) {
738
-			return false;
739
-		}
740
-		return true;
741
-	}
742
-
743
-	/**
744
-	 * perform login using the magic cookie (remember login)
745
-	 *
746
-	 * @param string $uid the username
747
-	 * @param string $currentToken
748
-	 * @param string $oldSessionId
749
-	 * @return bool
750
-	 */
751
-	public function loginWithCookie($uid, $currentToken, $oldSessionId) {
752
-		$this->session->regenerateId();
753
-		$this->manager->emit('\OC\User', 'preRememberedLogin', array($uid));
754
-		$user = $this->manager->get($uid);
755
-		if (is_null($user)) {
756
-			// user does not exist
757
-			return false;
758
-		}
759
-
760
-		// get stored tokens
761
-		$tokens = $this->config->getUserKeys($uid, 'login_token');
762
-		// test cookies token against stored tokens
763
-		if (!in_array($currentToken, $tokens, true)) {
764
-			return false;
765
-		}
766
-		// replace successfully used token with a new one
767
-		$this->config->deleteUserValue($uid, 'login_token', $currentToken);
768
-		$newToken = $this->random->generate(32);
769
-		$this->config->setUserValue($uid, 'login_token', $newToken, $this->timeFactory->getTime());
770
-
771
-		try {
772
-			$sessionId = $this->session->getId();
773
-			$this->tokenProvider->renewSessionToken($oldSessionId, $sessionId);
774
-		} catch (SessionNotAvailableException $ex) {
775
-			return false;
776
-		} catch (InvalidTokenException $ex) {
777
-			\OC::$server->getLogger()->warning('Renewing session token failed', ['app' => 'core']);
778
-			return false;
779
-		}
780
-
781
-		$this->setMagicInCookie($user->getUID(), $newToken);
782
-		$token = $this->tokenProvider->getToken($sessionId);
783
-
784
-		//login
785
-		$this->setUser($user);
786
-		$this->setLoginName($token->getLoginName());
787
-		$this->setToken($token->getId());
788
-		$this->lockdownManager->setToken($token);
789
-		$user->updateLastLoginTimestamp();
790
-		$this->manager->emit('\OC\User', 'postRememberedLogin', [$user]);
791
-		return true;
792
-	}
793
-
794
-	/**
795
-	 * @param IUser $user
796
-	 */
797
-	public function createRememberMeToken(IUser $user) {
798
-		$token = $this->random->generate(32);
799
-		$this->config->setUserValue($user->getUID(), 'login_token', $token, $this->timeFactory->getTime());
800
-		$this->setMagicInCookie($user->getUID(), $token);
801
-	}
802
-
803
-	/**
804
-	 * logout the user from the session
805
-	 */
806
-	public function logout() {
807
-		$this->manager->emit('\OC\User', 'logout');
808
-		$user = $this->getUser();
809
-		if (!is_null($user)) {
810
-			try {
811
-				$this->tokenProvider->invalidateToken($this->session->getId());
812
-			} catch (SessionNotAvailableException $ex) {
813
-
814
-			}
815
-		}
816
-		$this->setUser(null);
817
-		$this->setLoginName(null);
818
-		$this->setToken(null);
819
-		$this->unsetMagicInCookie();
820
-		$this->session->clear();
821
-		$this->manager->emit('\OC\User', 'postLogout');
822
-	}
823
-
824
-	/**
825
-	 * Set cookie value to use in next page load
826
-	 *
827
-	 * @param string $username username to be set
828
-	 * @param string $token
829
-	 */
830
-	public function setMagicInCookie($username, $token) {
831
-		$secureCookie = OC::$server->getRequest()->getServerProtocol() === 'https';
832
-		$webRoot = \OC::$WEBROOT;
833
-		if ($webRoot === '') {
834
-			$webRoot = '/';
835
-		}
836
-
837
-		$expires = $this->timeFactory->getTime() + $this->config->getSystemValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15);
838
-		setcookie('nc_username', $username, $expires, $webRoot, '', $secureCookie, true);
839
-		setcookie('nc_token', $token, $expires, $webRoot, '', $secureCookie, true);
840
-		try {
841
-			setcookie('nc_session_id', $this->session->getId(), $expires, $webRoot, '', $secureCookie, true);
842
-		} catch (SessionNotAvailableException $ex) {
843
-			// ignore
844
-		}
845
-	}
846
-
847
-	/**
848
-	 * Remove cookie for "remember username"
849
-	 */
850
-	public function unsetMagicInCookie() {
851
-		//TODO: DI for cookies and IRequest
852
-		$secureCookie = OC::$server->getRequest()->getServerProtocol() === 'https';
853
-
854
-		unset($_COOKIE['nc_username']); //TODO: DI
855
-		unset($_COOKIE['nc_token']);
856
-		unset($_COOKIE['nc_session_id']);
857
-		setcookie('nc_username', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT, '', $secureCookie, true);
858
-		setcookie('nc_token', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT, '', $secureCookie, true);
859
-		setcookie('nc_session_id', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT, '', $secureCookie, true);
860
-		// old cookies might be stored under /webroot/ instead of /webroot
861
-		// and Firefox doesn't like it!
862
-		setcookie('nc_username', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
863
-		setcookie('nc_token', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
864
-		setcookie('nc_session_id', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
865
-	}
866
-
867
-	/**
868
-	 * Update password of the browser session token if there is one
869
-	 *
870
-	 * @param string $password
871
-	 */
872
-	public function updateSessionTokenPassword($password) {
873
-		try {
874
-			$sessionId = $this->session->getId();
875
-			$token = $this->tokenProvider->getToken($sessionId);
876
-			$this->tokenProvider->setPassword($token, $sessionId, $password);
877
-		} catch (SessionNotAvailableException $ex) {
878
-			// Nothing to do
879
-		} catch (InvalidTokenException $ex) {
880
-			// Nothing to do
881
-		}
882
-	}
82
+    /** @var IUserManager|PublicEmitter $manager */
83
+    private $manager;
84
+
85
+    /** @var ISession $session */
86
+    private $session;
87
+
88
+    /** @var ITimeFactory */
89
+    private $timeFactory;
90
+
91
+    /** @var IProvider */
92
+    private $tokenProvider;
93
+
94
+    /** @var IConfig */
95
+    private $config;
96
+
97
+    /** @var User $activeUser */
98
+    protected $activeUser;
99
+
100
+    /** @var ISecureRandom */
101
+    private $random;
102
+
103
+    /** @var ILockdownManager  */
104
+    private $lockdownManager;
105
+
106
+    /**
107
+     * @param IUserManager $manager
108
+     * @param ISession $session
109
+     * @param ITimeFactory $timeFactory
110
+     * @param IProvider $tokenProvider
111
+     * @param IConfig $config
112
+     * @param ISecureRandom $random
113
+     * @param ILockdownManager $lockdownManager
114
+     */
115
+    public function __construct(IUserManager $manager,
116
+                                ISession $session,
117
+                                ITimeFactory $timeFactory,
118
+                                $tokenProvider,
119
+                                IConfig $config,
120
+                                ISecureRandom $random,
121
+                                ILockdownManager $lockdownManager
122
+    ) {
123
+        $this->manager = $manager;
124
+        $this->session = $session;
125
+        $this->timeFactory = $timeFactory;
126
+        $this->tokenProvider = $tokenProvider;
127
+        $this->config = $config;
128
+        $this->random = $random;
129
+        $this->lockdownManager = $lockdownManager;
130
+    }
131
+
132
+    /**
133
+     * @param IProvider $provider
134
+     */
135
+    public function setTokenProvider(IProvider $provider) {
136
+        $this->tokenProvider = $provider;
137
+    }
138
+
139
+    /**
140
+     * @param string $scope
141
+     * @param string $method
142
+     * @param callable $callback
143
+     */
144
+    public function listen($scope, $method, callable $callback) {
145
+        $this->manager->listen($scope, $method, $callback);
146
+    }
147
+
148
+    /**
149
+     * @param string $scope optional
150
+     * @param string $method optional
151
+     * @param callable $callback optional
152
+     */
153
+    public function removeListener($scope = null, $method = null, callable $callback = null) {
154
+        $this->manager->removeListener($scope, $method, $callback);
155
+    }
156
+
157
+    /**
158
+     * get the manager object
159
+     *
160
+     * @return Manager|PublicEmitter
161
+     */
162
+    public function getManager() {
163
+        return $this->manager;
164
+    }
165
+
166
+    /**
167
+     * get the session object
168
+     *
169
+     * @return ISession
170
+     */
171
+    public function getSession() {
172
+        return $this->session;
173
+    }
174
+
175
+    /**
176
+     * set the session object
177
+     *
178
+     * @param ISession $session
179
+     */
180
+    public function setSession(ISession $session) {
181
+        if ($this->session instanceof ISession) {
182
+            $this->session->close();
183
+        }
184
+        $this->session = $session;
185
+        $this->activeUser = null;
186
+    }
187
+
188
+    /**
189
+     * set the currently active user
190
+     *
191
+     * @param IUser|null $user
192
+     */
193
+    public function setUser($user) {
194
+        if (is_null($user)) {
195
+            $this->session->remove('user_id');
196
+        } else {
197
+            $this->session->set('user_id', $user->getUID());
198
+        }
199
+        $this->activeUser = $user;
200
+    }
201
+
202
+    /**
203
+     * get the current active user
204
+     *
205
+     * @return IUser|null Current user, otherwise null
206
+     */
207
+    public function getUser() {
208
+        // FIXME: This is a quick'n dirty work-around for the incognito mode as
209
+        // described at https://github.com/owncloud/core/pull/12912#issuecomment-67391155
210
+        if (OC_User::isIncognitoMode()) {
211
+            return null;
212
+        }
213
+        if (is_null($this->activeUser)) {
214
+            $uid = $this->session->get('user_id');
215
+            if (is_null($uid)) {
216
+                return null;
217
+            }
218
+            $this->activeUser = $this->manager->get($uid);
219
+            if (is_null($this->activeUser)) {
220
+                return null;
221
+            }
222
+            $this->validateSession();
223
+        }
224
+        return $this->activeUser;
225
+    }
226
+
227
+    /**
228
+     * Validate whether the current session is valid
229
+     *
230
+     * - For token-authenticated clients, the token validity is checked
231
+     * - For browsers, the session token validity is checked
232
+     */
233
+    protected function validateSession() {
234
+        $token = null;
235
+        $appPassword = $this->session->get('app_password');
236
+
237
+        if (is_null($appPassword)) {
238
+            try {
239
+                $token = $this->session->getId();
240
+            } catch (SessionNotAvailableException $ex) {
241
+                return;
242
+            }
243
+        } else {
244
+            $token = $appPassword;
245
+        }
246
+
247
+        if (!$this->validateToken($token)) {
248
+            // Session was invalidated
249
+            $this->logout();
250
+        }
251
+    }
252
+
253
+    /**
254
+     * Checks whether the user is logged in
255
+     *
256
+     * @return bool if logged in
257
+     */
258
+    public function isLoggedIn() {
259
+        $user = $this->getUser();
260
+        if (is_null($user)) {
261
+            return false;
262
+        }
263
+
264
+        return $user->isEnabled();
265
+    }
266
+
267
+    /**
268
+     * set the login name
269
+     *
270
+     * @param string|null $loginName for the logged in user
271
+     */
272
+    public function setLoginName($loginName) {
273
+        if (is_null($loginName)) {
274
+            $this->session->remove('loginname');
275
+        } else {
276
+            $this->session->set('loginname', $loginName);
277
+        }
278
+    }
279
+
280
+    /**
281
+     * get the login name of the current user
282
+     *
283
+     * @return string
284
+     */
285
+    public function getLoginName() {
286
+        if ($this->activeUser) {
287
+            return $this->session->get('loginname');
288
+        } else {
289
+            $uid = $this->session->get('user_id');
290
+            if ($uid) {
291
+                $this->activeUser = $this->manager->get($uid);
292
+                return $this->session->get('loginname');
293
+            } else {
294
+                return null;
295
+            }
296
+        }
297
+    }
298
+
299
+    /**
300
+     * set the token id
301
+     *
302
+     * @param int|null $token that was used to log in
303
+     */
304
+    protected function setToken($token) {
305
+        if ($token === null) {
306
+            $this->session->remove('token-id');
307
+        } else {
308
+            $this->session->set('token-id', $token);
309
+        }
310
+    }
311
+
312
+    /**
313
+     * try to log in with the provided credentials
314
+     *
315
+     * @param string $uid
316
+     * @param string $password
317
+     * @return boolean|null
318
+     * @throws LoginException
319
+     */
320
+    public function login($uid, $password) {
321
+        $this->session->regenerateId();
322
+        if ($this->validateToken($password, $uid)) {
323
+            return $this->loginWithToken($password);
324
+        }
325
+        return $this->loginWithPassword($uid, $password);
326
+    }
327
+
328
+    /**
329
+     * @param IUser $user
330
+     * @param array $loginDetails
331
+     * @param bool $regenerateSessionId
332
+     * @return bool
333
+     * @throws LoginException
334
+     */
335
+    public function completeLogin(IUser $user, array $loginDetails, $regenerateSessionId = true) {
336
+        if (!$user->isEnabled()) {
337
+            // disabled users can not log in
338
+            // injecting l10n does not work - there is a circular dependency between session and \OCP\L10N\IFactory
339
+            $message = \OC::$server->getL10N('lib')->t('User disabled');
340
+            throw new LoginException($message);
341
+        }
342
+
343
+        if($regenerateSessionId) {
344
+            $this->session->regenerateId();
345
+        }
346
+
347
+        $this->setUser($user);
348
+        $this->setLoginName($loginDetails['loginName']);
349
+
350
+        if(isset($loginDetails['token']) && $loginDetails['token'] instanceof IToken) {
351
+            $this->setToken($loginDetails['token']->getId());
352
+            $this->lockdownManager->setToken($loginDetails['token']);
353
+            $firstTimeLogin = false;
354
+        } else {
355
+            $this->setToken(null);
356
+            $firstTimeLogin = $user->updateLastLoginTimestamp();
357
+        }
358
+        $this->manager->emit('\OC\User', 'postLogin', [$user, $loginDetails['password']]);
359
+        if($this->isLoggedIn()) {
360
+            $this->prepareUserLogin($firstTimeLogin);
361
+            return true;
362
+        } else {
363
+            $message = \OC::$server->getL10N('lib')->t('Login canceled by app');
364
+            throw new LoginException($message);
365
+        }
366
+    }
367
+
368
+    /**
369
+     * Tries to log in a client
370
+     *
371
+     * Checks token auth enforced
372
+     * Checks 2FA enabled
373
+     *
374
+     * @param string $user
375
+     * @param string $password
376
+     * @param IRequest $request
377
+     * @param OC\Security\Bruteforce\Throttler $throttler
378
+     * @throws LoginException
379
+     * @throws PasswordLoginForbiddenException
380
+     * @return boolean
381
+     */
382
+    public function logClientIn($user,
383
+                                $password,
384
+                                IRequest $request,
385
+                                OC\Security\Bruteforce\Throttler $throttler) {
386
+        $currentDelay = $throttler->sleepDelay($request->getRemoteAddress(), 'login');
387
+
388
+        if ($this->manager instanceof PublicEmitter) {
389
+            $this->manager->emit('\OC\User', 'preLogin', array($user, $password));
390
+        }
391
+
392
+        $isTokenPassword = $this->isTokenPassword($password);
393
+        if (!$isTokenPassword && $this->isTokenAuthEnforced()) {
394
+            throw new PasswordLoginForbiddenException();
395
+        }
396
+        if (!$isTokenPassword && $this->isTwoFactorEnforced($user)) {
397
+            throw new PasswordLoginForbiddenException();
398
+        }
399
+        if (!$this->login($user, $password) ) {
400
+            $users = $this->manager->getByEmail($user);
401
+            if (count($users) === 1) {
402
+                return $this->login($users[0]->getUID(), $password);
403
+            }
404
+
405
+            $throttler->registerAttempt('login', $request->getRemoteAddress(), ['uid' => $user]);
406
+            if($currentDelay === 0) {
407
+                $throttler->sleepDelay($request->getRemoteAddress(), 'login');
408
+            }
409
+            return false;
410
+        }
411
+
412
+        if ($isTokenPassword) {
413
+            $this->session->set('app_password', $password);
414
+        } else if($this->supportsCookies($request)) {
415
+            // Password login, but cookies supported -> create (browser) session token
416
+            $this->createSessionToken($request, $this->getUser()->getUID(), $user, $password);
417
+        }
418
+
419
+        return true;
420
+    }
421
+
422
+    protected function supportsCookies(IRequest $request) {
423
+        if (!is_null($request->getCookie('cookie_test'))) {
424
+            return true;
425
+        }
426
+        setcookie('cookie_test', 'test', $this->timeFactory->getTime() + 3600);
427
+        return false;
428
+    }
429
+
430
+    private function isTokenAuthEnforced() {
431
+        return $this->config->getSystemValue('token_auth_enforced', false);
432
+    }
433
+
434
+    protected function isTwoFactorEnforced($username) {
435
+        Util::emitHook(
436
+            '\OCA\Files_Sharing\API\Server2Server',
437
+            'preLoginNameUsedAsUserName',
438
+            array('uid' => &$username)
439
+        );
440
+        $user = $this->manager->get($username);
441
+        if (is_null($user)) {
442
+            $users = $this->manager->getByEmail($username);
443
+            if (empty($users)) {
444
+                return false;
445
+            }
446
+            if (count($users) !== 1) {
447
+                return true;
448
+            }
449
+            $user = $users[0];
450
+        }
451
+        // DI not possible due to cyclic dependencies :'-/
452
+        return OC::$server->getTwoFactorAuthManager()->isTwoFactorAuthenticated($user);
453
+    }
454
+
455
+    /**
456
+     * Check if the given 'password' is actually a device token
457
+     *
458
+     * @param string $password
459
+     * @return boolean
460
+     */
461
+    public function isTokenPassword($password) {
462
+        try {
463
+            $this->tokenProvider->getToken($password);
464
+            return true;
465
+        } catch (InvalidTokenException $ex) {
466
+            return false;
467
+        }
468
+    }
469
+
470
+    protected function prepareUserLogin($firstTimeLogin) {
471
+        // TODO: mock/inject/use non-static
472
+        // Refresh the token
473
+        \OC::$server->getCsrfTokenManager()->refreshToken();
474
+        //we need to pass the user name, which may differ from login name
475
+        $user = $this->getUser()->getUID();
476
+        OC_Util::setupFS($user);
477
+
478
+        if ($firstTimeLogin) {
479
+            // TODO: lock necessary?
480
+            //trigger creation of user home and /files folder
481
+            $userFolder = \OC::$server->getUserFolder($user);
482
+
483
+            // copy skeleton
484
+            \OC_Util::copySkeleton($user, $userFolder);
485
+
486
+            // trigger any other initialization
487
+            \OC::$server->getEventDispatcher()->dispatch(IUser::class . '::firstLogin', new GenericEvent($this->getUser()));
488
+        }
489
+    }
490
+
491
+    /**
492
+     * Tries to login the user with HTTP Basic Authentication
493
+     *
494
+     * @todo do not allow basic auth if the user is 2FA enforced
495
+     * @param IRequest $request
496
+     * @param OC\Security\Bruteforce\Throttler $throttler
497
+     * @return boolean if the login was successful
498
+     */
499
+    public function tryBasicAuthLogin(IRequest $request,
500
+                                        OC\Security\Bruteforce\Throttler $throttler) {
501
+        if (!empty($request->server['PHP_AUTH_USER']) && !empty($request->server['PHP_AUTH_PW'])) {
502
+            try {
503
+                if ($this->logClientIn($request->server['PHP_AUTH_USER'], $request->server['PHP_AUTH_PW'], $request, $throttler)) {
504
+                    /**
505
+                     * Add DAV authenticated. This should in an ideal world not be
506
+                     * necessary but the iOS App reads cookies from anywhere instead
507
+                     * only the DAV endpoint.
508
+                     * This makes sure that the cookies will be valid for the whole scope
509
+                     * @see https://github.com/owncloud/core/issues/22893
510
+                     */
511
+                    $this->session->set(
512
+                        Auth::DAV_AUTHENTICATED, $this->getUser()->getUID()
513
+                    );
514
+
515
+                    // Set the last-password-confirm session to make the sudo mode work
516
+                        $this->session->set('last-password-confirm', $this->timeFactory->getTime());
517
+
518
+                    return true;
519
+                }
520
+            } catch (PasswordLoginForbiddenException $ex) {
521
+                // Nothing to do
522
+            }
523
+        }
524
+        return false;
525
+    }
526
+
527
+    /**
528
+     * Log an user in via login name and password
529
+     *
530
+     * @param string $uid
531
+     * @param string $password
532
+     * @return boolean
533
+     * @throws LoginException if an app canceld the login process or the user is not enabled
534
+     */
535
+    private function loginWithPassword($uid, $password) {
536
+        $user = $this->manager->checkPassword($uid, $password);
537
+        if ($user === false) {
538
+            // Password check failed
539
+            return false;
540
+        }
541
+
542
+        return $this->completeLogin($user, ['loginName' => $uid, 'password' => $password], false);
543
+    }
544
+
545
+    /**
546
+     * Log an user in with a given token (id)
547
+     *
548
+     * @param string $token
549
+     * @return boolean
550
+     * @throws LoginException if an app canceled the login process or the user is not enabled
551
+     */
552
+    private function loginWithToken($token) {
553
+        try {
554
+            $dbToken = $this->tokenProvider->getToken($token);
555
+        } catch (InvalidTokenException $ex) {
556
+            return false;
557
+        }
558
+        $uid = $dbToken->getUID();
559
+
560
+        // When logging in with token, the password must be decrypted first before passing to login hook
561
+        $password = '';
562
+        try {
563
+            $password = $this->tokenProvider->getPassword($dbToken, $token);
564
+        } catch (PasswordlessTokenException $ex) {
565
+            // Ignore and use empty string instead
566
+        }
567
+
568
+        $this->manager->emit('\OC\User', 'preLogin', array($uid, $password));
569
+
570
+        $user = $this->manager->get($uid);
571
+        if (is_null($user)) {
572
+            // user does not exist
573
+            return false;
574
+        }
575
+
576
+        return $this->completeLogin(
577
+            $user,
578
+            [
579
+                'loginName' => $dbToken->getLoginName(),
580
+                'password' => $password,
581
+                'token' => $dbToken
582
+            ],
583
+            false);
584
+    }
585
+
586
+    /**
587
+     * Create a new session token for the given user credentials
588
+     *
589
+     * @param IRequest $request
590
+     * @param string $uid user UID
591
+     * @param string $loginName login name
592
+     * @param string $password
593
+     * @param int $remember
594
+     * @return boolean
595
+     */
596
+    public function createSessionToken(IRequest $request, $uid, $loginName, $password = null, $remember = IToken::DO_NOT_REMEMBER) {
597
+        if (is_null($this->manager->get($uid))) {
598
+            // User does not exist
599
+            return false;
600
+        }
601
+        $name = isset($request->server['HTTP_USER_AGENT']) ? $request->server['HTTP_USER_AGENT'] : 'unknown browser';
602
+        try {
603
+            $sessionId = $this->session->getId();
604
+            $pwd = $this->getPassword($password);
605
+            $this->tokenProvider->generateToken($sessionId, $uid, $loginName, $pwd, $name, IToken::TEMPORARY_TOKEN, $remember);
606
+            return true;
607
+        } catch (SessionNotAvailableException $ex) {
608
+            // This can happen with OCC, where a memory session is used
609
+            // if a memory session is used, we shouldn't create a session token anyway
610
+            return false;
611
+        }
612
+    }
613
+
614
+    /**
615
+     * Checks if the given password is a token.
616
+     * If yes, the password is extracted from the token.
617
+     * If no, the same password is returned.
618
+     *
619
+     * @param string $password either the login password or a device token
620
+     * @return string|null the password or null if none was set in the token
621
+     */
622
+    private function getPassword($password) {
623
+        if (is_null($password)) {
624
+            // This is surely no token ;-)
625
+            return null;
626
+        }
627
+        try {
628
+            $token = $this->tokenProvider->getToken($password);
629
+            try {
630
+                return $this->tokenProvider->getPassword($token, $password);
631
+            } catch (PasswordlessTokenException $ex) {
632
+                return null;
633
+            }
634
+        } catch (InvalidTokenException $ex) {
635
+            return $password;
636
+        }
637
+    }
638
+
639
+    /**
640
+     * @param IToken $dbToken
641
+     * @param string $token
642
+     * @return boolean
643
+     */
644
+    private function checkTokenCredentials(IToken $dbToken, $token) {
645
+        // Check whether login credentials are still valid and the user was not disabled
646
+        // This check is performed each 5 minutes
647
+        $lastCheck = $dbToken->getLastCheck() ? : 0;
648
+        $now = $this->timeFactory->getTime();
649
+        if ($lastCheck > ($now - 60 * 5)) {
650
+            // Checked performed recently, nothing to do now
651
+            return true;
652
+        }
653
+
654
+        try {
655
+            $pwd = $this->tokenProvider->getPassword($dbToken, $token);
656
+        } catch (InvalidTokenException $ex) {
657
+            // An invalid token password was used -> log user out
658
+            return false;
659
+        } catch (PasswordlessTokenException $ex) {
660
+            // Token has no password
661
+
662
+            if (!is_null($this->activeUser) && !$this->activeUser->isEnabled()) {
663
+                $this->tokenProvider->invalidateToken($token);
664
+                return false;
665
+            }
666
+
667
+            $dbToken->setLastCheck($now);
668
+            return true;
669
+        }
670
+
671
+        if ($this->manager->checkPassword($dbToken->getLoginName(), $pwd) === false
672
+            || (!is_null($this->activeUser) && !$this->activeUser->isEnabled())) {
673
+            $this->tokenProvider->invalidateToken($token);
674
+            // Password has changed or user was disabled -> log user out
675
+            return false;
676
+        }
677
+        $dbToken->setLastCheck($now);
678
+        return true;
679
+    }
680
+
681
+    /**
682
+     * Check if the given token exists and performs password/user-enabled checks
683
+     *
684
+     * Invalidates the token if checks fail
685
+     *
686
+     * @param string $token
687
+     * @param string $user login name
688
+     * @return boolean
689
+     */
690
+    private function validateToken($token, $user = null) {
691
+        try {
692
+            $dbToken = $this->tokenProvider->getToken($token);
693
+        } catch (InvalidTokenException $ex) {
694
+            return false;
695
+        }
696
+
697
+        // Check if login names match
698
+        if (!is_null($user) && $dbToken->getLoginName() !== $user) {
699
+            // TODO: this makes it imposssible to use different login names on browser and client
700
+            // e.g. login by e-mail '[email protected]' on browser for generating the token will not
701
+            //      allow to use the client token with the login name 'user'.
702
+            return false;
703
+        }
704
+
705
+        if (!$this->checkTokenCredentials($dbToken, $token)) {
706
+            return false;
707
+        }
708
+
709
+        $this->tokenProvider->updateTokenActivity($dbToken);
710
+
711
+        return true;
712
+    }
713
+
714
+    /**
715
+     * Tries to login the user with auth token header
716
+     *
717
+     * @param IRequest $request
718
+     * @todo check remember me cookie
719
+     * @return boolean
720
+     */
721
+    public function tryTokenLogin(IRequest $request) {
722
+        $authHeader = $request->getHeader('Authorization');
723
+        if (strpos($authHeader, 'token ') === false) {
724
+            // No auth header, let's try session id
725
+            try {
726
+                $token = $this->session->getId();
727
+            } catch (SessionNotAvailableException $ex) {
728
+                return false;
729
+            }
730
+        } else {
731
+            $token = substr($authHeader, 6);
732
+        }
733
+
734
+        if (!$this->loginWithToken($token)) {
735
+            return false;
736
+        }
737
+        if(!$this->validateToken($token)) {
738
+            return false;
739
+        }
740
+        return true;
741
+    }
742
+
743
+    /**
744
+     * perform login using the magic cookie (remember login)
745
+     *
746
+     * @param string $uid the username
747
+     * @param string $currentToken
748
+     * @param string $oldSessionId
749
+     * @return bool
750
+     */
751
+    public function loginWithCookie($uid, $currentToken, $oldSessionId) {
752
+        $this->session->regenerateId();
753
+        $this->manager->emit('\OC\User', 'preRememberedLogin', array($uid));
754
+        $user = $this->manager->get($uid);
755
+        if (is_null($user)) {
756
+            // user does not exist
757
+            return false;
758
+        }
759
+
760
+        // get stored tokens
761
+        $tokens = $this->config->getUserKeys($uid, 'login_token');
762
+        // test cookies token against stored tokens
763
+        if (!in_array($currentToken, $tokens, true)) {
764
+            return false;
765
+        }
766
+        // replace successfully used token with a new one
767
+        $this->config->deleteUserValue($uid, 'login_token', $currentToken);
768
+        $newToken = $this->random->generate(32);
769
+        $this->config->setUserValue($uid, 'login_token', $newToken, $this->timeFactory->getTime());
770
+
771
+        try {
772
+            $sessionId = $this->session->getId();
773
+            $this->tokenProvider->renewSessionToken($oldSessionId, $sessionId);
774
+        } catch (SessionNotAvailableException $ex) {
775
+            return false;
776
+        } catch (InvalidTokenException $ex) {
777
+            \OC::$server->getLogger()->warning('Renewing session token failed', ['app' => 'core']);
778
+            return false;
779
+        }
780
+
781
+        $this->setMagicInCookie($user->getUID(), $newToken);
782
+        $token = $this->tokenProvider->getToken($sessionId);
783
+
784
+        //login
785
+        $this->setUser($user);
786
+        $this->setLoginName($token->getLoginName());
787
+        $this->setToken($token->getId());
788
+        $this->lockdownManager->setToken($token);
789
+        $user->updateLastLoginTimestamp();
790
+        $this->manager->emit('\OC\User', 'postRememberedLogin', [$user]);
791
+        return true;
792
+    }
793
+
794
+    /**
795
+     * @param IUser $user
796
+     */
797
+    public function createRememberMeToken(IUser $user) {
798
+        $token = $this->random->generate(32);
799
+        $this->config->setUserValue($user->getUID(), 'login_token', $token, $this->timeFactory->getTime());
800
+        $this->setMagicInCookie($user->getUID(), $token);
801
+    }
802
+
803
+    /**
804
+     * logout the user from the session
805
+     */
806
+    public function logout() {
807
+        $this->manager->emit('\OC\User', 'logout');
808
+        $user = $this->getUser();
809
+        if (!is_null($user)) {
810
+            try {
811
+                $this->tokenProvider->invalidateToken($this->session->getId());
812
+            } catch (SessionNotAvailableException $ex) {
813
+
814
+            }
815
+        }
816
+        $this->setUser(null);
817
+        $this->setLoginName(null);
818
+        $this->setToken(null);
819
+        $this->unsetMagicInCookie();
820
+        $this->session->clear();
821
+        $this->manager->emit('\OC\User', 'postLogout');
822
+    }
823
+
824
+    /**
825
+     * Set cookie value to use in next page load
826
+     *
827
+     * @param string $username username to be set
828
+     * @param string $token
829
+     */
830
+    public function setMagicInCookie($username, $token) {
831
+        $secureCookie = OC::$server->getRequest()->getServerProtocol() === 'https';
832
+        $webRoot = \OC::$WEBROOT;
833
+        if ($webRoot === '') {
834
+            $webRoot = '/';
835
+        }
836
+
837
+        $expires = $this->timeFactory->getTime() + $this->config->getSystemValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15);
838
+        setcookie('nc_username', $username, $expires, $webRoot, '', $secureCookie, true);
839
+        setcookie('nc_token', $token, $expires, $webRoot, '', $secureCookie, true);
840
+        try {
841
+            setcookie('nc_session_id', $this->session->getId(), $expires, $webRoot, '', $secureCookie, true);
842
+        } catch (SessionNotAvailableException $ex) {
843
+            // ignore
844
+        }
845
+    }
846
+
847
+    /**
848
+     * Remove cookie for "remember username"
849
+     */
850
+    public function unsetMagicInCookie() {
851
+        //TODO: DI for cookies and IRequest
852
+        $secureCookie = OC::$server->getRequest()->getServerProtocol() === 'https';
853
+
854
+        unset($_COOKIE['nc_username']); //TODO: DI
855
+        unset($_COOKIE['nc_token']);
856
+        unset($_COOKIE['nc_session_id']);
857
+        setcookie('nc_username', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT, '', $secureCookie, true);
858
+        setcookie('nc_token', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT, '', $secureCookie, true);
859
+        setcookie('nc_session_id', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT, '', $secureCookie, true);
860
+        // old cookies might be stored under /webroot/ instead of /webroot
861
+        // and Firefox doesn't like it!
862
+        setcookie('nc_username', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
863
+        setcookie('nc_token', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
864
+        setcookie('nc_session_id', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
865
+    }
866
+
867
+    /**
868
+     * Update password of the browser session token if there is one
869
+     *
870
+     * @param string $password
871
+     */
872
+    public function updateSessionTokenPassword($password) {
873
+        try {
874
+            $sessionId = $this->session->getId();
875
+            $token = $this->tokenProvider->getToken($sessionId);
876
+            $this->tokenProvider->setPassword($token, $sessionId, $password);
877
+        } catch (SessionNotAvailableException $ex) {
878
+            // Nothing to do
879
+        } catch (InvalidTokenException $ex) {
880
+            // Nothing to do
881
+        }
882
+    }
883 883
 
884 884
 
885 885
 }
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -340,14 +340,14 @@  discard block
 block discarded – undo
340 340
 			throw new LoginException($message);
341 341
 		}
342 342
 
343
-		if($regenerateSessionId) {
343
+		if ($regenerateSessionId) {
344 344
 			$this->session->regenerateId();
345 345
 		}
346 346
 
347 347
 		$this->setUser($user);
348 348
 		$this->setLoginName($loginDetails['loginName']);
349 349
 
350
-		if(isset($loginDetails['token']) && $loginDetails['token'] instanceof IToken) {
350
+		if (isset($loginDetails['token']) && $loginDetails['token'] instanceof IToken) {
351 351
 			$this->setToken($loginDetails['token']->getId());
352 352
 			$this->lockdownManager->setToken($loginDetails['token']);
353 353
 			$firstTimeLogin = false;
@@ -356,7 +356,7 @@  discard block
 block discarded – undo
356 356
 			$firstTimeLogin = $user->updateLastLoginTimestamp();
357 357
 		}
358 358
 		$this->manager->emit('\OC\User', 'postLogin', [$user, $loginDetails['password']]);
359
-		if($this->isLoggedIn()) {
359
+		if ($this->isLoggedIn()) {
360 360
 			$this->prepareUserLogin($firstTimeLogin);
361 361
 			return true;
362 362
 		} else {
@@ -396,14 +396,14 @@  discard block
 block discarded – undo
396 396
 		if (!$isTokenPassword && $this->isTwoFactorEnforced($user)) {
397 397
 			throw new PasswordLoginForbiddenException();
398 398
 		}
399
-		if (!$this->login($user, $password) ) {
399
+		if (!$this->login($user, $password)) {
400 400
 			$users = $this->manager->getByEmail($user);
401 401
 			if (count($users) === 1) {
402 402
 				return $this->login($users[0]->getUID(), $password);
403 403
 			}
404 404
 
405 405
 			$throttler->registerAttempt('login', $request->getRemoteAddress(), ['uid' => $user]);
406
-			if($currentDelay === 0) {
406
+			if ($currentDelay === 0) {
407 407
 				$throttler->sleepDelay($request->getRemoteAddress(), 'login');
408 408
 			}
409 409
 			return false;
@@ -411,7 +411,7 @@  discard block
 block discarded – undo
411 411
 
412 412
 		if ($isTokenPassword) {
413 413
 			$this->session->set('app_password', $password);
414
-		} else if($this->supportsCookies($request)) {
414
+		} else if ($this->supportsCookies($request)) {
415 415
 			// Password login, but cookies supported -> create (browser) session token
416 416
 			$this->createSessionToken($request, $this->getUser()->getUID(), $user, $password);
417 417
 		}
@@ -484,7 +484,7 @@  discard block
 block discarded – undo
484 484
 			\OC_Util::copySkeleton($user, $userFolder);
485 485
 
486 486
 			// trigger any other initialization
487
-			\OC::$server->getEventDispatcher()->dispatch(IUser::class . '::firstLogin', new GenericEvent($this->getUser()));
487
+			\OC::$server->getEventDispatcher()->dispatch(IUser::class.'::firstLogin', new GenericEvent($this->getUser()));
488 488
 		}
489 489
 	}
490 490
 
@@ -644,7 +644,7 @@  discard block
 block discarded – undo
644 644
 	private function checkTokenCredentials(IToken $dbToken, $token) {
645 645
 		// Check whether login credentials are still valid and the user was not disabled
646 646
 		// This check is performed each 5 minutes
647
-		$lastCheck = $dbToken->getLastCheck() ? : 0;
647
+		$lastCheck = $dbToken->getLastCheck() ?: 0;
648 648
 		$now = $this->timeFactory->getTime();
649 649
 		if ($lastCheck > ($now - 60 * 5)) {
650 650
 			// Checked performed recently, nothing to do now
@@ -734,7 +734,7 @@  discard block
 block discarded – undo
734 734
 		if (!$this->loginWithToken($token)) {
735 735
 			return false;
736 736
 		}
737
-		if(!$this->validateToken($token)) {
737
+		if (!$this->validateToken($token)) {
738 738
 			return false;
739 739
 		}
740 740
 		return true;
@@ -859,9 +859,9 @@  discard block
 block discarded – undo
859 859
 		setcookie('nc_session_id', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT, '', $secureCookie, true);
860 860
 		// old cookies might be stored under /webroot/ instead of /webroot
861 861
 		// and Firefox doesn't like it!
862
-		setcookie('nc_username', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
863
-		setcookie('nc_token', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
864
-		setcookie('nc_session_id', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT . '/', '', $secureCookie, true);
862
+		setcookie('nc_username', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT.'/', '', $secureCookie, true);
863
+		setcookie('nc_token', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT.'/', '', $secureCookie, true);
864
+		setcookie('nc_session_id', '', $this->timeFactory->getTime() - 3600, OC::$WEBROOT.'/', '', $secureCookie, true);
865 865
 	}
866 866
 
867 867
 	/**
Please login to merge, or discard this patch.