Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
invalidate existing tokens when deleting an oauth client
Signed-off-by: Artur Neumann <[email protected]>
  • Loading branch information
individual-it committed Jan 6, 2023
commit 80a7186f15bd99f8d55379d5f9fa85b215337110
28 changes: 26 additions & 2 deletions apps/oauth2/lib/Controller/SettingsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
*/
namespace OCA\OAuth2\Controller;

use OC\Authentication\Token\IProvider as IAuthTokenProvider;
use OCA\OAuth2\Db\AccessTokenMapper;
use OCA\OAuth2\Db\Client;
use OCA\OAuth2\Db\ClientMapper;
Expand All @@ -38,6 +39,8 @@
use OCP\AppFramework\Http\JSONResponse;
use OCP\IL10N;
use OCP\IRequest;
use OCP\IUser;
use OCP\IUserManager;
use OCP\Security\ISecureRandom;

class SettingsController extends Controller {
Expand All @@ -49,21 +52,30 @@ class SettingsController extends Controller {
private $accessTokenMapper;
/** @var IL10N */
private $l;

/** @var IAuthTokenProvider */
private $tokenProvider;
/**
* @var IUserManager
*/
private $userManager;
public const validChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

public function __construct(string $appName,
IRequest $request,
ClientMapper $clientMapper,
ISecureRandom $secureRandom,
AccessTokenMapper $accessTokenMapper,
IL10N $l
IL10N $l,
IAuthTokenProvider $tokenProvider,
IUserManager $userManager
) {
parent::__construct($appName, $request);
$this->secureRandom = $secureRandom;
$this->clientMapper = $clientMapper;
$this->accessTokenMapper = $accessTokenMapper;
$this->l = $l;
$this->tokenProvider = $tokenProvider;
$this->userManager = $userManager;
}

public function addClient(string $name,
Expand Down Expand Up @@ -92,6 +104,18 @@ public function addClient(string $name,

public function deleteClient(int $id): JSONResponse {
$client = $this->clientMapper->getByUid($id);

$this->userManager->callForAllUsers(function (IUser $user) use ($client) {
$tokens = $this->tokenProvider->getTokenByUser($user->getUID());
foreach ($tokens as $token) {
if ($token->getName() === $client->getName()) {
$this->tokenProvider->invalidateTokenById(
$user->getUID(), $token->getId()
);
}
}
});

$this->accessTokenMapper->deleteByClientId($id);
$this->clientMapper->delete($client);
return new JSONResponse([]);
Expand Down
62 changes: 57 additions & 5 deletions apps/oauth2/tests/Controller/SettingsControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
*/
namespace OCA\OAuth2\Tests\Controller;

use OC\Authentication\Token\IToken;
use OC\Authentication\Token\IProvider as IAuthTokenProvider;
use OCA\OAuth2\Controller\SettingsController;
use OCA\OAuth2\Db\AccessTokenMapper;
use OCA\OAuth2\Db\Client;
Expand All @@ -34,9 +36,14 @@
use OCP\AppFramework\Http\JSONResponse;
use OCP\IL10N;
use OCP\IRequest;
use OCP\IUser;
use OCP\IUserManager;
use OCP\Security\ISecureRandom;
use Test\TestCase;

/**
* @group DB
*/
class SettingsControllerTest extends TestCase {
/** @var IRequest|\PHPUnit\Framework\MockObject\MockObject */
private $request;
Expand All @@ -48,6 +55,8 @@ class SettingsControllerTest extends TestCase {
private $accessTokenMapper;
/** @var SettingsController */
private $settingsController;
/** @var IL10N|\PHPUnit\Framework\MockObject\MockObject */
private $l;

protected function setUp(): void {
parent::setUp();
Expand All @@ -56,18 +65,20 @@ protected function setUp(): void {
$this->clientMapper = $this->createMock(ClientMapper::class);
$this->secureRandom = $this->createMock(ISecureRandom::class);
$this->accessTokenMapper = $this->createMock(AccessTokenMapper::class);
$l = $this->createMock(IL10N::class);
$l->method('t')
$this->l = $this->createMock(IL10N::class);
$this->l->method('t')
->willReturnArgument(0);

$this->settingsController = new SettingsController(
'oauth2',
$this->request,
$this->clientMapper,
$this->secureRandom,
$this->accessTokenMapper,
$l
$this->l,
$this->createMock(IAuthTokenProvider::class),
$this->createMock(IUserManager::class)
);

}

public function testAddClient() {
Expand Down Expand Up @@ -113,6 +124,34 @@ public function testAddClient() {
}

public function testDeleteClient() {

$userManager = \OC::$server->getUserManager();
// count other users in the db before adding our own
$count = 0;
$function = function (IUser $user) use (&$count) {
$count++;
};
$userManager->callForAllUsers($function);
$user1 = $userManager->createUser('test101', 'test101');
$tokenMocks[0] = $this->getMockBuilder(IToken::class)->getMock();
$tokenMocks[0]->method('getName')->willReturn('Firefox session');
$tokenMocks[0]->method('getId')->willReturn(1);
$tokenMocks[1] = $this->getMockBuilder(IToken::class)->getMock();
$tokenMocks[1]->method('getName')->willReturn('My Client Name');
$tokenMocks[1]->method('getId')->willReturn(2);
$tokenMocks[2] = $this->getMockBuilder(IToken::class)->getMock();
$tokenMocks[2]->method('getName')->willReturn('mobile client');
$tokenMocks[2]->method('getId')->willReturn(3);

$tokenProviderMock = $this->getMockBuilder(IAuthTokenProvider::class)->getMock();
$tokenProviderMock->method('getTokenByUser')->willReturn($tokenMocks);

// expect one call per user and make sure the correct tokeId is selected
$tokenProviderMock
->expects($this->exactly($count + 1))
->method('invalidateTokenById')
->with($this->isType('string'), 2);

$client = new Client();
$client->setId(123);
$client->setName('My Client Name');
Expand All @@ -132,9 +171,22 @@ public function testDeleteClient() {
->method('delete')
->with($client);

$result = $this->settingsController->deleteClient(123);
$settingsController = new SettingsController(
'oauth2',
$this->request,
$this->clientMapper,
$this->secureRandom,
$this->accessTokenMapper,
$this->l,
$tokenProviderMock,
$userManager
);

$result = $settingsController->deleteClient(123);
$this->assertInstanceOf(JSONResponse::class, $result);
$this->assertEquals([], $result->getData());

$user1->delete();
}

public function testInvalidRedirectUri() {
Expand Down