summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorJohn Molakvoæ <skjnldsv@users.noreply.github.com>2021-12-30 08:14:23 +0100
committerGitHub <noreply@github.com>2021-12-30 08:14:23 +0100
commitbfaeb6ae64b01d591c8122ccb8ba4f7af98652c7 (patch)
treee424b97303d34c95befc9bc2a8d43bb590cf3b02 /core
parentbf6388ef2d1b13829ef85dc83d6ccbd5e43759bb (diff)
parentcdda25acb49e50e5989743c0251b394dbbebcaa5 (diff)
downloadnextcloud-server-bfaeb6ae64b01d591c8122ccb8ba4f7af98652c7.tar.gz
nextcloud-server-bfaeb6ae64b01d591c8122ccb8ba4f7af98652c7.zip
Merge pull request #29531 from nextcloud/bugfix/noid/flow-auth-v2-apptoken
Diffstat (limited to 'core')
-rw-r--r--core/Controller/ClientFlowLoginV2Controller.php46
-rw-r--r--core/Service/LoginFlowV2Service.php17
-rw-r--r--core/css/login/authpicker.css5
-rw-r--r--core/routes.php1
-rw-r--r--core/templates/loginflow/authpicker.php8
-rw-r--r--core/templates/loginflowv2/authpicker.php18
6 files changed, 91 insertions, 4 deletions
diff --git a/core/Controller/ClientFlowLoginV2Controller.php b/core/Controller/ClientFlowLoginV2Controller.php
index 46031356ba5..ab46cb4b729 100644
--- a/core/Controller/ClientFlowLoginV2Controller.php
+++ b/core/Controller/ClientFlowLoginV2Controller.php
@@ -27,6 +27,7 @@ declare(strict_types=1);
*/
namespace OC\Core\Controller;
+use OC\Authentication\Exceptions\InvalidTokenException;
use OC\Core\Db\LoginFlowV2;
use OC\Core\Exception\LoginFlowV2NotFoundException;
use OC\Core\Service\LoginFlowV2Service;
@@ -175,6 +176,48 @@ class ClientFlowLoginV2Controller extends Controller {
}
/**
+ * @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
*/
@@ -197,7 +240,10 @@ class ClientFlowLoginV2Controller extends Controller {
$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 6f8c7966e27..8710cab5cae 100644
--- a/core/Service/LoginFlowV2Service.php
+++ b/core/Service/LoginFlowV2Service.php
@@ -186,6 +186,23 @@ class LoginFlowV2Service {
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/css/login/authpicker.css b/core/css/login/authpicker.css
index 3603a7906e4..d245c48680f 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/routes.php b/core/routes.php
index 5750dac2ad1..c3bbb7337ba 100644
--- a/core/routes.php
+++ b/core/routes.php
@@ -68,6 +68,7 @@ $application->registerRoutes($this, [
['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/loginflow/authpicker.php b/core/templates/loginflow/authpicker.php
index 128429cb0b3..d8ef2998d13 100644
--- a/core/templates/loginflow/authpicker.php
+++ b/core/templates/loginflow/authpicker.php
@@ -64,8 +64,8 @@ $urlGenerator = $_['urlGenerator'];
<input type="hidden" name="requesttoken" value="<?php p($_['requesttoken']) ?>">
<input id="submit-app-token-login" type="submit" class="login primary icon-confirm-white" value="<?php p($l->t('Grant access')) ?>">
</form>
-</div>
-<?php if (empty($_['oauthState'])): ?>
-<a id="app-token-login" class="warning" href="#"><?php p($l->t('Alternative log in using app token')) ?></a>
-<?php endif; ?>
+ <?php if (empty($_['oauthState'])): ?>
+ <a id="app-token-login" class="apptoken-link" href="#"><?php p($l->t('Alternative log in using app token')) ?></a>
+ <?php endif; ?>
+</div>
diff --git a/core/templates/loginflowv2/authpicker.php b/core/templates/loginflowv2/authpicker.php
index 42eb72aee33..8caa42f2ce8 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 @@ $urlGenerator = $_['urlGenerator'];
</a>
</p>
+ <form action="<?php p($urlGenerator->linkToRouteAbsolute('core.ClientFlowLoginV2.apptokenRedirect')); ?>" method="post" id="app-token-login-field" class="hidden">
+ <p class="grouptop">
+ <input type="text" name="user" id="user" placeholder="<?php p($l->t('Username')) ?>">
+ <label for="user" class="infield"><?php p($l->t('Username')) ?></label>
+ </p>
+ <p class="groupbottom">
+ <input type="password" name="password" id="password" placeholder="<?php p($l->t('App token')) ?>">
+ <label for="password" class="infield"><?php p($l->t('Password')) ?></label>
+ </p>
+ <input type="hidden" name="stateToken" value="<?php p($_['stateToken']) ?>" />
+ <input type="hidden" name="requesttoken" value="<?php p($_['requesttoken']) ?>">
+ <input id="submit-app-token-login" type="submit" class="login primary icon-confirm-white" value="<?php p($l->t('Grant access')) ?>">
+ </form>
+
+ <?php if (empty($_['oauthState'])): ?>
+ <a id="app-token-login" class="apptoken-link" href="#"><?php p($l->t('Alternative log in using app token')) ?></a>
+ <?php endif; ?>
</div>