Passed
Push — master ( 301144...baff2c )
by Morris
09:28
created
lib/private/Authentication/Token/PublicKeyTokenProvider.php 1 patch
Indentation   +337 added lines, -337 removed lines patch added patch discarded remove patch
@@ -34,341 +34,341 @@
 block discarded – undo
34 34
 use OCP\Security\ICrypto;
35 35
 
36 36
 class PublicKeyTokenProvider implements IProvider {
37
-	/** @var PublicKeyTokenMapper */
38
-	private $mapper;
39
-
40
-	/** @var ICrypto */
41
-	private $crypto;
42
-
43
-	/** @var IConfig */
44
-	private $config;
45
-
46
-	/** @var ILogger $logger */
47
-	private $logger;
48
-
49
-	/** @var ITimeFactory $time */
50
-	private $time;
51
-
52
-	public function __construct(PublicKeyTokenMapper $mapper,
53
-								ICrypto $crypto,
54
-								IConfig $config,
55
-								ILogger $logger,
56
-								ITimeFactory $time) {
57
-		$this->mapper = $mapper;
58
-		$this->crypto = $crypto;
59
-		$this->config = $config;
60
-		$this->logger = $logger;
61
-		$this->time = $time;
62
-	}
63
-
64
-	/**
65
-	 * {@inheritDoc}
66
-	 */
67
-	public function generateToken(string $token,
68
-								  string $uid,
69
-								  string $loginName,
70
-								  $password,
71
-								  string $name,
72
-								  int $type = IToken::TEMPORARY_TOKEN,
73
-								  int $remember = IToken::DO_NOT_REMEMBER): IToken {
74
-		$dbToken = $this->newToken($token, $uid, $loginName, $password, $name, $type, $remember);
75
-
76
-		$this->mapper->insert($dbToken);
77
-
78
-		return $dbToken;
79
-	}
80
-
81
-	public function getToken(string $tokenId): IToken {
82
-		try {
83
-			$token = $this->mapper->getToken($this->hashToken($tokenId));
84
-		} catch (DoesNotExistException $ex) {
85
-			throw new InvalidTokenException();
86
-		}
87
-
88
-		if ((int)$token->getExpires() !== 0 && $token->getExpires() < $this->time->getTime()) {
89
-			throw new ExpiredTokenException($token);
90
-		}
91
-
92
-		if ($token->getType() === IToken::WIPE_TOKEN) {
93
-			throw new WipeTokenException($token);
94
-		}
95
-
96
-		return $token;
97
-	}
98
-
99
-	public function getTokenById(int $tokenId): IToken {
100
-		try {
101
-			$token = $this->mapper->getTokenById($tokenId);
102
-		} catch (DoesNotExistException $ex) {
103
-			throw new InvalidTokenException();
104
-		}
105
-
106
-		if ((int)$token->getExpires() !== 0 && $token->getExpires() < $this->time->getTime()) {
107
-			throw new ExpiredTokenException($token);
108
-		}
109
-
110
-		if ($token->getType() === IToken::WIPE_TOKEN) {
111
-			throw new WipeTokenException($token);
112
-		}
113
-
114
-		return $token;
115
-	}
116
-
117
-	public function renewSessionToken(string $oldSessionId, string $sessionId) {
118
-		$token = $this->getToken($oldSessionId);
119
-
120
-		if (!($token instanceof PublicKeyToken)) {
121
-			throw new InvalidTokenException();
122
-		}
123
-
124
-		$password = null;
125
-		if (!is_null($token->getPassword())) {
126
-			$privateKey = $this->decrypt($token->getPrivateKey(), $oldSessionId);
127
-			$password = $this->decryptPassword($token->getPassword(), $privateKey);
128
-		}
129
-
130
-		$this->generateToken(
131
-			$sessionId,
132
-			$token->getUID(),
133
-			$token->getLoginName(),
134
-			$password,
135
-			$token->getName(),
136
-			IToken::TEMPORARY_TOKEN,
137
-			$token->getRemember()
138
-		);
139
-
140
-		$this->mapper->delete($token);
141
-	}
142
-
143
-	public function invalidateToken(string $token) {
144
-		$this->mapper->invalidate($this->hashToken($token));
145
-	}
146
-
147
-	public function invalidateTokenById(string $uid, int $id) {
148
-		$this->mapper->deleteById($uid, $id);
149
-	}
150
-
151
-	public function invalidateOldTokens() {
152
-		$olderThan = $this->time->getTime() - (int) $this->config->getSystemValue('session_lifetime', 60 * 60 * 24);
153
-		$this->logger->debug('Invalidating session tokens older than ' . date('c', $olderThan), ['app' => 'cron']);
154
-		$this->mapper->invalidateOld($olderThan, IToken::DO_NOT_REMEMBER);
155
-		$rememberThreshold = $this->time->getTime() - (int) $this->config->getSystemValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15);
156
-		$this->logger->debug('Invalidating remembered session tokens older than ' . date('c', $rememberThreshold), ['app' => 'cron']);
157
-		$this->mapper->invalidateOld($rememberThreshold, IToken::REMEMBER);
158
-	}
159
-
160
-	public function updateToken(IToken $token) {
161
-		if (!($token instanceof PublicKeyToken)) {
162
-			throw new InvalidTokenException();
163
-		}
164
-		$this->mapper->update($token);
165
-	}
166
-
167
-	public function updateTokenActivity(IToken $token) {
168
-		if (!($token instanceof PublicKeyToken)) {
169
-			throw new InvalidTokenException();
170
-		}
171
-		/** @var DefaultToken $token */
172
-		$now = $this->time->getTime();
173
-		if ($token->getLastActivity() < ($now - 60)) {
174
-			// Update token only once per minute
175
-			$token->setLastActivity($now);
176
-			$this->mapper->update($token);
177
-		}
178
-	}
179
-
180
-	public function getTokenByUser(string $uid): array {
181
-		return $this->mapper->getTokenByUser($uid);
182
-	}
183
-
184
-	public function getPassword(IToken $token, string $tokenId): string {
185
-		if (!($token instanceof PublicKeyToken)) {
186
-			throw new InvalidTokenException();
187
-		}
188
-
189
-		if ($token->getPassword() === null) {
190
-			throw new PasswordlessTokenException();
191
-		}
192
-
193
-		// Decrypt private key with tokenId
194
-		$privateKey = $this->decrypt($token->getPrivateKey(), $tokenId);
195
-
196
-		// Decrypt password with private key
197
-		return $this->decryptPassword($token->getPassword(), $privateKey);
198
-	}
199
-
200
-	public function setPassword(IToken $token, string $tokenId, string $password) {
201
-		if (!($token instanceof PublicKeyToken)) {
202
-			throw new InvalidTokenException();
203
-		}
204
-
205
-		// When changing passwords all temp tokens are deleted
206
-		$this->mapper->deleteTempToken($token);
207
-
208
-		// Update the password for all tokens
209
-		$tokens = $this->mapper->getTokenByUser($token->getUID());
210
-		foreach ($tokens as $t) {
211
-			$publicKey = $t->getPublicKey();
212
-			$t->setPassword($this->encryptPassword($password, $publicKey));
213
-			$this->updateToken($t);
214
-		}
215
-	}
216
-
217
-	public function rotate(IToken $token, string $oldTokenId, string $newTokenId): IToken {
218
-		if (!($token instanceof PublicKeyToken)) {
219
-			throw new InvalidTokenException();
220
-		}
221
-
222
-		// Decrypt private key with oldTokenId
223
-		$privateKey = $this->decrypt($token->getPrivateKey(), $oldTokenId);
224
-		// Encrypt with the new token
225
-		$token->setPrivateKey($this->encrypt($privateKey, $newTokenId));
226
-
227
-		$token->setToken($this->hashToken($newTokenId));
228
-		$this->updateToken($token);
229
-
230
-		return $token;
231
-	}
232
-
233
-	private function encrypt(string $plaintext, string $token): string {
234
-		$secret = $this->config->getSystemValue('secret');
235
-		return $this->crypto->encrypt($plaintext, $token . $secret);
236
-	}
237
-
238
-	/**
239
-	 * @throws InvalidTokenException
240
-	 */
241
-	private function decrypt(string $cipherText, string $token): string {
242
-		$secret = $this->config->getSystemValue('secret');
243
-		try {
244
-			return $this->crypto->decrypt($cipherText, $token . $secret);
245
-		} catch (\Exception $ex) {
246
-			// Delete the invalid token
247
-			$this->invalidateToken($token);
248
-			throw new InvalidTokenException();
249
-		}
250
-	}
251
-
252
-	private function encryptPassword(string $password, string $publicKey): string {
253
-		openssl_public_encrypt($password, $encryptedPassword, $publicKey, OPENSSL_PKCS1_OAEP_PADDING);
254
-		$encryptedPassword = base64_encode($encryptedPassword);
255
-
256
-		return $encryptedPassword;
257
-	}
258
-
259
-	private function decryptPassword(string $encryptedPassword, string $privateKey): string {
260
-		$encryptedPassword = base64_decode($encryptedPassword);
261
-		openssl_private_decrypt($encryptedPassword, $password, $privateKey, OPENSSL_PKCS1_OAEP_PADDING);
262
-
263
-		return $password;
264
-	}
265
-
266
-	private function hashToken(string $token): string {
267
-		$secret = $this->config->getSystemValue('secret');
268
-		return hash('sha512', $token . $secret);
269
-	}
270
-
271
-	/**
272
-	 * Convert a DefaultToken to a publicKeyToken
273
-	 * This will also be updated directly in the Database
274
-	 * @throws \RuntimeException when OpenSSL reports a problem
275
-	 */
276
-	public function convertToken(DefaultToken $defaultToken, string $token, $password): PublicKeyToken {
277
-		$pkToken = $this->newToken(
278
-			$token,
279
-			$defaultToken->getUID(),
280
-			$defaultToken->getLoginName(),
281
-			$password,
282
-			$defaultToken->getName(),
283
-			$defaultToken->getType(),
284
-			$defaultToken->getRemember()
285
-		);
286
-
287
-		$pkToken->setExpires($defaultToken->getExpires());
288
-		$pkToken->setId($defaultToken->getId());
289
-
290
-		return $this->mapper->update($pkToken);
291
-	}
292
-
293
-	/**
294
-	 * @throws \RuntimeException when OpenSSL reports a problem
295
-	 */
296
-	private function newToken(string $token,
297
-							  string $uid,
298
-							  string $loginName,
299
-							  $password,
300
-							  string $name,
301
-							  int $type,
302
-							  int $remember): PublicKeyToken {
303
-		$dbToken = new PublicKeyToken();
304
-		$dbToken->setUid($uid);
305
-		$dbToken->setLoginName($loginName);
306
-
307
-		$config = array_merge([
308
-			'digest_alg' => 'sha512',
309
-			'private_key_bits' => 2048,
310
-		], $this->config->getSystemValue('openssl', []));
311
-
312
-		// Generate new key
313
-		$res = openssl_pkey_new($config);
314
-		if ($res === false) {
315
-			$this->logOpensslError();
316
-			throw new \RuntimeException('OpenSSL reported a problem');
317
-		}
318
-
319
-		openssl_pkey_export($res, $privateKey);
320
-
321
-		// Extract the public key from $res to $pubKey
322
-		$publicKey = openssl_pkey_get_details($res);
323
-		$publicKey = $publicKey['key'];
324
-
325
-		$dbToken->setPublicKey($publicKey);
326
-		$dbToken->setPrivateKey($this->encrypt($privateKey, $token));
327
-
328
-		if (!is_null($password)) {
329
-			$dbToken->setPassword($this->encryptPassword($password, $publicKey));
330
-		}
331
-
332
-		$dbToken->setName($name);
333
-		$dbToken->setToken($this->hashToken($token));
334
-		$dbToken->setType($type);
335
-		$dbToken->setRemember($remember);
336
-		$dbToken->setLastActivity($this->time->getTime());
337
-		$dbToken->setLastCheck($this->time->getTime());
338
-		$dbToken->setVersion(PublicKeyToken::VERSION);
339
-
340
-		return $dbToken;
341
-	}
342
-
343
-	public function markPasswordInvalid(IToken $token, string $tokenId) {
344
-		if (!($token instanceof PublicKeyToken)) {
345
-			throw new InvalidTokenException();
346
-		}
347
-
348
-		$token->setPasswordInvalid(true);
349
-		$this->mapper->update($token);
350
-	}
351
-
352
-	public function updatePasswords(string $uid, string $password) {
353
-		if (!$this->mapper->hasExpiredTokens($uid)) {
354
-			// Nothing to do here
355
-			return;
356
-		}
357
-
358
-		// Update the password for all tokens
359
-		$tokens = $this->mapper->getTokenByUser($uid);
360
-		foreach ($tokens as $t) {
361
-			$publicKey = $t->getPublicKey();
362
-			$t->setPassword($this->encryptPassword($password, $publicKey));
363
-			$this->updateToken($t);
364
-		}
365
-	}
366
-
367
-	private function logOpensslError() {
368
-		$errors = [];
369
-		while ($error = openssl_error_string()) {
370
-			$errors[] = $error;
371
-		}
372
-		$this->logger->critical('Something is wrong with your openssl setup: ' . implode(', ', $errors));
373
-	}
37
+    /** @var PublicKeyTokenMapper */
38
+    private $mapper;
39
+
40
+    /** @var ICrypto */
41
+    private $crypto;
42
+
43
+    /** @var IConfig */
44
+    private $config;
45
+
46
+    /** @var ILogger $logger */
47
+    private $logger;
48
+
49
+    /** @var ITimeFactory $time */
50
+    private $time;
51
+
52
+    public function __construct(PublicKeyTokenMapper $mapper,
53
+                                ICrypto $crypto,
54
+                                IConfig $config,
55
+                                ILogger $logger,
56
+                                ITimeFactory $time) {
57
+        $this->mapper = $mapper;
58
+        $this->crypto = $crypto;
59
+        $this->config = $config;
60
+        $this->logger = $logger;
61
+        $this->time = $time;
62
+    }
63
+
64
+    /**
65
+     * {@inheritDoc}
66
+     */
67
+    public function generateToken(string $token,
68
+                                    string $uid,
69
+                                    string $loginName,
70
+                                    $password,
71
+                                    string $name,
72
+                                    int $type = IToken::TEMPORARY_TOKEN,
73
+                                    int $remember = IToken::DO_NOT_REMEMBER): IToken {
74
+        $dbToken = $this->newToken($token, $uid, $loginName, $password, $name, $type, $remember);
75
+
76
+        $this->mapper->insert($dbToken);
77
+
78
+        return $dbToken;
79
+    }
80
+
81
+    public function getToken(string $tokenId): IToken {
82
+        try {
83
+            $token = $this->mapper->getToken($this->hashToken($tokenId));
84
+        } catch (DoesNotExistException $ex) {
85
+            throw new InvalidTokenException();
86
+        }
87
+
88
+        if ((int)$token->getExpires() !== 0 && $token->getExpires() < $this->time->getTime()) {
89
+            throw new ExpiredTokenException($token);
90
+        }
91
+
92
+        if ($token->getType() === IToken::WIPE_TOKEN) {
93
+            throw new WipeTokenException($token);
94
+        }
95
+
96
+        return $token;
97
+    }
98
+
99
+    public function getTokenById(int $tokenId): IToken {
100
+        try {
101
+            $token = $this->mapper->getTokenById($tokenId);
102
+        } catch (DoesNotExistException $ex) {
103
+            throw new InvalidTokenException();
104
+        }
105
+
106
+        if ((int)$token->getExpires() !== 0 && $token->getExpires() < $this->time->getTime()) {
107
+            throw new ExpiredTokenException($token);
108
+        }
109
+
110
+        if ($token->getType() === IToken::WIPE_TOKEN) {
111
+            throw new WipeTokenException($token);
112
+        }
113
+
114
+        return $token;
115
+    }
116
+
117
+    public function renewSessionToken(string $oldSessionId, string $sessionId) {
118
+        $token = $this->getToken($oldSessionId);
119
+
120
+        if (!($token instanceof PublicKeyToken)) {
121
+            throw new InvalidTokenException();
122
+        }
123
+
124
+        $password = null;
125
+        if (!is_null($token->getPassword())) {
126
+            $privateKey = $this->decrypt($token->getPrivateKey(), $oldSessionId);
127
+            $password = $this->decryptPassword($token->getPassword(), $privateKey);
128
+        }
129
+
130
+        $this->generateToken(
131
+            $sessionId,
132
+            $token->getUID(),
133
+            $token->getLoginName(),
134
+            $password,
135
+            $token->getName(),
136
+            IToken::TEMPORARY_TOKEN,
137
+            $token->getRemember()
138
+        );
139
+
140
+        $this->mapper->delete($token);
141
+    }
142
+
143
+    public function invalidateToken(string $token) {
144
+        $this->mapper->invalidate($this->hashToken($token));
145
+    }
146
+
147
+    public function invalidateTokenById(string $uid, int $id) {
148
+        $this->mapper->deleteById($uid, $id);
149
+    }
150
+
151
+    public function invalidateOldTokens() {
152
+        $olderThan = $this->time->getTime() - (int) $this->config->getSystemValue('session_lifetime', 60 * 60 * 24);
153
+        $this->logger->debug('Invalidating session tokens older than ' . date('c', $olderThan), ['app' => 'cron']);
154
+        $this->mapper->invalidateOld($olderThan, IToken::DO_NOT_REMEMBER);
155
+        $rememberThreshold = $this->time->getTime() - (int) $this->config->getSystemValue('remember_login_cookie_lifetime', 60 * 60 * 24 * 15);
156
+        $this->logger->debug('Invalidating remembered session tokens older than ' . date('c', $rememberThreshold), ['app' => 'cron']);
157
+        $this->mapper->invalidateOld($rememberThreshold, IToken::REMEMBER);
158
+    }
159
+
160
+    public function updateToken(IToken $token) {
161
+        if (!($token instanceof PublicKeyToken)) {
162
+            throw new InvalidTokenException();
163
+        }
164
+        $this->mapper->update($token);
165
+    }
166
+
167
+    public function updateTokenActivity(IToken $token) {
168
+        if (!($token instanceof PublicKeyToken)) {
169
+            throw new InvalidTokenException();
170
+        }
171
+        /** @var DefaultToken $token */
172
+        $now = $this->time->getTime();
173
+        if ($token->getLastActivity() < ($now - 60)) {
174
+            // Update token only once per minute
175
+            $token->setLastActivity($now);
176
+            $this->mapper->update($token);
177
+        }
178
+    }
179
+
180
+    public function getTokenByUser(string $uid): array {
181
+        return $this->mapper->getTokenByUser($uid);
182
+    }
183
+
184
+    public function getPassword(IToken $token, string $tokenId): string {
185
+        if (!($token instanceof PublicKeyToken)) {
186
+            throw new InvalidTokenException();
187
+        }
188
+
189
+        if ($token->getPassword() === null) {
190
+            throw new PasswordlessTokenException();
191
+        }
192
+
193
+        // Decrypt private key with tokenId
194
+        $privateKey = $this->decrypt($token->getPrivateKey(), $tokenId);
195
+
196
+        // Decrypt password with private key
197
+        return $this->decryptPassword($token->getPassword(), $privateKey);
198
+    }
199
+
200
+    public function setPassword(IToken $token, string $tokenId, string $password) {
201
+        if (!($token instanceof PublicKeyToken)) {
202
+            throw new InvalidTokenException();
203
+        }
204
+
205
+        // When changing passwords all temp tokens are deleted
206
+        $this->mapper->deleteTempToken($token);
207
+
208
+        // Update the password for all tokens
209
+        $tokens = $this->mapper->getTokenByUser($token->getUID());
210
+        foreach ($tokens as $t) {
211
+            $publicKey = $t->getPublicKey();
212
+            $t->setPassword($this->encryptPassword($password, $publicKey));
213
+            $this->updateToken($t);
214
+        }
215
+    }
216
+
217
+    public function rotate(IToken $token, string $oldTokenId, string $newTokenId): IToken {
218
+        if (!($token instanceof PublicKeyToken)) {
219
+            throw new InvalidTokenException();
220
+        }
221
+
222
+        // Decrypt private key with oldTokenId
223
+        $privateKey = $this->decrypt($token->getPrivateKey(), $oldTokenId);
224
+        // Encrypt with the new token
225
+        $token->setPrivateKey($this->encrypt($privateKey, $newTokenId));
226
+
227
+        $token->setToken($this->hashToken($newTokenId));
228
+        $this->updateToken($token);
229
+
230
+        return $token;
231
+    }
232
+
233
+    private function encrypt(string $plaintext, string $token): string {
234
+        $secret = $this->config->getSystemValue('secret');
235
+        return $this->crypto->encrypt($plaintext, $token . $secret);
236
+    }
237
+
238
+    /**
239
+     * @throws InvalidTokenException
240
+     */
241
+    private function decrypt(string $cipherText, string $token): string {
242
+        $secret = $this->config->getSystemValue('secret');
243
+        try {
244
+            return $this->crypto->decrypt($cipherText, $token . $secret);
245
+        } catch (\Exception $ex) {
246
+            // Delete the invalid token
247
+            $this->invalidateToken($token);
248
+            throw new InvalidTokenException();
249
+        }
250
+    }
251
+
252
+    private function encryptPassword(string $password, string $publicKey): string {
253
+        openssl_public_encrypt($password, $encryptedPassword, $publicKey, OPENSSL_PKCS1_OAEP_PADDING);
254
+        $encryptedPassword = base64_encode($encryptedPassword);
255
+
256
+        return $encryptedPassword;
257
+    }
258
+
259
+    private function decryptPassword(string $encryptedPassword, string $privateKey): string {
260
+        $encryptedPassword = base64_decode($encryptedPassword);
261
+        openssl_private_decrypt($encryptedPassword, $password, $privateKey, OPENSSL_PKCS1_OAEP_PADDING);
262
+
263
+        return $password;
264
+    }
265
+
266
+    private function hashToken(string $token): string {
267
+        $secret = $this->config->getSystemValue('secret');
268
+        return hash('sha512', $token . $secret);
269
+    }
270
+
271
+    /**
272
+     * Convert a DefaultToken to a publicKeyToken
273
+     * This will also be updated directly in the Database
274
+     * @throws \RuntimeException when OpenSSL reports a problem
275
+     */
276
+    public function convertToken(DefaultToken $defaultToken, string $token, $password): PublicKeyToken {
277
+        $pkToken = $this->newToken(
278
+            $token,
279
+            $defaultToken->getUID(),
280
+            $defaultToken->getLoginName(),
281
+            $password,
282
+            $defaultToken->getName(),
283
+            $defaultToken->getType(),
284
+            $defaultToken->getRemember()
285
+        );
286
+
287
+        $pkToken->setExpires($defaultToken->getExpires());
288
+        $pkToken->setId($defaultToken->getId());
289
+
290
+        return $this->mapper->update($pkToken);
291
+    }
292
+
293
+    /**
294
+     * @throws \RuntimeException when OpenSSL reports a problem
295
+     */
296
+    private function newToken(string $token,
297
+                                string $uid,
298
+                                string $loginName,
299
+                                $password,
300
+                                string $name,
301
+                                int $type,
302
+                                int $remember): PublicKeyToken {
303
+        $dbToken = new PublicKeyToken();
304
+        $dbToken->setUid($uid);
305
+        $dbToken->setLoginName($loginName);
306
+
307
+        $config = array_merge([
308
+            'digest_alg' => 'sha512',
309
+            'private_key_bits' => 2048,
310
+        ], $this->config->getSystemValue('openssl', []));
311
+
312
+        // Generate new key
313
+        $res = openssl_pkey_new($config);
314
+        if ($res === false) {
315
+            $this->logOpensslError();
316
+            throw new \RuntimeException('OpenSSL reported a problem');
317
+        }
318
+
319
+        openssl_pkey_export($res, $privateKey);
320
+
321
+        // Extract the public key from $res to $pubKey
322
+        $publicKey = openssl_pkey_get_details($res);
323
+        $publicKey = $publicKey['key'];
324
+
325
+        $dbToken->setPublicKey($publicKey);
326
+        $dbToken->setPrivateKey($this->encrypt($privateKey, $token));
327
+
328
+        if (!is_null($password)) {
329
+            $dbToken->setPassword($this->encryptPassword($password, $publicKey));
330
+        }
331
+
332
+        $dbToken->setName($name);
333
+        $dbToken->setToken($this->hashToken($token));
334
+        $dbToken->setType($type);
335
+        $dbToken->setRemember($remember);
336
+        $dbToken->setLastActivity($this->time->getTime());
337
+        $dbToken->setLastCheck($this->time->getTime());
338
+        $dbToken->setVersion(PublicKeyToken::VERSION);
339
+
340
+        return $dbToken;
341
+    }
342
+
343
+    public function markPasswordInvalid(IToken $token, string $tokenId) {
344
+        if (!($token instanceof PublicKeyToken)) {
345
+            throw new InvalidTokenException();
346
+        }
347
+
348
+        $token->setPasswordInvalid(true);
349
+        $this->mapper->update($token);
350
+    }
351
+
352
+    public function updatePasswords(string $uid, string $password) {
353
+        if (!$this->mapper->hasExpiredTokens($uid)) {
354
+            // Nothing to do here
355
+            return;
356
+        }
357
+
358
+        // Update the password for all tokens
359
+        $tokens = $this->mapper->getTokenByUser($uid);
360
+        foreach ($tokens as $t) {
361
+            $publicKey = $t->getPublicKey();
362
+            $t->setPassword($this->encryptPassword($password, $publicKey));
363
+            $this->updateToken($t);
364
+        }
365
+    }
366
+
367
+    private function logOpensslError() {
368
+        $errors = [];
369
+        while ($error = openssl_error_string()) {
370
+            $errors[] = $error;
371
+        }
372
+        $this->logger->critical('Something is wrong with your openssl setup: ' . implode(', ', $errors));
373
+    }
374 374
 }
