Skip to content

Commit 7e7961f

Browse files
committed
feat(federatedfilesharing): When a remote requests a share with a token, it may be an access token
Signed-off-by: Enrique Pérez Arnaud <enrique@cazalla.net>
1 parent da9da58 commit 7e7961f

4 files changed

Lines changed: 63 additions & 3 deletions

File tree

apps/cloud_federation_api/lib/Controller/RequestHandlerController.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use NCU\Security\Signature\Exceptions\SignatureNotFoundException;
1616
use NCU\Security\Signature\IIncomingSignedRequest;
1717
use NCU\Security\Signature\ISignatureManager;
18+
use OC\Authentication\Token\PublicKeyTokenProvider;
1819
use OC\OCM\OCMSignatoryManager;
1920
use OCA\CloudFederationAPI\Config;
2021
use OCA\CloudFederationAPI\Db\FederatedInviteMapper;
@@ -44,6 +45,7 @@
4445
use OCP\IRequest;
4546
use OCP\IURLGenerator;
4647
use OCP\IUserManager;
48+
use OCP\Server;
4749
use OCP\Share\Exceptions\ShareNotFound;
4850
use OCP\Util;
4951
use Psr\Log\LoggerInterface;
@@ -522,6 +524,12 @@ private function confirmNotificationIdentity(
522524
$provider = $this->cloudFederationProviderManager->getCloudFederationProvider($resourceType);
523525
if ($provider instanceof ISignedCloudFederationProvider) {
524526
$identity = $provider->getFederationIdFromSharedSecret($sharedSecret, $notification);
527+
if ($identity === "") {
528+
$tokenProvider = Server::get(PublicKeyTokenProvider::class);
529+
$accessTokenDb = $tokenProvider->getToken($sharedSecret);
530+
$refreshToken = $accessTokenDb->getUID();
531+
$identity = $provider->getFederationIdFromSharedSecret($refreshToken, $notification);
532+
}
525533
} else {
526534
$this->logger->debug('cloud federation provider {provider} does not implements ISignedCloudFederationProvider', ['provider' => $provider::class]);
527535
return;

apps/federatedfilesharing/lib/FederatedShareProvider.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,20 @@ public function getShareByToken(string $token): IShare {
751751

752752
$data = $cursor->fetchAssociative();
753753

754+
if ($data === false) {
755+
756+
$provider = Server::get(PublicKeyTokenProvider::class);
757+
$accessTokenDb = $provider->getToken($token);
758+
$refreshToken = $accessTokenDb->getUID();
759+
760+
$cursor = $qb->select('*')
761+
->from('share')
762+
->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
763+
->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($refreshToken)))
764+
->executeQuery();
765+
766+
$data = $cursor->fetch();
767+
}
754768
if ($data === false) {
755769
throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
756770
}

lib/private/Share20/Manager.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
*/
88
namespace OC\Share20;
99

10+
use OC\Authentication\Token\IToken;
11+
use OC\Authentication\Token\PublicKeyTokenProvider;
1012
use OC\Core\AppInfo\ConfigLexicon;
1113
use OC\Files\Mount\MoveableMount;
1214
use OC\KnownUser\KnownUserService;
@@ -38,6 +40,7 @@
3840
use OCP\Security\IHasher;
3941
use OCP\Security\ISecureRandom;
4042
use OCP\Security\PasswordContext;
43+
use OCP\Server;
4144
use OCP\Share;
4245
use OCP\Share\Events\BeforeShareDeletedEvent;
4346
use OCP\Share\Events\ShareAcceptedEvent;
@@ -1343,6 +1346,20 @@ public function getShareByToken(string $token): IShare {
13431346
}
13441347
}
13451348

1349+
// Try to fetch a federated share by access token
1350+
if ($share === null) {
1351+
try {
1352+
$provider = $this->factory->getProviderForType(IShare::TYPE_REMOTE);
1353+
$tokenProvider = Server::get(PublicKeyTokenProvider::class);
1354+
$accessTokenDb = $tokenProvider->getToken($token);
1355+
$refreshToken = $accessTokenDb->getUID();
1356+
$share = $provider->getShareByToken($refreshToken);
1357+
} catch (ProviderException $e) {
1358+
} catch (ShareNotFound $e) {
1359+
}
1360+
}
1361+
1362+
13461363
// If it is not a link share try to fetch a mail share by token
13471364
if ($share === null && $this->shareProviderExists(IShare::TYPE_EMAIL)) {
13481365
try {

lib/private/User/Session.php

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -609,14 +609,35 @@ private function loginWithToken($token) {
609609
// Ignore and use empty string instead
610610
}
611611

612-
$this->manager->emit('\OC\User', 'preLogin', [$dbToken->getLoginName(), $password]);
613-
614612
$user = $this->manager->get($uid);
615613
if (is_null($user)) {
614+
// Maybe this is an access token. We keep the refresh tokens as UID of access tokens
615+
try {
616+
$token = $uid;
617+
$dbToken = $this->tokenProvider->getToken($token);
618+
} catch (InvalidTokenException $ex) {
619+
return false;
620+
}
621+
$uid = $dbToken->getUID();
622+
623+
// When logging in with token, the password must be decrypted first before passing to login hook
624+
$password = '';
625+
try {
626+
$password = $this->tokenProvider->getPassword($dbToken, $token);
627+
} catch (PasswordlessTokenException $ex) {
628+
// Ignore and use empty string instead
629+
}
616630
// user does not exist
617-
return false;
631+
$user = $this->manager->get($uid);
632+
if (is_null($user)) {
633+
return false;
634+
}
618635
}
619636

637+
$this->manager->emit('\OC\User', 'preLogin', [$dbToken->getLoginName(), $password]);
638+
639+
// See line 173 in this module, needed for completeLogin
640+
OC_User::setIncognitoMode(false);
620641
return $this->completeLogin(
621642
$user,
622643
[

0 commit comments

Comments
 (0)