diff --git a/.vscode/launch.json b/.vscode/launch.json
index 8fd97968..0e2049e9 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -53,7 +53,7 @@
"AYANOVA_FOLDER_USER_FILES": "c:\\temp\\RavenTestData\\userfiles",
"AYANOVA_FOLDER_BACKUP_FILES": "c:\\temp\\RavenTestData\\backupfiles",
"AYANOVA_FOLDER_TEMPORARY_SERVER_FILES": "c:\\temp\\RavenTestData\\tempfiles",
- "AYANOVA_SERVER_TEST_MODE": "true",
+ "AYANOVA_SERVER_TEST_MODE": "false",
"AYANOVA_SERVER_TEST_MODE_SEEDLEVEL": "small",
"AYANOVA_SERVER_TEST_MODE_TZ_OFFSET": "-7",
"AYANOVA_BACKUP_PG_DUMP_PATH": "C:\\data\\code\\postgres_13\\bin\\"
diff --git a/server/AyaNova/Controllers/AuthController.cs b/server/AyaNova/Controllers/AuthController.cs
index 141ed754..a0062011 100644
--- a/server/AyaNova/Controllers/AuthController.cs
+++ b/server/AyaNova/Controllers/AuthController.cs
@@ -432,7 +432,7 @@ namespace AyaNova.Api.Controllers
///
///
/// From route path
- /// New TOTP secret
+ /// Authentication app activation code
[HttpGet("totp")]
public async Task GenerateAndSendTOTP(ApiVersion apiVersion)
{
@@ -454,22 +454,17 @@ namespace AyaNova.Api.Controllers
u.TotpSecret = tfa.CreateSecret(160);
await ct.SaveChangesAsync();
-//https://github.com/google/google-authenticator/wiki/Key-Uri-Format
+ //https://github.com/google/google-authenticator/wiki/Key-Uri-Format
QRCoder.PayloadGenerator.OneTimePassword generator = new QRCoder.PayloadGenerator.OneTimePassword()
{
Secret = u.TotpSecret,
Issuer = "AyaNova",
- //Label = $"AyaNova.{u.Id}",
+ Label = $"AyaNova.acct.{u.Name}",
Type = QRCoder.PayloadGenerator.OneTimePassword.OneTimePasswordAuthType.TOTP
};
string payload = generator.ToString();
- // QRCodeGenerator qrGenerator = new QRCodeGenerator();
- // QRCodeData qrCodeData = qrGenerator.CreateQrCode(payload, QRCodeGenerator.ECCLevel.Q);
- // QRCode qrCode = new QRCode(qrCodeData);
- // var qrCodeAsBitmap = qrCode.GetGraphic(20);
-
QRCodeGenerator qrGenerator = new QRCodeGenerator();
QRCodeData qrCodeData = qrGenerator.CreateQrCode(payload, QRCodeGenerator.ECCLevel.Q);
Base64QRCode qrCode = new Base64QRCode(qrCodeData);
@@ -482,6 +477,46 @@ namespace AyaNova.Api.Controllers
}));
}
+
+ ///
+ /// Confirm 2fa ready to use
+ ///
+ ///
+ /// Auth app 6 digit passcode
+ /// From route path
+ /// OK on success
+ [HttpPost("totp-validate")]
+ public async Task ValidateTOTP([FromBody] OTPPinParam pin, ApiVersion apiVersion)
+ {
+ if (!serverState.IsOpen)
+ return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));
+
+ if (!ModelState.IsValid)
+ return BadRequest(new ApiErrorResponse(ModelState));
+
+ //get user
+ var UserId = UserIdFromContext.Id(HttpContext.Items);
+
+ var u = await ct.User.FirstOrDefaultAsync(z => z.Id == UserId);
+ if (u == null)//should never happen but ?
+ return StatusCode(403, new ApiNotAuthorizedResponse());
+
+ if (u.TwoFactorEnabled)
+ return BadRequest(new ApiErrorResponse(ApiErrorCode.INVALID_OPERATION, "generalerror", "2fa already enabled"));
+
+ if (string.IsNullOrWhiteSpace(u.TotpSecret))
+ return BadRequest(new ApiErrorResponse(ApiErrorCode.INVALID_OPERATION, "generalerror", "2fa activation code not requested yet (missed a step?)"));
+
+ //ok, something to validate, let's validate it
+ var tfa = new TwoFactorAuth("AyaNova");
+ tfa.VerifyCode(u.TotpSecret, pin.Pin);
+
+ return Ok(ApiOkResponse.Response(new
+ {
+ ok = tfa.VerifyCode(u.TotpSecret, pin.Pin)
+ }));
+ }
+
//------------------------------------------------------
public class CredentialsParam
@@ -514,6 +549,12 @@ namespace AyaNova.Api.Controllers
public string PasswordResetCode { get; set; }
[System.ComponentModel.DataAnnotations.Required]
public string Password { get; set; }
+ }
+
+ public class OTPPinParam
+ {
+ [System.ComponentModel.DataAnnotations.Required]
+ public string Pin { get; set; }
}
diff --git a/server/AyaNova/resource/en.json b/server/AyaNova/resource/en.json
index d0e8ca53..94932186 100644
--- a/server/AyaNova/resource/en.json
+++ b/server/AyaNova/resource/en.json
@@ -2167,7 +2167,7 @@
"AlertNotes": "Alert notes",
"AuthTwoFactor":"Two-Factor Authentication",
"AuthConnectAppTitle": "Connect your app",
- "AuthConnectAppSubTitle": "Using an authenticator app such as Google Authenticator, Duo, Microsoft Authenticator or Authy, scan the QR code. It will display a 6 digit pass code which you need to enter below.",
+ "AuthConnectAppSubTitle": "Using an authenticator app such as Google Authenticator, Duo, Microsoft Authenticator, Authy etc, scan the QR code. It will display a 6 digit pass code which you need to enter below.",
"AuthConnectAppManualEntry":"Having trouble scanning the code? Enter the following manually into your authenticator app:",
"AuthEnterPin":"Enter 6 digit pass code"
}
\ No newline at end of file