Browse Source

Allow using an app token to login with v2 flow auth

Signed-off-by: Julius Härtl <jus@bitgrid.net>
tags/v24.0.0beta1
Julius Härtl 2 years ago
parent
commit
aa3f4bdf63
No account linked to committer's email address

+ 46
- 0
core/Controller/ClientFlowLoginV2Controller.php View File

@@ -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;
@@ -173,6 +174,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
@@ -196,7 +239,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,

+ 17
- 0
core/Service/LoginFlowV2Service.php View File

@@ -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);

+ 1
- 0
core/routes.php View File

@@ -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'],

+ 18
- 0
core/templates/loginflowv2/authpicker.php View File

@@ -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>

</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; ?>

Loading…
Cancel
Save