Merge pull request #12208 from nextcloud/backport/12130/stable13
[13] Reset bruteforce on token refresh OAuth
This commit is contained in:
commit
3aaeaf1316
|
@ -24,6 +24,7 @@ namespace OCA\OAuth2\Controller;
|
||||||
use OC\Authentication\Exceptions\InvalidTokenException;
|
use OC\Authentication\Exceptions\InvalidTokenException;
|
||||||
use OC\Authentication\Token\ExpiredTokenException;
|
use OC\Authentication\Token\ExpiredTokenException;
|
||||||
use OC\Authentication\Token\IProvider as TokenProvider;
|
use OC\Authentication\Token\IProvider as TokenProvider;
|
||||||
|
use OC\Security\Bruteforce\Throttler;
|
||||||
use OCA\OAuth2\Db\AccessTokenMapper;
|
use OCA\OAuth2\Db\AccessTokenMapper;
|
||||||
use OCA\OAuth2\Db\ClientMapper;
|
use OCA\OAuth2\Db\ClientMapper;
|
||||||
use OCA\OAuth2\Exceptions\AccessTokenNotFoundException;
|
use OCA\OAuth2\Exceptions\AccessTokenNotFoundException;
|
||||||
|
@ -49,6 +50,8 @@ class OauthApiController extends Controller {
|
||||||
private $secureRandom;
|
private $secureRandom;
|
||||||
/** @var ITimeFactory */
|
/** @var ITimeFactory */
|
||||||
private $time;
|
private $time;
|
||||||
|
/** @var Throttler */
|
||||||
|
private $throttler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $appName
|
* @param string $appName
|
||||||
|
@ -59,6 +62,7 @@ class OauthApiController extends Controller {
|
||||||
* @param TokenProvider $tokenProvider
|
* @param TokenProvider $tokenProvider
|
||||||
* @param ISecureRandom $secureRandom
|
* @param ISecureRandom $secureRandom
|
||||||
* @param ITimeFactory $time
|
* @param ITimeFactory $time
|
||||||
|
* @param Throttler $throttler
|
||||||
*/
|
*/
|
||||||
public function __construct($appName,
|
public function __construct($appName,
|
||||||
IRequest $request,
|
IRequest $request,
|
||||||
|
@ -67,7 +71,8 @@ class OauthApiController extends Controller {
|
||||||
ClientMapper $clientMapper,
|
ClientMapper $clientMapper,
|
||||||
TokenProvider $tokenProvider,
|
TokenProvider $tokenProvider,
|
||||||
ISecureRandom $secureRandom,
|
ISecureRandom $secureRandom,
|
||||||
ITimeFactory $time) {
|
ITimeFactory $time,
|
||||||
|
Throttler $throttler) {
|
||||||
parent::__construct($appName, $request);
|
parent::__construct($appName, $request);
|
||||||
$this->crypto = $crypto;
|
$this->crypto = $crypto;
|
||||||
$this->accessTokenMapper = $accessTokenMapper;
|
$this->accessTokenMapper = $accessTokenMapper;
|
||||||
|
@ -75,6 +80,7 @@ class OauthApiController extends Controller {
|
||||||
$this->tokenProvider = $tokenProvider;
|
$this->tokenProvider = $tokenProvider;
|
||||||
$this->secureRandom = $secureRandom;
|
$this->secureRandom = $secureRandom;
|
||||||
$this->time = $time;
|
$this->time = $time;
|
||||||
|
$this->throttler = $throttler;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -164,6 +170,8 @@ class OauthApiController extends Controller {
|
||||||
$accessToken->setEncryptedToken($this->crypto->encrypt($newToken, $newCode));
|
$accessToken->setEncryptedToken($this->crypto->encrypt($newToken, $newCode));
|
||||||
$this->accessTokenMapper->update($accessToken);
|
$this->accessTokenMapper->update($accessToken);
|
||||||
|
|
||||||
|
$this->throttler->resetDelay($this->request->getRemoteAddress(), 'login', ['user' => $appToken->getUID()]);
|
||||||
|
|
||||||
return new JSONResponse(
|
return new JSONResponse(
|
||||||
[
|
[
|
||||||
'access_token' => $newToken,
|
'access_token' => $newToken,
|
||||||
|
|
|
@ -27,6 +27,7 @@ use OC\Authentication\Token\DefaultTokenMapper;
|
||||||
use OC\Authentication\Token\ExpiredTokenException;
|
use OC\Authentication\Token\ExpiredTokenException;
|
||||||
use OC\Authentication\Token\IProvider as TokenProvider;
|
use OC\Authentication\Token\IProvider as TokenProvider;
|
||||||
use OC\Authentication\Token\IToken;
|
use OC\Authentication\Token\IToken;
|
||||||
|
use OC\Security\Bruteforce\Throttler;
|
||||||
use OCA\OAuth2\Controller\OauthApiController;
|
use OCA\OAuth2\Controller\OauthApiController;
|
||||||
use OCA\OAuth2\Db\AccessToken;
|
use OCA\OAuth2\Db\AccessToken;
|
||||||
use OCA\OAuth2\Db\AccessTokenMapper;
|
use OCA\OAuth2\Db\AccessTokenMapper;
|
||||||
|
@ -57,6 +58,8 @@ class OauthApiControllerTest extends TestCase {
|
||||||
private $secureRandom;
|
private $secureRandom;
|
||||||
/** @var ITimeFactory|\PHPUnit_Framework_MockObject_MockObject */
|
/** @var ITimeFactory|\PHPUnit_Framework_MockObject_MockObject */
|
||||||
private $time;
|
private $time;
|
||||||
|
/** @var Throttler|\PHPUnit_Framework_MockObject_MockObject */
|
||||||
|
private $throttler;
|
||||||
/** @var OauthApiController */
|
/** @var OauthApiController */
|
||||||
private $oauthApiController;
|
private $oauthApiController;
|
||||||
|
|
||||||
|
@ -70,6 +73,7 @@ class OauthApiControllerTest extends TestCase {
|
||||||
$this->tokenProvider = $this->createMock(TokenProvider::class);
|
$this->tokenProvider = $this->createMock(TokenProvider::class);
|
||||||
$this->secureRandom = $this->createMock(ISecureRandom::class);
|
$this->secureRandom = $this->createMock(ISecureRandom::class);
|
||||||
$this->time = $this->createMock(ITimeFactory::class);
|
$this->time = $this->createMock(ITimeFactory::class);
|
||||||
|
$this->throttler = $this->createMock(Throttler::class);
|
||||||
|
|
||||||
$this->oauthApiController = new OauthApiController(
|
$this->oauthApiController = new OauthApiController(
|
||||||
'oauth2',
|
'oauth2',
|
||||||
|
@ -79,7 +83,8 @@ class OauthApiControllerTest extends TestCase {
|
||||||
$this->clientMapper,
|
$this->clientMapper,
|
||||||
$this->tokenProvider,
|
$this->tokenProvider,
|
||||||
$this->secureRandom,
|
$this->secureRandom,
|
||||||
$this->time
|
$this->time,
|
||||||
|
$this->throttler
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,6 +291,17 @@ class OauthApiControllerTest extends TestCase {
|
||||||
'user_id' => 'userId',
|
'user_id' => 'userId',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$this->request->method('getRemoteAddress')
|
||||||
|
->willReturn('1.2.3.4');
|
||||||
|
|
||||||
|
$this->throttler->expects($this->once())
|
||||||
|
->method('resetDelay')
|
||||||
|
->with(
|
||||||
|
'1.2.3.4',
|
||||||
|
'login',
|
||||||
|
['user' => 'userId']
|
||||||
|
);
|
||||||
|
|
||||||
$this->assertEquals($expected, $this->oauthApiController->getToken('refresh_token', null, 'validrefresh', 'clientId', 'clientSecret'));
|
$this->assertEquals($expected, $this->oauthApiController->getToken('refresh_token', null, 'validrefresh', 'clientId', 'clientSecret'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,6 +386,17 @@ class OauthApiControllerTest extends TestCase {
|
||||||
$this->request->server['PHP_AUTH_USER'] = 'clientId';
|
$this->request->server['PHP_AUTH_USER'] = 'clientId';
|
||||||
$this->request->server['PHP_AUTH_PW'] = 'clientSecret';
|
$this->request->server['PHP_AUTH_PW'] = 'clientSecret';
|
||||||
|
|
||||||
|
$this->request->method('getRemoteAddress')
|
||||||
|
->willReturn('1.2.3.4');
|
||||||
|
|
||||||
|
$this->throttler->expects($this->once())
|
||||||
|
->method('resetDelay')
|
||||||
|
->with(
|
||||||
|
'1.2.3.4',
|
||||||
|
'login',
|
||||||
|
['user' => 'userId']
|
||||||
|
);
|
||||||
|
|
||||||
$this->assertEquals($expected, $this->oauthApiController->getToken('refresh_token', null, 'validrefresh', null, null));
|
$this->assertEquals($expected, $this->oauthApiController->getToken('refresh_token', null, 'validrefresh', null, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,6 +478,17 @@ class OauthApiControllerTest extends TestCase {
|
||||||
'user_id' => 'userId',
|
'user_id' => 'userId',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$this->request->method('getRemoteAddress')
|
||||||
|
->willReturn('1.2.3.4');
|
||||||
|
|
||||||
|
$this->throttler->expects($this->once())
|
||||||
|
->method('resetDelay')
|
||||||
|
->with(
|
||||||
|
'1.2.3.4',
|
||||||
|
'login',
|
||||||
|
['user' => 'userId']
|
||||||
|
);
|
||||||
|
|
||||||
$this->assertEquals($expected, $this->oauthApiController->getToken('refresh_token', null, 'validrefresh', 'clientId', 'clientSecret'));
|
$this->assertEquals($expected, $this->oauthApiController->getToken('refresh_token', null, 'validrefresh', 'clientId', 'clientSecret'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -758,7 +758,7 @@ class Server extends ServerContainer implements IServerContainer {
|
||||||
$this->registerService('TrustedDomainHelper', function ($c) {
|
$this->registerService('TrustedDomainHelper', function ($c) {
|
||||||
return new TrustedDomainHelper($this->getConfig());
|
return new TrustedDomainHelper($this->getConfig());
|
||||||
});
|
});
|
||||||
$this->registerService('Throttler', function (Server $c) {
|
$this->registerService(Throttler::class, function (Server $c) {
|
||||||
return new Throttler(
|
return new Throttler(
|
||||||
$c->getDatabaseConnection(),
|
$c->getDatabaseConnection(),
|
||||||
new TimeFactory(),
|
new TimeFactory(),
|
||||||
|
@ -766,6 +766,7 @@ class Server extends ServerContainer implements IServerContainer {
|
||||||
$c->getConfig()
|
$c->getConfig()
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
$this->registerAlias('Throttler', Throttler::class);
|
||||||
$this->registerService('IntegrityCodeChecker', function (Server $c) {
|
$this->registerService('IntegrityCodeChecker', function (Server $c) {
|
||||||
// IConfig and IAppManager requires a working database. This code
|
// IConfig and IAppManager requires a working database. This code
|
||||||
// might however be called when ownCloud is not yet setup.
|
// might however be called when ownCloud is not yet setup.
|
||||||
|
|
Loading…
Reference in New Issue