feature: Provide Text Authenticator Key during 2FA in addition to QR code

This commit is contained in:
usmannasir
2025-06-29 13:50:53 +05:00
parent 500752f43c
commit a930650b2d
3 changed files with 46 additions and 1 deletions

View File

@@ -154,6 +154,32 @@ app.controller('modifyUser', function ($scope, $http) {
} }
}; };
$scope.copySecretKey = function() {
if ($scope.secretKey) {
// Create a temporary textarea element
var tempTextarea = document.createElement('textarea');
tempTextarea.value = $scope.secretKey;
tempTextarea.style.position = 'fixed';
tempTextarea.style.opacity = '0';
document.body.appendChild(tempTextarea);
// Select and copy the text
tempTextarea.select();
tempTextarea.setSelectionRange(0, 99999); // For mobile devices
try {
document.execCommand('copy');
// Show success feedback (you can add a toast notification here if available)
alert('Secret key copied to clipboard!');
} catch (err) {
alert('Failed to copy secret key. Please copy it manually.');
}
// Remove the temporary element
document.body.removeChild(tempTextarea);
}
};
$scope.fetchUserDetails = function () { $scope.fetchUserDetails = function () {
@@ -192,6 +218,12 @@ app.controller('modifyUser', function ($scope, $http) {
$scope.currentSecurityLevel = userDetails.securityLevel; $scope.currentSecurityLevel = userDetails.securityLevel;
$scope.twofa = Boolean(userDetails.twofa); $scope.twofa = Boolean(userDetails.twofa);
// Format secret key with spaces for better readability
if (userDetails.secretKey) {
$scope.secretKey = userDetails.secretKey;
$scope.formattedSecretKey = userDetails.secretKey.match(/.{1,4}/g).join(' ');
}
qrCode.set({ qrCode.set({
value: userDetails.otpauth value: userDetails.otpauth
}); });

View File

@@ -286,6 +286,18 @@
<div style="max-width:220px;"> <div style="max-width:220px;">
<canvas id="qr"></canvas> <canvas id="qr"></canvas>
</div> </div>
<div class="mt-3">
<p class="help-text mb-2">{% trans "Or manually enter this key:" %}</p>
<div class="input-group" style="max-width:350px;">
<input type="text" class="form-control" ng-model="formattedSecretKey" readonly style="font-family: monospace; font-size: 14px;">
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button" ng-click="copySecretKey()" title="{% trans 'Copy to clipboard' %}">
<i class="fa fa-copy"></i>
</button>
</div>
</div>
<small class="text-muted mt-1 d-block">{% trans "Enter this key in your authenticator app if you cannot scan QR codes." %}</small>
</div>
</div> </div>
</div> </div>
<div class="form-group" style="margin-top: 2rem;"> <div class="form-group" style="margin-top: 2rem;">

View File

@@ -310,7 +310,8 @@ def fetchUserDetails(request):
"websitesLimit": websitesLimit, "websitesLimit": websitesLimit,
"securityLevel": SecurityLevel(user.securityLevel).name, "securityLevel": SecurityLevel(user.securityLevel).name,
"otpauth": otpauth, "otpauth": otpauth,
'twofa': user.twoFA 'twofa': user.twoFA,
'secretKey': user.secretKey
} }
data_ret = {'fetchStatus': 1, 'error_message': 'None', "userDetails": userDetails} data_ret = {'fetchStatus': 1, 'error_message': 'None', "userDetails": userDetails}