From aa3f4bdf6351a600f1b422c6ab1daf75727c265e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Julius=20H=C3=A4rtl?=
Date: Wed, 3 Nov 2021 10:54:02 +0100
Subject: [PATCH 1/2] Allow using an app token to login with v2 flow auth
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Julius Härtl
---
.../ClientFlowLoginV2Controller.php | 46 +++++++++++++++++++
core/Service/LoginFlowV2Service.php | 17 +++++++
core/routes.php | 1 +
core/templates/loginflowv2/authpicker.php | 18 ++++++++
4 files changed, 82 insertions(+)
diff --git a/core/Controller/ClientFlowLoginV2Controller.php b/core/Controller/ClientFlowLoginV2Controller.php
index 205c1ff8a1c74..84321d33e13fb 100644
--- a/core/Controller/ClientFlowLoginV2Controller.php
+++ b/core/Controller/ClientFlowLoginV2Controller.php
@@ -27,6 +27,7 @@
*/
namespace OC\Core\Controller;
+use OC\Authentication\Exceptions\InvalidTokenException;
use OC\Core\Db\LoginFlowV2;
use OC\Core\Exception\LoginFlowV2NotFoundException;
use OC\Core\Service\LoginFlowV2Service;
@@ -173,6 +174,48 @@ public function grantPage(string $stateToken): StandaloneTemplateResponse {
);
}
+ /**
+ * @PublicPage
+ */
+ public function apptokenRedirect(string $stateToken, string $user, string $password) {
+ if (!$this->isValidStateToken($stateToken)) {
+ return $this->stateTokenForbiddenResponse();
+ }
+
+ try {
+ $this->getFlowByLoginToken();
+ } catch (LoginFlowV2NotFoundException $e) {
+ return $this->loginTokenForbiddenResponse();
+ }
+
+ $loginToken = $this->session->get(self::TOKEN_NAME);
+
+ // Clear session variables
+ $this->session->remove(self::TOKEN_NAME);
+ $this->session->remove(self::STATE_NAME);
+
+ try {
+ $token = \OC::$server->get(\OC\Authentication\Token\IProvider::class)->getToken($password);
+ if ($token->getLoginName() !== $user) {
+ throw new InvalidTokenException('login name does not match');
+ }
+ } catch (InvalidTokenException $e) {
+ $response = new StandaloneTemplateResponse(
+ $this->appName,
+ '403',
+ [
+ 'message' => $this->l10n->t('Invalid app password'),
+ ],
+ 'guest'
+ );
+ $response->setStatus(Http::STATUS_FORBIDDEN);
+ return $response;
+ }
+
+ $result = $this->loginFlowV2Service->flowDoneWithAppPassword($loginToken, $this->getServerPath(), $this->userId, $password);
+ return $this->handleFlowDone($result);
+ }
+
/**
* @NoAdminRequired
* @UseSession
@@ -196,7 +239,10 @@ public function generateAppPassword(string $stateToken): Response {
$sessionId = $this->session->getId();
$result = $this->loginFlowV2Service->flowDone($loginToken, $sessionId, $this->getServerPath(), $this->userId);
+ return $this->handleFlowDone($result);
+ }
+ private function handleFlowDone(bool $result): StandaloneTemplateResponse {
if ($result) {
return new StandaloneTemplateResponse(
$this->appName,
diff --git a/core/Service/LoginFlowV2Service.php b/core/Service/LoginFlowV2Service.php
index 6f8c7966e2733..8710cab5cae64 100644
--- a/core/Service/LoginFlowV2Service.php
+++ b/core/Service/LoginFlowV2Service.php
@@ -186,6 +186,23 @@ public function flowDone(string $loginToken, string $sessionId, string $server,
return true;
}
+ public function flowDoneWithAppPassword(string $loginToken, string $server, string $loginName, string $appPassword): bool {
+ try {
+ $data = $this->mapper->getByLoginToken($loginToken);
+ } catch (DoesNotExistException $e) {
+ return false;
+ }
+
+ $data->setLoginName($loginName);
+ $data->setServer($server);
+
+ // Properly encrypt
+ $data->setAppPassword($this->encryptPassword($appPassword, $data->getPublicKey()));
+
+ $this->mapper->update($data);
+ return true;
+ }
+
public function createTokens(string $userAgent): LoginFlowV2Tokens {
$flow = new LoginFlowV2();
$pollToken = $this->random->generate(128, ISecureRandom::CHAR_DIGITS.ISecureRandom::CHAR_LOWER.ISecureRandom::CHAR_UPPER);
diff --git a/core/routes.php b/core/routes.php
index 5750dac2ad1b7..c3bbb7337ba85 100644
--- a/core/routes.php
+++ b/core/routes.php
@@ -68,6 +68,7 @@
['name' => 'ClientFlowLoginV2#grantPage', 'url' => '/login/v2/grant', 'verb' => 'GET'],
['name' => 'ClientFlowLoginV2#generateAppPassword', 'url' => '/login/v2/grant', 'verb' => 'POST'],
['name' => 'ClientFlowLoginV2#init', 'url' => '/login/v2', 'verb' => 'POST'],
+ ['name' => 'ClientFlowLoginV2#apptokenRedirect', 'url' => '/login/v2/apptoken', 'verb' => 'POST'],
['name' => 'TwoFactorChallenge#selectChallenge', 'url' => '/login/selectchallenge', 'verb' => 'GET'],
['name' => 'TwoFactorChallenge#showChallenge', 'url' => '/login/challenge/{challengeProviderId}', 'verb' => 'GET'],
['name' => 'TwoFactorChallenge#solveChallenge', 'url' => '/login/challenge/{challengeProviderId}', 'verb' => 'POST'],
diff --git a/core/templates/loginflowv2/authpicker.php b/core/templates/loginflowv2/authpicker.php
index ce993ea20920d..468eed99e35c3 100644
--- a/core/templates/loginflowv2/authpicker.php
+++ b/core/templates/loginflowv2/authpicker.php
@@ -20,6 +20,7 @@
*/
style('core', 'login/authpicker');
+script('core', 'login/authpicker');
/** @var array $_ */
/** @var \OCP\IURLGenerator $urlGenerator */
@@ -50,4 +51,21 @@
+
+
+
+ t('Alternative log in using app token')) ?>
+
From cdda25acb49e50e5989743c0251b394dbbebcaa5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Julius=20H=C3=A4rtl?=
Date: Fri, 3 Dec 2021 08:44:09 +0100
Subject: [PATCH 2/2] Adjust auth token link design
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Julius Härtl
---
core/css/login/authpicker.css | 5 +++++
core/templates/loginflow/authpicker.php | 8 ++++----
core/templates/loginflowv2/authpicker.php | 6 +++---
3 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/core/css/login/authpicker.css b/core/css/login/authpicker.css
index 3603a7906e45f..d245c48680ff4 100644
--- a/core/css/login/authpicker.css
+++ b/core/css/login/authpicker.css
@@ -7,3 +7,8 @@
border-radius: 3px;
cursor: default;
}
+
+.apptoken-link {
+ margin: 20px;
+ display: block;
+}
diff --git a/core/templates/loginflow/authpicker.php b/core/templates/loginflow/authpicker.php
index 02b4b9cc003b4..e0980a8d2b32e 100644
--- a/core/templates/loginflow/authpicker.php
+++ b/core/templates/loginflow/authpicker.php
@@ -64,8 +64,8 @@
-
-
-t('Alternative log in using app token')) ?>
-
+
+ t('Alternative log in using app token')) ?>
+
+
diff --git a/core/templates/loginflowv2/authpicker.php b/core/templates/loginflowv2/authpicker.php
index 468eed99e35c3..af49ed6d760fa 100644
--- a/core/templates/loginflowv2/authpicker.php
+++ b/core/templates/loginflowv2/authpicker.php
@@ -65,7 +65,7 @@
+
+ t('Alternative log in using app token')) ?>
+
-
- t('Alternative log in using app token')) ?>
-