Completed
Push — master ( b4df57...e6895c )
by Lukas
26s
created

Manager::loadTwoFactorApp()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 5
rs 9.4285
1
<?php
2
/**
3
 * @author Christoph Wurst <[email protected]>
4
 *
5
 * @copyright Copyright (c) 2016, ownCloud, Inc.
6
 * @license AGPL-3.0
7
 *
8
 * This code is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Affero General Public License, version 3,
10
 * as published by the Free Software Foundation.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
 * GNU Affero General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Affero General Public License, version 3,
18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
19
 *
20
 */
21
22
namespace OC\Authentication\TwoFactorAuth;
23
24
use Exception;
25
use OC;
26
use OC\App\AppManager;
27
use OC_App;
28
use OCP\AppFramework\QueryException;
29
use OCP\Authentication\TwoFactorAuth\IProvider;
30
use OCP\IConfig;
31
use OCP\ISession;
32
use OCP\IUser;
33
34
class Manager {
35
36
	const SESSION_UID_KEY = 'two_factor_auth_uid';
37
38
	/** @var AppManager */
39
	private $appManager;
40
41
	/** @var ISession */
42
	private $session;
43
44
	/** @var IConfig */
45
	private $config;
46
47
	/**
48
	 * @param AppManager $appManager
49
	 * @param ISession $session
50
	 * @param IConfig $config
51
	 */
52
	public function __construct(AppManager $appManager, ISession $session, IConfig $config) {
53
		$this->appManager = $appManager;
54
		$this->session = $session;
55
		$this->config = $config;
56
	}
57
58
	/**
59
	 * Determine whether the user must provide a second factor challenge
60
	 *
61
	 * @param IUser $user
62
	 * @return boolean
63
	 */
64
	public function isTwoFactorAuthenticated(IUser $user) {
65
		$twoFactorEnabled = ((int) $this->config->getUserValue($user->getUID(), 'core', 'two_factor_auth_disabled', 0)) === 0;
66
		return $twoFactorEnabled && count($this->getProviders($user)) > 0;
67
	}
68
69
	/**
70
	 * Disable 2FA checks for the given user
71
	 *
72
	 * @param IUser $user
73
	 */
74
	public function disableTwoFactorAuthentication(IUser $user) {
75
		$this->config->setUserValue($user->getUID(), 'core', 'two_factor_auth_disabled', 1);
76
	}
77
78
	/**
79
	 * Enable all 2FA checks for the given user
80
	 *
81
	 * @param IUser $user
82
	 */
83
	public function enableTwoFactorAuthentication(IUser $user) {
84
		$this->config->deleteUserValue($user->getUID(), 'core', 'two_factor_auth_disabled');
85
	}
86
87
	/**
88
	 * Get a 2FA provider by its ID
89
	 *
90
	 * @param IUser $user
91
	 * @param string $challengeProviderId
92
	 * @return IProvider|null
93
	 */
94
	public function getProvider(IUser $user, $challengeProviderId) {
95
		$providers = $this->getProviders($user);
96
		return isset($providers[$challengeProviderId]) ? $providers[$challengeProviderId] : null;
97
	}
98
99
	/**
100
	 * Get the list of 2FA providers for the given user
101
	 *
102
	 * @param IUser $user
103
	 * @return IProvider[]
104
	 */
105
	public function getProviders(IUser $user) {
106
		$allApps = $this->appManager->getEnabledAppsForUser($user);
107
		$providers = [];
108
109
		foreach ($allApps as $appId) {
110
			$info = $this->appManager->getAppInfo($appId);
111
			$providerClasses = $info['two-factor-providers'];
112
			foreach ($providerClasses as $class) {
113
				try {
114
					$this->loadTwoFactorApp($appId);
115
					$provider = OC::$server->query($class);
116
					$providers[$provider->getId()] = $provider;
117
				} catch (QueryException $exc) {
118
					// Provider class can not be resolved
119
					throw new Exception("Could not load two-factor auth provider $class");
120
				}
121
			}
122
		}
123
124
		return array_filter($providers, function ($provider) use ($user) {
125
			/* @var $provider IProvider */
126
			return $provider->isTwoFactorAuthEnabledForUser($user);
127
		});
128
	}
129
130
	/**
131
	 * Load an app by ID if it has not been loaded yet
132
	 *
133
	 * @param string $appId
134
	 */
135
	protected function loadTwoFactorApp($appId) {
136
		if (!OC_App::isAppLoaded($appId)) {
137
			OC_App::loadApp($appId);
138
		}
139
	}
140
141
	/**
142
	 * Verify the given challenge
143
	 *
144
	 * @param string $providerId
145
	 * @param IUser $user
146
	 * @param string $challenge
147
	 * @return boolean
148
	 */
149
	public function verifyChallenge($providerId, IUser $user, $challenge) {
150
		$provider = $this->getProvider($user, $providerId);
151
		if (is_null($provider)) {
152
			return false;
153
		}
154
155
		$result = $provider->verifyChallenge($user, $challenge);
156
		if ($result) {
157
			$this->session->remove(self::SESSION_UID_KEY);
158
		}
159
		return $result;
160
	}
161
162
	/**
163
	 * Check if the currently logged in user needs to pass 2FA
164
	 *
165
	 * @return boolean
166
	 */
167
	public function needsSecondFactor() {
168
		return $this->session->exists(self::SESSION_UID_KEY);
169
	}
170
171
	/**
172
	 * Prepare the 2FA login (set session value)
173
	 *
174
	 * @param IUser $user
175
	 */
176
	public function prepareTwoFactorLogin(IUser $user) {
177
		$this->session->set(self::SESSION_UID_KEY, $user->getUID());
178
	}
179
180
}
181