Skip to content

Commit c7900de

Browse files
authored
Merge pull request #51051 from nextcloud/artonge/fix/login_flow_v2_sessions_2
feat: Close sessions created for login flow v2
2 parents 7ef9ffa + c629320 commit c7900de

File tree

7 files changed

+101
-61
lines changed

7 files changed

+101
-61
lines changed

core/Controller/ClientFlowLoginV2Controller.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
class ClientFlowLoginV2Controller extends Controller {
4242
public const TOKEN_NAME = 'client.flow.v2.login.token';
4343
public const STATE_NAME = 'client.flow.v2.state.token';
44+
// Denotes that the session was created for the login flow and should therefore be ephemeral.
45+
public const EPHEMERAL_NAME = 'client.flow.v2.state.ephemeral';
4446

4547
public function __construct(
4648
string $appName,

lib/composer/composer/autoload_classmap.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -982,6 +982,7 @@
982982
'OC\\AppFramework\\Http\\RequestId' => $baseDir . '/lib/private/AppFramework/Http/RequestId.php',
983983
'OC\\AppFramework\\Middleware\\AdditionalScriptsMiddleware' => $baseDir . '/lib/private/AppFramework/Middleware/AdditionalScriptsMiddleware.php',
984984
'OC\\AppFramework\\Middleware\\CompressionMiddleware' => $baseDir . '/lib/private/AppFramework/Middleware/CompressionMiddleware.php',
985+
'OC\\AppFramework\\Middleware\\FlowV2EphemeralSessionsMiddleware' => $baseDir . '/lib/private/AppFramework/Middleware/FlowV2EphemeralSessionsMiddleware.php',
985986
'OC\\AppFramework\\Middleware\\MiddlewareDispatcher' => $baseDir . '/lib/private/AppFramework/Middleware/MiddlewareDispatcher.php',
986987
'OC\\AppFramework\\Middleware\\NotModifiedMiddleware' => $baseDir . '/lib/private/AppFramework/Middleware/NotModifiedMiddleware.php',
987988
'OC\\AppFramework\\Middleware\\OCSMiddleware' => $baseDir . '/lib/private/AppFramework/Middleware/OCSMiddleware.php',
@@ -1079,6 +1080,7 @@
10791080
'OC\\Authentication\\Login\\CreateSessionTokenCommand' => $baseDir . '/lib/private/Authentication/Login/CreateSessionTokenCommand.php',
10801081
'OC\\Authentication\\Login\\EmailLoginCommand' => $baseDir . '/lib/private/Authentication/Login/EmailLoginCommand.php',
10811082
'OC\\Authentication\\Login\\FinishRememberedLoginCommand' => $baseDir . '/lib/private/Authentication/Login/FinishRememberedLoginCommand.php',
1083+
'OC\\Authentication\\Login\\FlowV2EphemeralSessionsCommand' => $baseDir . '/lib/private/Authentication/Login/FlowV2EphemeralSessionsCommand.php',
10821084
'OC\\Authentication\\Login\\LoggedInCheckCommand' => $baseDir . '/lib/private/Authentication/Login/LoggedInCheckCommand.php',
10831085
'OC\\Authentication\\Login\\LoginData' => $baseDir . '/lib/private/Authentication/Login/LoginData.php',
10841086
'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
@@ -1031,6 +1031,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
10311031
'OC\\AppFramework\\Http\\RequestId' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Http/RequestId.php',
10321032
'OC\\AppFramework\\Middleware\\AdditionalScriptsMiddleware' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/AdditionalScriptsMiddleware.php',
10331033
'OC\\AppFramework\\Middleware\\CompressionMiddleware' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/CompressionMiddleware.php',
1034+
'OC\\AppFramework\\Middleware\\FlowV2EphemeralSessionsMiddleware' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/FlowV2EphemeralSessionsMiddleware.php',
10341035
'OC\\AppFramework\\Middleware\\MiddlewareDispatcher' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/MiddlewareDispatcher.php',
10351036
'OC\\AppFramework\\Middleware\\NotModifiedMiddleware' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/NotModifiedMiddleware.php',
10361037
'OC\\AppFramework\\Middleware\\OCSMiddleware' => __DIR__ . '/../../..' . '/lib/private/AppFramework/Middleware/OCSMiddleware.php',
@@ -1128,6 +1129,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
11281129
'OC\\Authentication\\Login\\CreateSessionTokenCommand' => __DIR__ . '/../../..' . '/lib/private/Authentication/Login/CreateSessionTokenCommand.php',
11291130
'OC\\Authentication\\Login\\EmailLoginCommand' => __DIR__ . '/../../..' . '/lib/private/Authentication/Login/EmailLoginCommand.php',
11301131
'OC\\Authentication\\Login\\FinishRememberedLoginCommand' => __DIR__ . '/../../..' . '/lib/private/Authentication/Login/FinishRememberedLoginCommand.php',
1132+
'OC\\Authentication\\Login\\FlowV2EphemeralSessionsCommand' => __DIR__ . '/../../..' . '/lib/private/Authentication/Login/FlowV2EphemeralSessionsCommand.php',
11311133
'OC\\Authentication\\Login\\LoggedInCheckCommand' => __DIR__ . '/../../..' . '/lib/private/Authentication/Login/LoggedInCheckCommand.php',
11321134
'OC\\Authentication\\Login\\LoginData' => __DIR__ . '/../../..' . '/lib/private/Authentication/Login/LoginData.php',
11331135
'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
@@ -10,6 +10,7 @@
1010
use OC\AppFramework\Http;
1111
use OC\AppFramework\Http\Dispatcher;
1212
use OC\AppFramework\Http\Output;
13+
use OC\AppFramework\Middleware\FlowV2EphemeralSessionsMiddleware;
1314
use OC\AppFramework\Middleware\MiddlewareDispatcher;
1415
use OC\AppFramework\Middleware\OCSMiddleware;
1516
use OC\AppFramework\Middleware\Security\CORSMiddleware;
@@ -216,7 +217,12 @@ public function __construct(string $appName, array $urlParams = [], ?ServerConta
216217
)
217218
);
218219

219-
220+
$dispatcher->registerMiddleware(
221+
new FlowV2EphemeralSessionsMiddleware(
222+
$c->get(ISession::class),
223+
$c->get(IUserSession::class),
224+
)
225+
);
220226

221227
$securityMiddleware = new SecurityMiddleware(
222228
$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: 15 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -9,67 +9,21 @@
99
namespace OC\Authentication\Login;
1010

1111
class Chain {
12-
/** @var PreLoginHookCommand */
13-
private $preLoginHookCommand;
14-
15-
/** @var UserDisabledCheckCommand */
16-
private $userDisabledCheckCommand;
17-
18-
/** @var UidLoginCommand */
19-
private $uidLoginCommand;
20-
21-
/** @var EmailLoginCommand */
22-
private $emailLoginCommand;
23-
24-
/** @var LoggedInCheckCommand */
25-
private $loggedInCheckCommand;
26-
27-
/** @var CompleteLoginCommand */
28-
private $completeLoginCommand;
29-
30-
/** @var CreateSessionTokenCommand */
31-
private $createSessionTokenCommand;
32-
33-
/** @var ClearLostPasswordTokensCommand */
34-
private $clearLostPasswordTokensCommand;
35-
36-
/** @var UpdateLastPasswordConfirmCommand */
37-
private $updateLastPasswordConfirmCommand;
38-
39-
/** @var SetUserTimezoneCommand */
40-
private $setUserTimezoneCommand;
41-
42-
/** @var TwoFactorCommand */
43-
private $twoFactorCommand;
44-
45-
/** @var FinishRememberedLoginCommand */
46-
private $finishRememberedLoginCommand;
47-
48-
public function __construct(PreLoginHookCommand $preLoginHookCommand,
49-
UserDisabledCheckCommand $userDisabledCheckCommand,
50-
UidLoginCommand $uidLoginCommand,
51-
EmailLoginCommand $emailLoginCommand,
52-
LoggedInCheckCommand $loggedInCheckCommand,
53-
CompleteLoginCommand $completeLoginCommand,
54-
CreateSessionTokenCommand $createSessionTokenCommand,
55-
ClearLostPasswordTokensCommand $clearLostPasswordTokensCommand,
56-
UpdateLastPasswordConfirmCommand $updateLastPasswordConfirmCommand,
57-
SetUserTimezoneCommand $setUserTimezoneCommand,
58-
TwoFactorCommand $twoFactorCommand,
59-
FinishRememberedLoginCommand $finishRememberedLoginCommand,
12+
public function __construct(
13+
private PreLoginHookCommand $preLoginHookCommand,
14+
private UserDisabledCheckCommand $userDisabledCheckCommand,
15+
private UidLoginCommand $uidLoginCommand,
16+
private EmailLoginCommand $emailLoginCommand,
17+
private LoggedInCheckCommand $loggedInCheckCommand,
18+
private CompleteLoginCommand $completeLoginCommand,
19+
private CreateSessionTokenCommand $createSessionTokenCommand,
20+
private ClearLostPasswordTokensCommand $clearLostPasswordTokensCommand,
21+
private UpdateLastPasswordConfirmCommand $updateLastPasswordConfirmCommand,
22+
private SetUserTimezoneCommand $setUserTimezoneCommand,
23+
private TwoFactorCommand $twoFactorCommand,
24+
private FinishRememberedLoginCommand $finishRememberedLoginCommand,
25+
private FlowV2EphemeralSessionsCommand $flowV2EphemeralSessionsCommand,
6026
) {
61-
$this->preLoginHookCommand = $preLoginHookCommand;
62-
$this->userDisabledCheckCommand = $userDisabledCheckCommand;
63-
$this->uidLoginCommand = $uidLoginCommand;
64-
$this->emailLoginCommand = $emailLoginCommand;
65-
$this->loggedInCheckCommand = $loggedInCheckCommand;
66-
$this->completeLoginCommand = $completeLoginCommand;
67-
$this->createSessionTokenCommand = $createSessionTokenCommand;
68-
$this->clearLostPasswordTokensCommand = $clearLostPasswordTokensCommand;
69-
$this->updateLastPasswordConfirmCommand = $updateLastPasswordConfirmCommand;
70-
$this->setUserTimezoneCommand = $setUserTimezoneCommand;
71-
$this->twoFactorCommand = $twoFactorCommand;
72-
$this->finishRememberedLoginCommand = $finishRememberedLoginCommand;
7327
}
7428

7529
public function process(LoginData $loginData): LoginResult {
@@ -80,6 +34,7 @@ public function process(LoginData $loginData): LoginResult {
8034
->setNext($this->emailLoginCommand)
8135
->setNext($this->loggedInCheckCommand)
8236
->setNext($this->completeLoginCommand)
37+
->setNext($this->flowV2EphemeralSessionsCommand)
8338
->setNext($this->createSessionTokenCommand)
8439
->setNext($this->clearLostPasswordTokensCommand)
8540
->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)