Please login to merge, or discard this patch.
lib/private/Authentication/Token/IProvider.php 1 patch
Indentation   +145 added lines, -145 removed lines patch added patch discarded remove patch
@@ -34,149 +34,149 @@
 block discarded – undo
34 34
 interface IProvider {
35 35
 
36 36
 
37
-	/**
38
-	 * Create and persist a new token
39
-	 *
40
-	 * @param string $token
41
-	 * @param string $uid
42
-	 * @param string $loginName
43
-	 * @param string|null $password
44
-	 * @param string $name
45
-	 * @param int $type token type
46
-	 * @param int $remember whether the session token should be used for remember-me
47
-	 * @return IToken
48
-	 * @throws \RuntimeException when OpenSSL reports a problem
49
-	 */
50
-	public function generateToken(string $token,
51
-								  string $uid,
52
-								  string $loginName,
53
-								  $password,
54
-								  string $name,
55
-								  int $type = IToken::TEMPORARY_TOKEN,
56
-								  int $remember = IToken::DO_NOT_REMEMBER): IToken;
57
-
58
-	/**
59
-	 * Get a token by token id
60
-	 *
61
-	 * @param string $tokenId
62
-	 * @throws InvalidTokenException
63
-	 * @throws ExpiredTokenException
64
-	 * @throws WipeTokenException
65
-	 * @return IToken
66
-	 */
67
-	public function getToken(string $tokenId): IToken;
68
-
69
-	/**
70
-	 * Get a token by token id
71
-	 *
72
-	 * @param int $tokenId
73
-	 * @throws InvalidTokenException
74
-	 * @throws ExpiredTokenException
75
-	 * @throws WipeTokenException
76
-	 * @return IToken
77
-	 */
78
-	public function getTokenById(int $tokenId): IToken;
79
-
80
-	/**
81
-	 * Duplicate an existing session token
82
-	 *
83
-	 * @param string $oldSessionId
84
-	 * @param string $sessionId
85
-	 * @throws InvalidTokenException
86
-	 * @throws \RuntimeException when OpenSSL reports a problem
87
-	 */
88
-	public function renewSessionToken(string $oldSessionId, string $sessionId);
89
-
90
-	/**
91
-	 * Invalidate (delete) the given session token
92
-	 *
93
-	 * @param string $token
94
-	 */
95
-	public function invalidateToken(string $token);
96
-
97
-	/**
98
-	 * Invalidate (delete) the given token
99
-	 *
100
-	 * @param string $uid
101
-	 * @param int $id
102
-	 */
103
-	public function invalidateTokenById(string $uid, int $id);
104
-
105
-	/**
106
-	 * Invalidate (delete) old session tokens
107
-	 */
108
-	public function invalidateOldTokens();
109
-
110
-	/**
111
-	 * Save the updated token
112
-	 *
113
-	 * @param IToken $token
114
-	 */
115
-	public function updateToken(IToken $token);
116
-
117
-	/**
118
-	 * Update token activity timestamp
119
-	 *
120
-	 * @param IToken $token
121
-	 */
122
-	public function updateTokenActivity(IToken $token);
123
-
124
-	/**
125
-	 * Get all tokens of a user
126
-	 *
127
-	 * The provider may limit the number of result rows in case of an abuse
128
-	 * where a high number of (session) tokens is generated
129
-	 *
130
-	 * @param string $uid
131
-	 * @return IToken[]
132
-	 */
133
-	public function getTokenByUser(string $uid): array;
134
-
135
-	/**
136
-	 * Get the (unencrypted) password of the given token
137
-	 *
138
-	 * @param IToken $token
139
-	 * @param string $tokenId
140
-	 * @throws InvalidTokenException
141
-	 * @throws PasswordlessTokenException
142
-	 * @return string
143
-	 */
144
-	public function getPassword(IToken $token, string $tokenId): string;
145
-
146
-	/**
147
-	 * Encrypt and set the password of the given token
148
-	 *
149
-	 * @param IToken $token
150
-	 * @param string $tokenId
151
-	 * @param string $password
152
-	 * @throws InvalidTokenException
153
-	 */
154
-	public function setPassword(IToken $token, string $tokenId, string $password);
155
-
156
-	/**
157
-	 * Rotate the token. Usefull for for example oauth tokens
158
-	 *
159
-	 * @param IToken $token
160
-	 * @param string $oldTokenId
161
-	 * @param string $newTokenId
162
-	 * @return IToken
163
-	 * @throws \RuntimeException when OpenSSL reports a problem
164
-	 */
165
-	public function rotate(IToken $token, string $oldTokenId, string $newTokenId): IToken;
166
-
167
-	/**
168
-	 * Marks a token as having an invalid password.
169
-	 *
170
-	 * @param IToken $token
171
-	 * @param string $tokenId
172
-	 */
173
-	public function markPasswordInvalid(IToken $token, string $tokenId);
174
-
175
-	/**
176
-	 * Update all the passwords of $uid if required
177
-	 *
178
-	 * @param string $uid
179
-	 * @param string $password
180
-	 */
181
-	public function updatePasswords(string $uid, string $password);
37
+    /**
38
+     * Create and persist a new token
39
+     *
40
+     * @param string $token
41
+     * @param string $uid
42
+     * @param string $loginName
43
+     * @param string|null $password
44
+     * @param string $name
45
+     * @param int $type token type
46
+     * @param int $remember whether the session token should be used for remember-me
47
+     * @return IToken
48
+     * @throws \RuntimeException when OpenSSL reports a problem
49
+     */
50
+    public function generateToken(string $token,
51
+                                    string $uid,
52
+                                    string $loginName,
53
+                                    $password,
54
+                                    string $name,
55
+                                    int $type = IToken::TEMPORARY_TOKEN,
56
+                                    int $remember = IToken::DO_NOT_REMEMBER): IToken;
57
+
58
+    /**
59
+     * Get a token by token id
60
+     *
61
+     * @param string $tokenId
62
+     * @throws InvalidTokenException
63
+     * @throws ExpiredTokenException
64
+     * @throws WipeTokenException
65
+     * @return IToken
66
+     */
67
+    public function getToken(string $tokenId): IToken;
68
+
69
+    /**
70
+     * Get a token by token id
71
+     *
72
+     * @param int $tokenId
73
+     * @throws InvalidTokenException
74
+     * @throws ExpiredTokenException
75
+     * @throws WipeTokenException
76
+     * @return IToken
77
+     */
78
+    public function getTokenById(int $tokenId): IToken;
79
+
80
+    /**
81
+     * Duplicate an existing session token
82
+     *
83
+     * @param string $oldSessionId
84
+     * @param string $sessionId
85
+     * @throws InvalidTokenException
86
+     * @throws \RuntimeException when OpenSSL reports a problem
87
+     */
88
+    public function renewSessionToken(string $oldSessionId, string $sessionId);
89
+
90
+    /**
91
+     * Invalidate (delete) the given session token
92
+     *
93
+     * @param string $token
94
+     */
95
+    public function invalidateToken(string $token);
96
+
97
+    /**
98
+     * Invalidate (delete) the given token
99
+     *
100
+     * @param string $uid
101
+     * @param int $id
102
+     */
103
+    public function invalidateTokenById(string $uid, int $id);
104
+
105
+    /**
106
+     * Invalidate (delete) old session tokens
107
+     */
108
+    public function invalidateOldTokens();
109
+
110
+    /**
111
+     * Save the updated token
112
+     *
113
+     * @param IToken $token
114
+     */
115
+    public function updateToken(IToken $token);
116
+
117
+    /**
118
+     * Update token activity timestamp
119
+     *
120
+     * @param IToken $token
121
+     */
122
+    public function updateTokenActivity(IToken $token);
123
+
124
+    /**
125
+     * Get all tokens of a user
126
+     *
127
+     * The provider may limit the number of result rows in case of an abuse
128
+     * where a high number of (session) tokens is generated
129
+     *
130
+     * @param string $uid
131
+     * @return IToken[]
132
+     */
133
+    public function getTokenByUser(string $uid): array;
134
+
135
+    /**
136
+     * Get the (unencrypted) password of the given token
137
+     *
138
+     * @param IToken $token
139
+     * @param string $tokenId
140
+     * @throws InvalidTokenException
141
+     * @throws PasswordlessTokenException
142
+     * @return string
143
+     */
144
+    public function getPassword(IToken $token, string $tokenId): string;
145
+
146
+    /**
147
+     * Encrypt and set the password of the given token
148
+     *
149
+     * @param IToken $token
150
+     * @param string $tokenId
151
+     * @param string $password
152
+     * @throws InvalidTokenException
153
+     */
154
+    public function setPassword(IToken $token, string $tokenId, string $password);
155
+
156
+    /**
157
+     * Rotate the token. Usefull for for example oauth tokens
158
+     *
159
+     * @param IToken $token
160
+     * @param string $oldTokenId
161
+     * @param string $newTokenId
162
+     * @return IToken
163
+     * @throws \RuntimeException when OpenSSL reports a problem
164
+     */
165
+    public function rotate(IToken $token, string $oldTokenId, string $newTokenId): IToken;
166
+
167
+    /**
168
+     * Marks a token as having an invalid password.
169
+     *
170
+     * @param IToken $token
171
+     * @param string $tokenId
172
+     */
173
+    public function markPasswordInvalid(IToken $token, string $tokenId);
174
+
175
+    /**
176
+     * Update all the passwords of $uid if required
177
+     *
178
+     * @param string $uid
179
+     * @param string $password
180
+     */
181
+    public function updatePasswords(string $uid, string $password);
182 182
 }
