Allow to disable AuthToken v1

Signed-off-by: Joas Schilling <coding@schilljs.com>
pull/31206/head
Joas Schilling 2 years ago committed by backportbot[bot]
parent b3072cf02e
commit 595e1dec73

@ -300,6 +300,16 @@ $CONFIG = [
*/ */
'auth.bruteforce.protection.enabled' => true, 'auth.bruteforce.protection.enabled' => true,
/**
* Whether the authtoken v1 provider should be skipped
*
* The v1 provider is deprecated and removed in Nextcloud 24 onwards. It can be
* disabled already when the instance was installed after Nextcloud 14.
*
* Defaults to ``false``
*/
'auth.authtoken.v1.disabled' => false,
/** /**
* By default WebAuthn is available but it can be explicitly disabled by admins * By default WebAuthn is available but it can be explicitly disabled by admins
*/ */

@ -25,9 +25,22 @@ namespace OC\Authentication\Token;
use OC; use OC;
use OC\BackgroundJob\Job; use OC\BackgroundJob\Job;
use OCP\IConfig;
class DefaultTokenCleanupJob extends Job { class DefaultTokenCleanupJob extends Job {
/** @var IConfig */
protected $config;
public function __construct(IConfig $config) {
$this->config = $config;
}
protected function run($argument) { protected function run($argument) {
if ($this->config->getSystemValueBool('auth.authtoken.v1.disabled')) {
return;
}
/* @var $provider IProvider */ /* @var $provider IProvider */
$provider = OC::$server->query(IProvider::class); $provider = OC::$server->query(IProvider::class);
$provider->invalidateOldTokens(); $provider->invalidateOldTokens();

@ -33,13 +33,19 @@ namespace OC\Authentication\Token;
use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\QBMapper; use OCP\AppFramework\Db\QBMapper;
use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IConfig;
use OCP\IDBConnection; use OCP\IDBConnection;
/** /**
* @template-extends QBMapper<DefaultToken> * @template-extends QBMapper<DefaultToken>
*/ */
class DefaultTokenMapper extends QBMapper { class DefaultTokenMapper extends QBMapper {
public function __construct(IDBConnection $db) {
/** @var IConfig */
protected $config;
public function __construct(IDBConnection $db, IConfig $config) {
$this->config = $config;
parent::__construct($db, 'authtoken'); parent::__construct($db, 'authtoken');
} }
@ -49,6 +55,10 @@ class DefaultTokenMapper extends QBMapper {
* @param string $token * @param string $token
*/ */
public function invalidate(string $token) { public function invalidate(string $token) {
if ($this->config->getSystemValueBool('auth.authtoken.v1.disabled')) {
return;
}
/* @var $qb IQueryBuilder */ /* @var $qb IQueryBuilder */
$qb = $this->db->getQueryBuilder(); $qb = $this->db->getQueryBuilder();
$qb->delete('authtoken') $qb->delete('authtoken')
@ -62,6 +72,10 @@ class DefaultTokenMapper extends QBMapper {
* @param int $remember * @param int $remember
*/ */
public function invalidateOld(int $olderThan, int $remember = IToken::DO_NOT_REMEMBER) { public function invalidateOld(int $olderThan, int $remember = IToken::DO_NOT_REMEMBER) {
if ($this->config->getSystemValueBool('auth.authtoken.v1.disabled')) {
return;
}
/* @var $qb IQueryBuilder */ /* @var $qb IQueryBuilder */
$qb = $this->db->getQueryBuilder(); $qb = $this->db->getQueryBuilder();
$qb->delete('authtoken') $qb->delete('authtoken')
@ -80,6 +94,10 @@ class DefaultTokenMapper extends QBMapper {
* @return DefaultToken * @return DefaultToken
*/ */
public function getToken(string $token): DefaultToken { public function getToken(string $token): DefaultToken {
if ($this->config->getSystemValueBool('auth.authtoken.v1.disabled')) {
throw new DoesNotExistException('Authtoken v1 disabled');
}
/* @var $qb IQueryBuilder */ /* @var $qb IQueryBuilder */
$qb = $this->db->getQueryBuilder(); $qb = $this->db->getQueryBuilder();
$result = $qb->select('id', 'uid', 'login_name', 'password', 'name', 'token', 'type', 'remember', 'last_activity', 'last_check', 'scope', 'expires', 'version') $result = $qb->select('id', 'uid', 'login_name', 'password', 'name', 'token', 'type', 'remember', 'last_activity', 'last_check', 'scope', 'expires', 'version')
@ -104,6 +122,10 @@ class DefaultTokenMapper extends QBMapper {
* @return DefaultToken * @return DefaultToken
*/ */
public function getTokenById(int $id): DefaultToken { public function getTokenById(int $id): DefaultToken {
if ($this->config->getSystemValueBool('auth.authtoken.v1.disabled')) {
throw new DoesNotExistException('Authtoken v1 disabled');
}
/* @var $qb IQueryBuilder */ /* @var $qb IQueryBuilder */
$qb = $this->db->getQueryBuilder(); $qb = $this->db->getQueryBuilder();
$result = $qb->select('id', 'uid', 'login_name', 'password', 'name', 'token', 'type', 'remember', 'last_activity', 'last_check', 'scope', 'expires', 'version') $result = $qb->select('id', 'uid', 'login_name', 'password', 'name', 'token', 'type', 'remember', 'last_activity', 'last_check', 'scope', 'expires', 'version')
@ -130,6 +152,10 @@ class DefaultTokenMapper extends QBMapper {
* @return DefaultToken[] * @return DefaultToken[]
*/ */
public function getTokenByUser(string $uid): array { public function getTokenByUser(string $uid): array {
if ($this->config->getSystemValueBool('auth.authtoken.v1.disabled')) {
return [];
}
/* @var $qb IQueryBuilder */ /* @var $qb IQueryBuilder */
$qb = $this->db->getQueryBuilder(); $qb = $this->db->getQueryBuilder();
$qb->select('id', 'uid', 'login_name', 'password', 'name', 'token', 'type', 'remember', 'last_activity', 'last_check', 'scope', 'expires', 'version') $qb->select('id', 'uid', 'login_name', 'password', 'name', 'token', 'type', 'remember', 'last_activity', 'last_check', 'scope', 'expires', 'version')
@ -149,6 +175,10 @@ class DefaultTokenMapper extends QBMapper {
} }
public function deleteById(string $uid, int $id) { public function deleteById(string $uid, int $id) {
if ($this->config->getSystemValueBool('auth.authtoken.v1.disabled')) {
return;
}
/* @var $qb IQueryBuilder */ /* @var $qb IQueryBuilder */
$qb = $this->db->getQueryBuilder(); $qb = $this->db->getQueryBuilder();
$qb->delete('authtoken') $qb->delete('authtoken')
@ -164,6 +194,10 @@ class DefaultTokenMapper extends QBMapper {
* @param string $name * @param string $name
*/ */
public function deleteByName(string $name) { public function deleteByName(string $name) {
if ($this->config->getSystemValueBool('auth.authtoken.v1.disabled')) {
return;
}
$qb = $this->db->getQueryBuilder(); $qb = $this->db->getQueryBuilder();
$qb->delete('authtoken') $qb->delete('authtoken')
->where($qb->expr()->eq('name', $qb->createNamedParameter($name), IQueryBuilder::PARAM_STR)) ->where($qb->expr()->eq('name', $qb->createNamedParameter($name), IQueryBuilder::PARAM_STR))

@ -90,6 +90,10 @@ class DefaultTokenProvider implements IProvider {
string $name, string $name,
int $type = IToken::TEMPORARY_TOKEN, int $type = IToken::TEMPORARY_TOKEN,
int $remember = IToken::DO_NOT_REMEMBER): IToken { int $remember = IToken::DO_NOT_REMEMBER): IToken {
if ($this->config->getSystemValueBool('auth.authtoken.v1.disabled')) {
throw new InvalidTokenException('Authtokens v1 disabled');
}
$dbToken = new DefaultToken(); $dbToken = new DefaultToken();
$dbToken->setUid($uid); $dbToken->setUid($uid);
$dbToken->setLoginName($loginName); $dbToken->setLoginName($loginName);
@ -116,6 +120,10 @@ class DefaultTokenProvider implements IProvider {
* @throws InvalidTokenException * @throws InvalidTokenException
*/ */
public function updateToken(IToken $token) { public function updateToken(IToken $token) {
if ($this->config->getSystemValueBool('auth.authtoken.v1.disabled')) {
throw new InvalidTokenException('Authtokens v1 disabled');
}
if (!($token instanceof DefaultToken)) { if (!($token instanceof DefaultToken)) {
throw new InvalidTokenException("Invalid token type"); throw new InvalidTokenException("Invalid token type");
} }
@ -129,6 +137,10 @@ class DefaultTokenProvider implements IProvider {
* @param IToken $token * @param IToken $token
*/ */
public function updateTokenActivity(IToken $token) { public function updateTokenActivity(IToken $token) {
if ($this->config->getSystemValueBool('auth.authtoken.v1.disabled')) {
throw new InvalidTokenException('Authtokens v1 disabled');
}
if (!($token instanceof DefaultToken)) { if (!($token instanceof DefaultToken)) {
throw new InvalidTokenException("Invalid token type"); throw new InvalidTokenException("Invalid token type");
} }
@ -142,6 +154,10 @@ class DefaultTokenProvider implements IProvider {
} }
public function getTokenByUser(string $uid): array { public function getTokenByUser(string $uid): array {
if ($this->config->getSystemValueBool('auth.authtoken.v1.disabled')) {
return [];
}
return $this->mapper->getTokenByUser($uid); return $this->mapper->getTokenByUser($uid);
} }
@ -154,6 +170,10 @@ class DefaultTokenProvider implements IProvider {
* @return IToken * @return IToken
*/ */
public function getToken(string $tokenId): IToken { public function getToken(string $tokenId): IToken {
if ($this->config->getSystemValueBool('auth.authtoken.v1.disabled')) {
throw new InvalidTokenException('Authtokens v1 disabled');
}
try { try {
$token = $this->mapper->getToken($this->hashToken($tokenId)); $token = $this->mapper->getToken($this->hashToken($tokenId));
} catch (DoesNotExistException $ex) { } catch (DoesNotExistException $ex) {
@ -176,6 +196,10 @@ class DefaultTokenProvider implements IProvider {
* @return IToken * @return IToken
*/ */
public function getTokenById(int $tokenId): IToken { public function getTokenById(int $tokenId): IToken {
if ($this->config->getSystemValueBool('auth.authtoken.v1.disabled')) {
throw new InvalidTokenException('Authtokens v1 disabled');
}
try { try {
$token = $this->mapper->getTokenById($tokenId); $token = $this->mapper->getTokenById($tokenId);
} catch (DoesNotExistException $ex) { } catch (DoesNotExistException $ex) {
@ -196,6 +220,10 @@ class DefaultTokenProvider implements IProvider {
* @return IToken * @return IToken
*/ */
public function renewSessionToken(string $oldSessionId, string $sessionId): IToken { public function renewSessionToken(string $oldSessionId, string $sessionId): IToken {
if ($this->config->getSystemValueBool('auth.authtoken.v1.disabled')) {
throw new InvalidTokenException('Authtokens v1 disabled');
}
$token = $this->getToken($oldSessionId); $token = $this->getToken($oldSessionId);
$newToken = new DefaultToken(); $newToken = new DefaultToken();
@ -224,6 +252,10 @@ class DefaultTokenProvider implements IProvider {
* @return string * @return string
*/ */
public function getPassword(IToken $savedToken, string $tokenId): string { public function getPassword(IToken $savedToken, string $tokenId): string {
if ($this->config->getSystemValueBool('auth.authtoken.v1.disabled')) {
throw new InvalidTokenException('Authtokens v1 disabled');
}
$password = $savedToken->getPassword(); $password = $savedToken->getPassword();
if ($password === null || $password === '') { if ($password === null || $password === '') {
throw new PasswordlessTokenException(); throw new PasswordlessTokenException();
@ -240,6 +272,10 @@ class DefaultTokenProvider implements IProvider {
* @throws InvalidTokenException * @throws InvalidTokenException
*/ */
public function setPassword(IToken $token, string $tokenId, string $password) { public function setPassword(IToken $token, string $tokenId, string $password) {
if ($this->config->getSystemValueBool('auth.authtoken.v1.disabled')) {
throw new InvalidTokenException('Authtokens v1 disabled');
}
if (!($token instanceof DefaultToken)) { if (!($token instanceof DefaultToken)) {
throw new InvalidTokenException("Invalid token type"); throw new InvalidTokenException("Invalid token type");
} }
@ -254,10 +290,18 @@ class DefaultTokenProvider implements IProvider {
* @param string $token * @param string $token
*/ */
public function invalidateToken(string $token) { public function invalidateToken(string $token) {
if ($this->config->getSystemValueBool('auth.authtoken.v1.disabled')) {
return;
}
$this->mapper->invalidate($this->hashToken($token)); $this->mapper->invalidate($this->hashToken($token));
} }
public function invalidateTokenById(string $uid, int $id) { public function invalidateTokenById(string $uid, int $id) {
if ($this->config->getSystemValueBool('auth.authtoken.v1.disabled')) {
return;
}
$this->mapper->deleteById($uid, $id); $this->mapper->deleteById($uid, $id);
} }
@ -265,6 +309,10 @@ class DefaultTokenProvider implements IProvider {
* Invalidate (delete) old session tokens * Invalidate (delete) old session tokens
*/ */
public function invalidateOldTokens() { public function invalidateOldTokens() {
if ($this->config->getSystemValueBool('auth.authtoken.v1.disabled')) {
return;
}
$olderThan = $this->time->getTime() - (int) $this->config->getSystemValue('session_lifetime', 60 * 60 * 24); $olderThan = $this->time->getTime() - (int) $this->config->getSystemValue('session_lifetime', 60 * 60 * 24);
$this->logger->debug('Invalidating session tokens older than ' . date('c', $olderThan), ['app' => 'cron']); $this->logger->debug('Invalidating session tokens older than ' . date('c', $olderThan), ['app' => 'cron']);
$this->mapper->invalidateOld($olderThan, IToken::DO_NOT_REMEMBER); $this->mapper->invalidateOld($olderThan, IToken::DO_NOT_REMEMBER);
@ -282,6 +330,10 @@ class DefaultTokenProvider implements IProvider {
* @return IToken * @return IToken
*/ */
public function rotate(IToken $token, string $oldTokenId, string $newTokenId): IToken { public function rotate(IToken $token, string $oldTokenId, string $newTokenId): IToken {
if ($this->config->getSystemValueBool('auth.authtoken.v1.disabled')) {
throw new InvalidTokenException('Authtokens v1 disabled');
}
try { try {
$password = $this->getPassword($token, $oldTokenId); $password = $this->getPassword($token, $oldTokenId);
$token->setPassword($this->encryptPassword($password, $newTokenId)); $token->setPassword($this->encryptPassword($password, $newTokenId));
@ -339,6 +391,10 @@ class DefaultTokenProvider implements IProvider {
} }
public function markPasswordInvalid(IToken $token, string $tokenId) { public function markPasswordInvalid(IToken $token, string $tokenId) {
if ($this->config->getSystemValueBool('auth.authtoken.v1.disabled')) {
throw new InvalidTokenException('Authtokens v1 disabled');
}
if (!($token instanceof DefaultToken)) { if (!($token instanceof DefaultToken)) {
throw new InvalidTokenException("Invalid token type"); throw new InvalidTokenException("Invalid token type");
} }

Loading…
Cancel
Save