mirror of
https://github.com/nextcloud/server.git
synced 2026-06-08 16:26:59 -04:00
fix: add app config to control onetime case
Signed-off-by: Joas Schilling <coding@schilljs.com>
This commit is contained in:
parent
e7d0ed2020
commit
bacb4323de
4 changed files with 30 additions and 32 deletions
|
|
@ -20,6 +20,7 @@ use OCP\Config\ValueType;
|
|||
* Please Add & Manage your Config Keys in that file and keep the Lexicon up to date!
|
||||
*/
|
||||
class ConfigLexicon implements ILexicon {
|
||||
public const LOGIN_QRCODE_ONETIME = 'qrcode_onetime';
|
||||
public const USER_SETTINGS_EMAIL = 'email';
|
||||
public const USER_LIST_SHOW_STORAGE_PATH = 'user_list_show_storage_path';
|
||||
public const USER_LIST_SHOW_USER_BACKEND = 'user_list_show_user_backend';
|
||||
|
|
@ -33,7 +34,9 @@ class ConfigLexicon implements ILexicon {
|
|||
}
|
||||
|
||||
public function getAppConfigs(): array {
|
||||
return [];
|
||||
return [
|
||||
new Entry(key: self::LOGIN_QRCODE_ONETIME, type: ValueType::BOOL, defaultRaw: false, definition: 'Use onetime QR codes for app passwords', note: 'Limits compatibility for mobile apps to versions released in 2026 or later'),
|
||||
];
|
||||
}
|
||||
|
||||
public function getUserConfigs(): array {
|
||||
|
|
|
|||
|
|
@ -14,12 +14,14 @@ use OC\Authentication\Token\INamedToken;
|
|||
use OC\Authentication\Token\IProvider;
|
||||
use OC\Authentication\Token\RemoteWipe;
|
||||
use OCA\Settings\Activity\Provider;
|
||||
use OCA\Settings\ConfigLexicon;
|
||||
use OCP\Activity\IManager;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
|
||||
use OCP\AppFramework\Http\Attribute\PasswordConfirmationRequired;
|
||||
use OCP\AppFramework\Http\JSONResponse;
|
||||
use OCP\AppFramework\Services\IAppConfig;
|
||||
use OCP\Authentication\Exceptions\ExpiredTokenException;
|
||||
use OCP\Authentication\Exceptions\InvalidTokenException;
|
||||
use OCP\Authentication\Exceptions\WipeTokenException;
|
||||
|
|
@ -32,49 +34,31 @@ use OCP\Session\Exceptions\SessionNotAvailableException;
|
|||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class AuthSettingsController extends Controller {
|
||||
/** @var IProvider */
|
||||
private $tokenProvider;
|
||||
|
||||
/** @var RemoteWipe */
|
||||
private $remoteWipe;
|
||||
|
||||
/**
|
||||
* @param string $appName
|
||||
* @param IRequest $request
|
||||
* @param IProvider $tokenProvider
|
||||
* @param ISession $session
|
||||
* @param ISecureRandom $random
|
||||
* @param string|null $userId
|
||||
* @param IUserSession $userSession
|
||||
* @param IManager $activityManager
|
||||
* @param RemoteWipe $remoteWipe
|
||||
* @param LoggerInterface $logger
|
||||
*/
|
||||
public function __construct(
|
||||
string $appName,
|
||||
IRequest $request,
|
||||
IProvider $tokenProvider,
|
||||
private IProvider $tokenProvider,
|
||||
private ISession $session,
|
||||
private ISecureRandom $random,
|
||||
private ?string $userId,
|
||||
private IUserSession $userSession,
|
||||
private IManager $activityManager,
|
||||
RemoteWipe $remoteWipe,
|
||||
private IAppConfig $appConfig,
|
||||
private RemoteWipe $remoteWipe,
|
||||
private LoggerInterface $logger,
|
||||
) {
|
||||
parent::__construct($appName, $request);
|
||||
$this->tokenProvider = $tokenProvider;
|
||||
$this->remoteWipe = $remoteWipe;
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoSubAdminRequired
|
||||
*
|
||||
* @param bool $oneTime If set to true, the returned token can only be used to get the actual app password a single time
|
||||
* @param bool $qrcodeLogin If set to true, the returned token could be (depending on server settings) a onetime password, that can only be used to get the actual app password a single time
|
||||
*/
|
||||
#[NoAdminRequired]
|
||||
#[PasswordConfirmationRequired]
|
||||
public function create(string $name = '', bool $oneTime = false): JSONResponse {
|
||||
public function create(string $name = '', bool $qrcodeLogin = false): JSONResponse {
|
||||
if ($this->checkAppToken()) {
|
||||
return $this->getServiceNotAvailableResponse();
|
||||
}
|
||||
|
|
@ -100,10 +84,16 @@ class AuthSettingsController extends Controller {
|
|||
return $this->getServiceNotAvailableResponse();
|
||||
}
|
||||
|
||||
if ($oneTime) {
|
||||
$name = 'One time login';
|
||||
$type = IToken::ONETIME_TOKEN;
|
||||
$scope = [];
|
||||
if ($qrcodeLogin) {
|
||||
if ($this->appConfig->getAppValueBool(ConfigLexicon::LOGIN_QRCODE_ONETIME)) {
|
||||
$name = 'One time login';
|
||||
$type = IToken::ONETIME_TOKEN;
|
||||
$scope = [];
|
||||
} else {
|
||||
$name = 'QR Code login';
|
||||
$type = IToken::PERMANENT_TOKEN;
|
||||
$scope = null;
|
||||
}
|
||||
} elseif ($name === '') {
|
||||
// No name is only allowed for one time logins
|
||||
return $this->getServiceNotAvailableResponse();
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ export default defineComponent({
|
|||
async handleQrCodeClick() {
|
||||
await confirmPassword()
|
||||
|
||||
const { data } = await axios.post<ITokenResponse>(generateUrl('/settings/personal/authtokens'), { name: '', oneTime: true })
|
||||
const { data } = await axios.post<ITokenResponse>(generateUrl('/settings/personal/authtokens'), { qrcodeLogin: true })
|
||||
|
||||
await spawnDialog(AccountQrLoginDialog, { data })
|
||||
},
|
||||
|
|
|
|||
|
|
@ -41,13 +41,16 @@ const buttons = [{
|
|||
callback: () => undefined,
|
||||
}]
|
||||
|
||||
const isOneTimeToken = (props.data?.deviceToken?.type ?? 1) === 3
|
||||
|
||||
const qrUrl = computed(() => {
|
||||
const user = props.data?.loginName ?? ''
|
||||
const password = props.data?.token ?? ''
|
||||
const path = isOneTimeToken ? 'onetime-login' : 'login'
|
||||
const server = getBaseUrl()
|
||||
|
||||
// TODO return different result for error handling (to not provide invalid URL)
|
||||
return `nc://onetime-login/user:${user}&password:${password}&server:${server}`
|
||||
return `nc://${path}/user:${user}&password:${password}&server:${server}`
|
||||
})
|
||||
|
||||
const expirationTimestamp = (props.data?.deviceToken?.lastActivity ? props.data.deviceToken.lastActivity * 1_000 : Date.now()) + 120_000
|
||||
|
|
@ -77,8 +80,10 @@ function onClosing(result: unknown) {
|
|||
{{ t('core', 'Use {productName} mobile client you want to connect to scan the code', { productName }) }}
|
||||
</p>
|
||||
<QR :value="qrUrl" />
|
||||
<!-- TRANSLATORS Intl will provide a conjunction, e.g. 'Code will expire in 30 seconds' -->
|
||||
{{ t('core', 'Code will expire {timeCountdown} or after use', { timeCountdown }) }}
|
||||
<template v-if="isOneTimeToken">
|
||||
<!-- TRANSLATORS Intl will provide a conjunction, e.g. 'Code will expire in 30 seconds' -->
|
||||
{{ t('core', 'Code will expire {timeCountdown} or after use', { timeCountdown }) }}
|
||||
</template>
|
||||
</div>
|
||||
</NcDialog>
|
||||
</template>
|
||||
|
|
|
|||
Loading…
Reference in a new issue