Skip to content

Commit a43b9ed

Browse files
committed
feat: Close sessions created for login flow v2
Sessions created during the login flow v2 should be short lived to not leave an unexpected opened session in the browser. This commit add a property to the session object to track its origin, and will close it as soon as possible, i.e., on the first non public page request. Signed-off-by: Louis Chemineau <[email protected]>
1 parent dfc5d22 commit a43b9ed

7 files changed

Lines changed: 90 additions & 1 deletion

File tree

core/Controller/ClientFlowLoginV2Controller.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949
class ClientFlowLoginV2Controller extends Controller {
5050
public const TOKEN_NAME = 'client.flow.v2.login.token';
5151
public const STATE_NAME = 'client.flow.v2.state.token';
52+
// Denotes that the session was created for the login flow and should therefore be ephemeral.
53+
public const EPHEMERAL_NAME = 'client.flow.v2.state.ephemeral';
5254

5355
private LoginFlowV2Service $loginFlowV2Service;
5456
private IURLGenerator $urlGenerator;

lib/composer/composer/autoload_classmap.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,7 @@
686686
'OC\\AppFramework\\Logger' => $baseDir . '/lib/private/AppFramework/Logger.php',
687687
'OC\\AppFramework\\Middleware\\AdditionalScriptsMiddleware' => $baseDir . '/lib/private/AppFramework/Middleware/AdditionalScriptsMiddleware.php',
688688
'OC\\AppFramework\\Middleware\\CompressionMiddleware' => $baseDir . '/lib/private/AppFramework/Middleware/CompressionMiddleware.php',
689+
'OC\\AppFramework\\Middleware\\FlowV2EphemeralSessionsMiddleware' => $baseDir . '/lib/private/AppFramework/Middleware/FlowV2EphemeralSessionsMiddleware.php',
689690
'OC\\AppFramework\\Middleware\\MiddlewareDispatcher' => $baseDir . '/lib/private/AppFramework/Middleware/MiddlewareDispatcher.php',
690691
'OC\\AppFramework\\Middleware\\NotModifiedMiddleware' => $baseDir . '/lib/private/AppFramework/Middleware/NotModifiedMiddleware.php',
691692
'OC\\AppFramework\\Middleware\\OCSMiddleware' => $baseDir . '/lib/private/AppFramework/Middleware/OCSMiddleware.php',
@@ -779,6 +780,7 @@
779780
'OC\\Authentication\\Login\\CreateSessionTokenCommand' => $baseDir . '/lib/private/Authentication/Login/CreateSessionTokenCommand.php',
780781
'OC\\Authentication\\Login\\EmailLoginCommand' => $baseDir . '/lib/private/Authentication/Login/EmailLoginCommand.php',
781782
'OC\\Authentication\\Login\\FinishRememberedLoginCommand' => $baseDir . '/lib/private/Authentication/Login/FinishRememberedLoginCommand.php',
783+
'OC\\Authentication\\Login\\FlowV2EphemeralSessionsCommand' => $baseDir . '/lib/private/Authentication/Login/FlowV2EphemeralSessionsCommand.php',
782784
'OC\\Authentication\\Login\\LoggedInCheckCommand' => $baseDir . '/lib/private/Authentication/Login/LoggedInCheckCommand.php',
783785
'OC\\Authentication\\Login\\LoginData' => $baseDir . '/lib/private/Authentication/Login/LoginData.php',
784786
'OC\\Authentication\\Login\\LoginResult' => $baseDir . '/lib/private/Authentication/Login/LoginResult.php',

lib/composer/composer/autoload_static.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
719719
'OC\\AppFramework\\Logger' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Logger.php',
720720
'OC\\AppFramework\\Middleware\\AdditionalScriptsMiddleware' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/AdditionalScriptsMiddleware.php',
721721
'OC\\AppFramework\\Middleware\\CompressionMiddleware' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/CompressionMiddleware.php',
722+
'OC\\AppFramework\\Middleware\\FlowV2EphemeralSessionsMiddleware' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/FlowV2EphemeralSessionsMiddleware.php',
722723
'OC\\AppFramework\\Middleware\\MiddlewareDispatcher' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/MiddlewareDispatcher.php',
723724
'OC\\AppFramework\\Middleware\\NotModifiedMiddleware' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/NotModifiedMiddleware.php',
724725
'OC\\AppFramework\\Middleware\\OCSMiddleware' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/OCSMiddleware.php',
@@ -812,6 +813,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
812813
'OC\\Authentication\\Login\\CreateSessionTokenCommand' => __DIR__ . '/../../..' . '/lib/private/Authentication/Login/CreateSessionTokenCommand.php',
813814
'OC\\Authentication\\Login\\EmailLoginCommand' => __DIR__ . '/../../..' . '/lib/private/Authentication/Login/EmailLoginCommand.php',
814815
'OC\\Authentication\\Login\\FinishRememberedLoginCommand' => __DIR__ . '/../../..' . '/lib/private/Authentication/Login/FinishRememberedLoginCommand.php',
816+
'OC\\Authentication\\Login\\FlowV2EphemeralSessionsCommand' => __DIR__ . '/../../..' . '/lib/private/Authentication/Login/FlowV2EphemeralSessionsCommand.php',
815817
'OC\\Authentication\\Login\\LoggedInCheckCommand' => __DIR__ . '/../../..' . '/lib/private/Authentication/Login/LoggedInCheckCommand.php',
816818
'OC\\Authentication\\Login\\LoginData' => __DIR__ . '/../../..' . '/lib/private/Authentication/Login/LoginData.php',
817819
'OC\\Authentication\\Login\\LoginResult' => __DIR__ . '/../../..' . '/lib/private/Authentication/Login/LoginResult.php',

lib/private/AppFramework/DependencyInjection/DIContainer.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
use OC\AppFramework\Http;
3838
use OC\AppFramework\Http\Dispatcher;
3939
use OC\AppFramework\Http\Output;
40+
use OC\AppFramework\Middleware\FlowV2EphemeralSessionsMiddleware;
4041
use OC\AppFramework\Middleware\MiddlewareDispatcher;
4142
use OC\AppFramework\Middleware\OCSMiddleware;
4243
use OC\AppFramework\Middleware\Security\CORSMiddleware;
@@ -236,7 +237,12 @@ public function __construct($appName, $urlParams = [], ServerContainer $server =
236237
)
237238
);
238239

