Skip to content

Commit 891faa3

Browse files
skjnldsvbackportbot[bot]
authored andcommitted
fix(dav): allow multiple link shares token in session
Signed-off-by: skjnldsv <[email protected]> [skip ci]
1 parent 082425b commit 891faa3

File tree

7 files changed

+78
-30
lines changed

7 files changed

+78
-30
lines changed

apps/dav/lib/Connector/Sabre/PublicAuth.php

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,7 @@ private function checkToken(): array {
134134
\OC_User::setIncognitoMode(true);
135135

136136
// If already authenticated
137-
if ($this->session->exists(self::DAV_AUTHENTICATED)
138-
&& $this->session->get(self::DAV_AUTHENTICATED) === $share->getId()) {
137+
if ($this->isShareInSession($share)) {
139138
return [true, $this->principalPrefix . $token];
140139
}
141140

@@ -177,11 +176,11 @@ protected function validateUserPass($username, $password) {
177176
if ($share->getShareType() === IShare::TYPE_LINK
178177
|| $share->getShareType() === IShare::TYPE_EMAIL
179178
|| $share->getShareType() === IShare::TYPE_CIRCLE) {
179+
// Validate password if provided
180180
if ($this->shareManager->checkPassword($share, $password)) {
181181
// If not set, set authenticated session cookie
182-
if (!$this->session->exists(self::DAV_AUTHENTICATED)
183-
|| $this->session->get(self::DAV_AUTHENTICATED) !== $share->getId()) {
184-
$this->session->set(self::DAV_AUTHENTICATED, $share->getId());
182+
if (!$this->isShareInSession($share)) {
183+
$this->addShareToSession($share);
185184
}
186185
return true;
187186
}
@@ -221,4 +220,27 @@ public function getShare(): IShare {
221220

222221
return $this->share;
223222
}
223+
224+
private function addShareToSession(IShare $share): void {
225+
$allowedShareIds = $this->session->get(self::DAV_AUTHENTICATED) ?? [];
226+
if (!is_array($allowedShareIds)) {
227+
$allowedShareIds = [];
228+
}
229+
230+
$allowedShareIds[] = $share->getId();
231+
$this->session->set(self::DAV_AUTHENTICATED, $allowedShareIds);
232+
}
233+
234+
private function isShareInSession(IShare $share): bool {
235+
if (!$this->session->exists(self::DAV_AUTHENTICATED)) {
236+
return false;
237+
}
238+
239+
$allowedShareIds = $this->session->get(self::DAV_AUTHENTICATED);
240+
if (!is_array($allowedShareIds)) {
241+
return false;
242+
}
243+
244+
return in_array($share->getId(), $allowedShareIds);
245+
}
224246
}

apps/dav/tests/unit/Connector/Sabre/PublicAuthTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ public function testInvalidSharePasswordLinkValidSession(): void {
333333
)->willReturn(false);
334334

335335
$this->session->method('exists')->with('public_link_authenticated')->willReturn(true);
336-
$this->session->method('get')->with('public_link_authenticated')->willReturn('42');
336+
$this->session->method('get')->with('public_link_authenticated')->willReturn(['42']);
337337

338338
$result = $this->invokePrivate($this->auth, 'validateUserPass', ['username', 'password']);
339339

apps/files_sharing/lib/Controller/ShareController.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,12 @@ protected function authSucceeded() {
196196
}
197197

198198
// For share this was always set so it is still used in other apps
199-
$this->session->set(PublicAuth::DAV_AUTHENTICATED, $this->share->getId());
199+
$allowedShareIds = $this->session->get(PublicAuth::DAV_AUTHENTICATED);
200+
if (!is_array($allowedShareIds)) {
201+
$allowedShareIds = [];
202+
}
203+
204+
$this->session->set(PublicAuth::DAV_AUTHENTICATED, array_merge($allowedShareIds, [$this->share->getId()]));
200205
}
201206

202207
protected function authFailed() {

lib/public/AppFramework/AuthPublicShareController.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,7 @@ final public function authenticate(string $password = '', string $passwordReques
158158
$this->session->regenerateId(true, true);
159159
$response = $this->getRedirect();
160160

161-
$this->session->set('public_link_authenticated_token', $this->getToken());
162-
$this->session->set('public_link_authenticated_password_hash', $this->getPasswordHash());
161+
$this->storeTokenSession($this->getToken(), $this->getPasswordHash());
163162

164163
$this->authSucceeded();
165164

lib/public/AppFramework/PublicShareController.php

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,21 @@
2525
* @since 14.0.0
2626
*/
2727
abstract class PublicShareController extends Controller {
28-
/** @var ISession */
29-
protected $session;
28+
29+
public const DAV_AUTHENTICATED_FRONTEND = 'public_link_authenticated_frontend';
3030

3131
/** @var string */
3232
private $token;
3333

3434
/**
3535
* @since 14.0.0
3636
*/
37-
public function __construct(string $appName,
37+
public function __construct(
38+
string $appName,
3839
IRequest $request,
39-
ISession $session) {
40+
protected ISession $session,
41+
) {
4042
parent::__construct($appName, $request);
41-
42-
$this->session = $session;
4343
}
4444

4545
/**
@@ -116,4 +116,31 @@ public function isAuthenticated(): bool {
116116
*/
117117
public function shareNotFound() {
118118
}
119+
120+
/**
121+
* Validate the token and password hash stored in session
122+
*/
123+
protected function validateTokenSession(string $token, string $passwordHash): bool {
124+
$allowedTokensJSON = $this->session->get(self::DAV_AUTHENTICATED_FRONTEND) ?? '[]';
125+
$allowedTokens = json_decode($allowedTokensJSON, true);
126+
if (!is_array($allowedTokens)) {
127+
$allowedTokens = [];
128+
}
129+
130+
return ($allowedTokens[$token] ?? '') === $passwordHash;
131+
}
132+
133+
/**
134+
* Store the token and password hash in session
135+
*/
136+
protected function storeTokenSession(string $token, string $passwordHash = ''): void {
137+
$allowedTokensJSON = $this->session->get(self::DAV_AUTHENTICATED_FRONTEND) ?? '[]';
138+
$allowedTokens = json_decode($allowedTokensJSON, true);
139+
if (!is_array($allowedTokens)) {
140+
$allowedTokens = [];
141+
}
142+
143+
$allowedTokens[$token] = $passwordHash;
144+
$this->session->set(self::DAV_AUTHENTICATED_FRONTEND, json_encode($allowedTokens));
145+
}
119146
}

tests/lib/AppFramework/Controller/AuthPublicShareControllerTest.php

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -109,17 +109,15 @@ public function testAuthenticateValidPassword(): void {
109109
$this->session->method('get')
110110
->willReturnMap(['public_link_authenticate_redirect', ['foo' => 'bar']]);
111111

112-
$tokenSet = false;
113-
$hashSet = false;
112+
$tokenStored = false;
114113
$this->session
115114
->method('set')
116-
->willReturnCallback(function ($key, $value) use (&$tokenSet, &$hashSet) {
117-
if ($key === 'public_link_authenticated_token' && $value === 'token') {
118-
$tokenSet = true;
119-
return true;
120-
}
121-
if ($key === 'public_link_authenticated_password_hash' && $value === 'hash') {
122-
$hashSet = true;
115+
->willReturnCallback(function ($key, $value) use (&$tokenStored) {
116+
if ($key === AuthPublicShareController::DAV_AUTHENTICATED_FRONTEND) {
117+
$decoded = json_decode($value, true);
118+
if (isset($decoded['token']) && $decoded['token'] === 'hash') {
119+
$tokenStored = true;
120+
}
123121
return true;
124122
}
125123
return false;
@@ -131,7 +129,6 @@ public function testAuthenticateValidPassword(): void {
131129
$result = $this->controller->authenticate('password');
132130
$this->assertInstanceOf(RedirectResponse::class, $result);
133131
$this->assertSame('myLink!', $result->getRedirectURL());
134-
$this->assertTrue($tokenSet);
135-
$this->assertTrue($hashSet);
132+
$this->assertTrue($tokenStored);
136133
}
137134
}

tests/lib/AppFramework/Controller/PublicShareControllerTest.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,8 @@ public function testIsAuthenticatedNotPasswordProtected(bool $protected, string
7777
$controller = new TestController('app', $this->request, $this->session, $hash2, $protected);
7878

7979
$this->session->method('get')
80-
->willReturnMap([
81-
['public_link_authenticated_token', $token1],
82-
['public_link_authenticated_password_hash', $hash1],
83-
]);
80+
->with(PublicShareController::DAV_AUTHENTICATED_FRONTEND)
81+
->willReturn("{\"$token1\":\"$hash1\"}");
8482

8583
$controller->setToken($token2);
8684

0 commit comments

Comments
 (0)