Please login to merge, or discard this patch.
lib/private/Authentication/Token/Manager.php 1 patch
Indentation   +221 added lines, -221 removed lines patch added patch discarded remove patch
@@ -30,227 +30,227 @@
 block discarded – undo
30 30
 
31 31
 class Manager implements IProvider {
32 32
 
33
-	/** @var DefaultTokenProvider */
34
-	private $defaultTokenProvider;
35
-
36
-	/** @var PublicKeyTokenProvider */
37
-	private $publicKeyTokenProvider;
38
-
39
-	public function __construct(DefaultTokenProvider $defaultTokenProvider, PublicKeyTokenProvider $publicKeyTokenProvider) {
40
-		$this->defaultTokenProvider = $defaultTokenProvider;
41
-		$this->publicKeyTokenProvider = $publicKeyTokenProvider;
42
-	}
43
-
44
-	/**
45
-	 * Create and persist a new token
46
-	 *
47
-	 * @param string $token
48
-	 * @param string $uid
49
-	 * @param string $loginName
50
-	 * @param string|null $password
51
-	 * @param string $name
52
-	 * @param int $type token type
53
-	 * @param int $remember whether the session token should be used for remember-me
54
-	 * @return IToken
55
-	 */
56
-	public function generateToken(string $token,
57
-								  string $uid,
58
-								  string $loginName,
59
-								  $password,
60
-								  string $name,
61
-								  int $type = IToken::TEMPORARY_TOKEN,
62
-								  int $remember = IToken::DO_NOT_REMEMBER): IToken {
63
-		return $this->publicKeyTokenProvider->generateToken(
64
-			$token,
65
-			$uid,
66
-			$loginName,
67
-			$password,
68
-			$name,
69
-			$type,
70
-			$remember
71
-		);
72
-	}
73
-
74
-	/**
75
-	 * Save the updated token
76
-	 *
77
-	 * @param IToken $token
78
-	 * @throws InvalidTokenException
79
-	 */
80
-	public function updateToken(IToken $token) {
81
-		$provider = $this->getProvider($token);
82
-		$provider->updateToken($token);
83
-	}
84
-
85
-	/**
86
-	 * Update token activity timestamp
87
-	 *
88
-	 * @throws InvalidTokenException
89
-	 * @param IToken $token
90
-	 */
91
-	public function updateTokenActivity(IToken $token) {
92
-		$provider = $this->getProvider($token);
93
-		$provider->updateTokenActivity($token);
94
-	}
95
-
96
-	/**
97
-	 * @param string $uid
98
-	 * @return IToken[]
99
-	 */
100
-	public function getTokenByUser(string $uid): array {
101
-		$old = $this->defaultTokenProvider->getTokenByUser($uid);
102
-		$new = $this->publicKeyTokenProvider->getTokenByUser($uid);
103
-
104
-		return array_merge($old, $new);
105
-	}
106
-
107
-	/**
108
-	 * Get a token by token
109
-	 *
110
-	 * @param string $tokenId
111
-	 * @throws InvalidTokenException
112
-	 * @throws \RuntimeException when OpenSSL reports a problem
113
-	 * @return IToken
114
-	 */
115
-	public function getToken(string $tokenId): IToken {
116
-		try {
117
-			return $this->publicKeyTokenProvider->getToken($tokenId);
118
-		} catch (WipeTokenException $e) {
119
-			throw $e;
120
-		} catch (ExpiredTokenException $e) {
121
-			throw $e;
122
-		} catch(InvalidTokenException $e) {
123
-			// No worries we try to convert it to a PublicKey Token
124
-		}
125
-
126
-		//Convert!
127
-		$token = $this->defaultTokenProvider->getToken($tokenId);
128
-
129
-		try {
130
-			$password = $this->defaultTokenProvider->getPassword($token, $tokenId);
131
-		} catch (PasswordlessTokenException $e) {
132
-			$password = null;
133
-		}
134
-
135
-		return $this->publicKeyTokenProvider->convertToken($token, $tokenId, $password);
136
-	}
137
-
138
-	/**
139
-	 * Get a token by token id
140
-	 *
141
-	 * @param int $tokenId
142
-	 * @throws InvalidTokenException
143
-	 * @return IToken
144
-	 */
145
-	public function getTokenById(int $tokenId): IToken {
146
-		try {
147
-			return $this->publicKeyTokenProvider->getTokenById($tokenId);
148
-		} catch (ExpiredTokenException $e) {
149
-			throw $e;
150
-		} catch (WipeTokenException $e) {
151
-			throw $e;
152
-		} catch (InvalidTokenException $e) {
153
-			return $this->defaultTokenProvider->getTokenById($tokenId);
154
-		}
155
-	}
156
-
157
-	/**
158
-	 * @param string $oldSessionId
159
-	 * @param string $sessionId
160
-	 * @throws InvalidTokenException
161
-	 */
162
-	public function renewSessionToken(string $oldSessionId, string $sessionId) {
163
-		try {
164
-			$this->publicKeyTokenProvider->renewSessionToken($oldSessionId, $sessionId);
165
-		} catch (ExpiredTokenException $e) {
166
-			throw $e;
167
-		} catch (InvalidTokenException $e) {
168
-			$this->defaultTokenProvider->renewSessionToken($oldSessionId, $sessionId);
169
-		}
170
-	}
171
-
172
-	/**
173
-	 * @param IToken $savedToken
174
-	 * @param string $tokenId session token
175
-	 * @throws InvalidTokenException
176
-	 * @throws PasswordlessTokenException
177
-	 * @return string
178
-	 */
179
-	public function getPassword(IToken $savedToken, string $tokenId): string {
180
-		$provider = $this->getProvider($savedToken);
181
-		return $provider->getPassword($savedToken, $tokenId);
182
-	}
183
-
184
-	public function setPassword(IToken $token, string $tokenId, string $password) {
185
-		$provider = $this->getProvider($token);
186
-		$provider->setPassword($token, $tokenId, $password);
187
-	}
188
-
189
-	public function invalidateToken(string $token) {
190
-		$this->defaultTokenProvider->invalidateToken($token);
191
-		$this->publicKeyTokenProvider->invalidateToken($token);
192
-	}
193
-
194
-	public function invalidateTokenById(string $uid, int $id) {
195
-		$this->defaultTokenProvider->invalidateTokenById($uid, $id);
196
-		$this->publicKeyTokenProvider->invalidateTokenById($uid, $id);
197
-	}
198
-
199
-	public function invalidateOldTokens() {
200
-		$this->defaultTokenProvider->invalidateOldTokens();
201
-		$this->publicKeyTokenProvider->invalidateOldTokens();
202
-	}
203
-
204
-	/**
205
-	 * @param IToken $token
206
-	 * @param string $oldTokenId
207
-	 * @param string $newTokenId
208
-	 * @return IToken
209
-	 * @throws InvalidTokenException
210
-	 * @throws \RuntimeException when OpenSSL reports a problem
211
-	 */
212
-	public function rotate(IToken $token, string $oldTokenId, string $newTokenId): IToken {
213
-		if ($token instanceof DefaultToken) {
214
-			try {
215
-				$password = $this->defaultTokenProvider->getPassword($token, $oldTokenId);
216
-			} catch (PasswordlessTokenException $e) {
217
-				$password = null;
218
-			}
219
-
220
-			return $this->publicKeyTokenProvider->convertToken($token, $newTokenId, $password);
221
-		}
222
-
223
-		if ($token instanceof PublicKeyToken) {
224
-			return $this->publicKeyTokenProvider->rotate($token, $oldTokenId, $newTokenId);
225
-		}
226
-
227
-		throw new InvalidTokenException();
228
-	}
229
-
230
-	/**
231
-	 * @param IToken $token
232
-	 * @return IProvider
233
-	 * @throws InvalidTokenException
234
-	 */
235
-	private function getProvider(IToken $token): IProvider {
236
-		if ($token instanceof DefaultToken) {
237
-			return $this->defaultTokenProvider;
238
-		}
239
-		if ($token instanceof PublicKeyToken) {
240
-			return $this->publicKeyTokenProvider;
241
-		}
242
-		throw new InvalidTokenException();
243
-	}
244
-
245
-
246
-	public function markPasswordInvalid(IToken $token, string $tokenId) {
247
-		$this->getProvider($token)->markPasswordInvalid($token, $tokenId);
248
-	}
249
-
250
-	public function updatePasswords(string $uid, string $password) {
251
-		$this->defaultTokenProvider->updatePasswords($uid, $password);
252
-		$this->publicKeyTokenProvider->updatePasswords($uid, $password);
253
-	}
33
+    /** @var DefaultTokenProvider */
34
+    private $defaultTokenProvider;
35
+
36
+    /** @var PublicKeyTokenProvider */
37
+    private $publicKeyTokenProvider;
38
+
39
+    public function __construct(DefaultTokenProvider $defaultTokenProvider, PublicKeyTokenProvider $publicKeyTokenProvider) {
40
+        $this->defaultTokenProvider = $defaultTokenProvider;
41
+        $this->publicKeyTokenProvider = $publicKeyTokenProvider;
42
+    }
43
+
44
+    /**
45
+     * Create and persist a new token
46
+     *
47
+     * @param string $token
48
+     * @param string $uid
49
+     * @param string $loginName
50
+     * @param string|null $password
51
+     * @param string $name
52
+     * @param int $type token type
53
+     * @param int $remember whether the session token should be used for remember-me
54
+     * @return IToken
55
+     */
56
+    public function generateToken(string $token,
57
+                                    string $uid,
58
+                                    string $loginName,
59
+                                    $password,
60
+                                    string $name,
61
+                                    int $type = IToken::TEMPORARY_TOKEN,
62
+                                    int $remember = IToken::DO_NOT_REMEMBER): IToken {
63
+        return $this->publicKeyTokenProvider->generateToken(
64
+            $token,
65
+            $uid,
66
+            $loginName,
67
+            $password,
68
+            $name,
69
+            $type,
70
+            $remember
71
+        );
72
+    }
73
+
74
+    /**
75
+     * Save the updated token
76
+     *
77
+     * @param IToken $token
78
+     * @throws InvalidTokenException
79
+     */
80
+    public function updateToken(IToken $token) {
81
+        $provider = $this->getProvider($token);
82
+        $provider->updateToken($token);
83
+    }
84
+
85
+    /**
86
+     * Update token activity timestamp
87
+     *
88
+     * @throws InvalidTokenException
89
+     * @param IToken $token
90
+     */
91
+    public function updateTokenActivity(IToken $token) {
92
+        $provider = $this->getProvider($token);
93
+        $provider->updateTokenActivity($token);
94
+    }
95
+
96
+    /**
97
+     * @param string $uid
98
+     * @return IToken[]
99
+     */
100
+    public function getTokenByUser(string $uid): array {
101
+        $old = $this->defaultTokenProvider->getTokenByUser($uid);
102
+        $new = $this->publicKeyTokenProvider->getTokenByUser($uid);
103
+
104
+        return array_merge($old, $new);
105
+    }
106
+
107
+    /**
108
+     * Get a token by token
109
+     *
110
+     * @param string $tokenId
111
+     * @throws InvalidTokenException
112
+     * @throws \RuntimeException when OpenSSL reports a problem
113
+     * @return IToken
114
+     */
115
+    public function getToken(string $tokenId): IToken {
116
+        try {
117
+            return $this->publicKeyTokenProvider->getToken($tokenId);
118
+        } catch (WipeTokenException $e) {
119
+            throw $e;
120
+        } catch (ExpiredTokenException $e) {
121
+            throw $e;
122
+        } catch(InvalidTokenException $e) {
123
+            // No worries we try to convert it to a PublicKey Token
124
+        }
125
+
126
+        //Convert!
127
+        $token = $this->defaultTokenProvider->getToken($tokenId);
128
+
129
+        try {
130
+            $password = $this->defaultTokenProvider->getPassword($token, $tokenId);
131
+        } catch (PasswordlessTokenException $e) {
132
+            $password = null;
133
+        }
134
+
135
+        return $this->publicKeyTokenProvider->convertToken($token, $tokenId, $password);
136
+    }
137
+
138
+    /**
139
+     * Get a token by token id
140
+     *
141
+     * @param int $tokenId
142
+     * @throws InvalidTokenException
143
+     * @return IToken
144
+     */
145
+    public function getTokenById(int $tokenId): IToken {
146
+        try {
147
+            return $this->publicKeyTokenProvider->getTokenById($tokenId);
148
+        } catch (ExpiredTokenException $e) {
149
+            throw $e;
150
+        } catch (WipeTokenException $e) {
151
+            throw $e;
152
+        } catch (InvalidTokenException $e) {
153
+            return $this->defaultTokenProvider->getTokenById($tokenId);
154
+        }
155
+    }
156
+
157
+    /**
158
+     * @param string $oldSessionId
159
+     * @param string $sessionId
160
+     * @throws InvalidTokenException
161
+     */
162
+    public function renewSessionToken(string $oldSessionId, string $sessionId) {
163
+        try {
164
+            $this->publicKeyTokenProvider->renewSessionToken($oldSessionId, $sessionId);
165
+        } catch (ExpiredTokenException $e) {
166
+            throw $e;
167
+        } catch (InvalidTokenException $e) {
168
+            $this->defaultTokenProvider->renewSessionToken($oldSessionId, $sessionId);
169
+        }
170
+    }
171
+
172
+    /**
173
+     * @param IToken $savedToken
174
+     * @param string $tokenId session token
175
+     * @throws InvalidTokenException
176
+     * @throws PasswordlessTokenException
177
+     * @return string
178
+     */
179
+    public function getPassword(IToken $savedToken, string $tokenId): string {
180
+        $provider = $this->getProvider($savedToken);
181
+        return $provider->getPassword($savedToken, $tokenId);
182
+    }
183
+
184
+    public function setPassword(IToken $token, string $tokenId, string $password) {
185
+        $provider = $this->getProvider($token);
186
+        $provider->setPassword($token, $tokenId, $password);
187
+    }
188
+
189
+    public function invalidateToken(string $token) {
190
+        $this->defaultTokenProvider->invalidateToken($token);
191
+        $this->publicKeyTokenProvider->invalidateToken($token);
192
+    }
193
+
194
+    public function invalidateTokenById(string $uid, int $id) {
195
+        $this->defaultTokenProvider->invalidateTokenById($uid, $id);
196
+        $this->publicKeyTokenProvider->invalidateTokenById($uid, $id);
197
+    }
198
+
199
+    public function invalidateOldTokens() {
200
+        $this->defaultTokenProvider->invalidateOldTokens();
201
+        $this->publicKeyTokenProvider->invalidateOldTokens();
202
+    }
203
+
204
+    /**
205
+     * @param IToken $token
206
+     * @param string $oldTokenId
207
+     * @param string $newTokenId
208
+     * @return IToken
209
+     * @throws InvalidTokenException
210
+     * @throws \RuntimeException when OpenSSL reports a problem
211
+     */
212
+    public function rotate(IToken $token, string $oldTokenId, string $newTokenId): IToken {
213
+        if ($token instanceof DefaultToken) {
214
+            try {
215
+                $password = $this->defaultTokenProvider->getPassword($token, $oldTokenId);
216
+            } catch (PasswordlessTokenException $e) {
217
+                $password = null;
218
+            }
219
+
220
+            return $this->publicKeyTokenProvider->convertToken($token, $newTokenId, $password);
221
+        }
222
+
223
+        if ($token instanceof PublicKeyToken) {
224
+            return $this->publicKeyTokenProvider->rotate($token, $oldTokenId, $newTokenId);
225
+        }
226
+
227
+        throw new InvalidTokenException();
228
+    }
229
+
230
+    /**
231
+     * @param IToken $token
232
+     * @return IProvider
233
+     * @throws InvalidTokenException
234
+     */
235
+    private function getProvider(IToken $token): IProvider {
236
+        if ($token instanceof DefaultToken) {
237
+            return $this->defaultTokenProvider;
238
+        }
239
+        if ($token instanceof PublicKeyToken) {
240
+            return $this->publicKeyTokenProvider;
241
+        }
242
+        throw new InvalidTokenException();
243
+    }
244
+
245
+
246
+    public function markPasswordInvalid(IToken $token, string $tokenId) {
247
+        $this->getProvider($token)->markPasswordInvalid($token, $tokenId);
248
+    }
249
+
250
+    public function updatePasswords(string $uid, string $password) {
251
+        $this->defaultTokenProvider->updatePasswords($uid, $password);
252
+        $this->publicKeyTokenProvider->updatePasswords($uid, $password);
253
+    }
254 254
 
255 255
 
256 256
 }
Please login to merge, or discard this patch.