239-
240+
$dispatcher->registerMiddleware(
241+
new FlowV2EphemeralSessionsMiddleware(
242+
$c->get(ISession::class),
243+
$c->get(IUserSession::class),
244+
)
245+
);
240246

241247
$securityMiddleware = new SecurityMiddleware(
242248
$c->get(IRequest::class),
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
/**
5+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
6+
* SPDX-License-Identifier: AGPL-3.0-only
7+
*/
8+
namespace OC\AppFramework\Middleware;
9+
10+
use OC\Core\Controller\ClientFlowLoginV2Controller;
11+
use OCP\AppFramework\Controller;
12+
use OCP\AppFramework\Middleware;
13+
use OCP\ISession;
14+
use OCP\IUserSession;
15+
use ReflectionMethod;
16+
17+
// Will close the session if the user session is ephemeral.
18+
// Happens when the user logs in via the login flow v2.
19+
class FlowV2EphemeralSessionsMiddleware extends Middleware {
20+
public function __construct(
21+
private ISession $session,
22+
private IUserSession $userSession,
23+
) {
24+
}
25+
26+
public function beforeController(Controller $controller, string $methodName) {
27+
if (!$this->session->get(ClientFlowLoginV2Controller::EPHEMERAL_NAME)) {
28+
return;
29+
}
30+
31+
if (
32+
$controller instanceof ClientFlowLoginV2Controller &&
33+
($methodName === 'grantPage' || $methodName === 'generateAppPassword')
34+
) {
35+
return;
36+
}
37+
38+
$reflectionMethod = new ReflectionMethod($controller, $methodName);
39+
if (!empty($reflectionMethod->getAttributes('PublicPage'))) {
40+
return;
41+
}
42+
43+
$this->userSession->logout();
44+
$this->session->close();
45+
}
46+
}

lib/private/Authentication/Login/Chain.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ class Chain {
6363
/** @var FinishRememberedLoginCommand */
6464
private $finishRememberedLoginCommand;
6565

66+
/** @var FlowV2EphemeralSessionsCommand */
67+
private $flowV2EphemeralSessionsCommand;
68+
6669
public function __construct(PreLoginHookCommand $preLoginHookCommand,
6770
UserDisabledCheckCommand $userDisabledCheckCommand,
6871
UidLoginCommand $uidLoginCommand,
@@ -98,6 +101,7 @@ public function process(LoginData $loginData): LoginResult {
98101
->setNext($this->emailLoginCommand)
99102
->setNext($this->loggedInCheckCommand)
100103
->setNext($this->completeLoginCommand)
104+
->setNext($this->flowV2EphemeralSessionsCommand)
101105
->setNext($this->createSessionTokenCommand)
102106
->setNext($this->clearLostPasswordTokensCommand)
103107
->setNext($this->updateLastPasswordConfirmCommand)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/**
6+
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
7+
* SPDX-License-Identifier: AGPL-3.0-or-later
8+
*/
9+
namespace OC\Authentication\Login;
10+
11+
use OC\Core\Controller\ClientFlowLoginV2Controller;
12+
use OCP\ISession;
13+
14+
class FlowV2EphemeralSessionsCommand extends ALoginCommand {
15+
public function __construct(
16+
private ISession $session,
17+
) {
18+
}
19+
20+
public function process(LoginData $loginData): LoginResult {
21+
if (str_starts_with($loginData->getRedirectUrl() ?? '', '/login/v2/grant')) {
22+
$this->session->set(ClientFlowLoginV2Controller::EPHEMERAL_NAME, true);
23+
}
24+
25+
return $this->processNextOrFinishSuccessfully($loginData);
26+
}
27+
}

0 commit comments

Comments
 (0)