aboutsummaryrefslogtreecommitdiff
path: root/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints')
-rw-r--r--plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/KeepAliveEndpoint.cs25
-rw-r--r--plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/LoginEndpoint.cs10
-rw-r--r--plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/MFAEndpoint.cs6
3 files changed, 38 insertions, 3 deletions
diff --git a/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/KeepAliveEndpoint.cs b/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/KeepAliveEndpoint.cs
index fe5a65b..0ff0869 100644
--- a/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/KeepAliveEndpoint.cs
+++ b/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/KeepAliveEndpoint.cs
@@ -27,14 +27,19 @@ using System.Net;
using System.Text.Json;
using System.Collections.Generic;
+using VNLib.Utils.Extensions;
using VNLib.Plugins.Essentials.Endpoints;
+using VNLib.Plugins.Essentials.Extensions;
using VNLib.Plugins.Extensions.Loading;
+
namespace VNLib.Plugins.Essentials.Accounts.Endpoints
{
[ConfigurationName("keepalive_endpoint")]
internal sealed class KeepAliveEndpoint : ProtectedWebEndpoint
{
+ readonly TimeSpan tokenRegenTime;
+
/*
* Endpoint does not use a log, so IniPathAndLog is never called
* and path verification happens verbosly
@@ -43,6 +48,8 @@ namespace VNLib.Plugins.Essentials.Accounts.Endpoints
{
string? path = config["path"].GetString();
+ tokenRegenTime = config["token_refresh_sec"].GetTimeSpan(TimeParseType.Seconds);
+
InitPathAndLog(path, pbase.Log);
}
@@ -56,6 +63,24 @@ namespace VNLib.Plugins.Essentials.Accounts.Endpoints
//Allow post to update user's credentials
protected override VfReturnType Post(HttpEntity entity)
{
+ //Get the last token update
+ DateTimeOffset lastTokenUpdate = entity.Session.LastTokenUpgrade();
+
+ //See if its expired
+ if (lastTokenUpdate.Add(tokenRegenTime) < entity.RequestedTimeUtc)
+ {
+ //if so updaet token
+ WebMessage webm = new()
+ {
+ Token = entity.RegenerateClientToken(),
+ Success = true
+ };
+
+ //Send the update message to the client
+ entity.CloseResponse(webm);
+ return VfReturnType.VirtualSkip;
+ }
+
//Return okay
entity.CloseResponse(HttpStatusCode.OK);
return VfReturnType.VirtualSkip;
diff --git a/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/LoginEndpoint.cs b/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/LoginEndpoint.cs
index 4100620..f973fe8 100644
--- a/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/LoginEndpoint.cs
+++ b/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/LoginEndpoint.cs
@@ -44,7 +44,7 @@ using VNLib.Plugins.Essentials.Accounts.Validators;
using VNLib.Plugins.Extensions.Loading;
using VNLib.Plugins.Extensions.Loading.Users;
using static VNLib.Plugins.Essentials.Statics;
-using static VNLib.Plugins.Essentials.Accounts.AccountManager;
+using static VNLib.Plugins.Essentials.Accounts.AccountUtil;
namespace VNLib.Plugins.Essentials.Accounts.Endpoints
@@ -378,11 +378,14 @@ namespace VNLib.Plugins.Essentials.Accounts.Endpoints
private static string EncryptSecret(string pubKey, byte[] secret)
{
//Alloc buffer for secret
- using IMemoryHandle<byte> buffer = Memory.SafeAlloc<byte>(4096);
+ using IMemoryHandle<byte> buffer = MemoryUtil.SafeAlloc<byte>(4096);
+
//Try to encrypt the data
ERRNO count = TryEncryptClientData(pubKey, secret, buffer.Span);
+
//Clear secret
RandomHash.GetRandomBytes(secret);
+
//Convert to base64 string
return Convert.ToBase64String(buffer.Span[..(int)count]);
}
@@ -391,11 +394,13 @@ namespace VNLib.Plugins.Essentials.Accounts.Endpoints
{
//Recover last counter value
TimestampedCounter flc = user.FailedLoginCount();
+
if(flc.Count < MaxFailedLogins)
{
//Period exceeded
return false;
}
+
//See if the flc timeout period has expired
if (flc.LastModified.Add(FailedCountTimeout) < DateTimeOffset.UtcNow)
{
@@ -403,6 +408,7 @@ namespace VNLib.Plugins.Essentials.Accounts.Endpoints
user.FailedLoginCount(0);
return false;
}
+
//Count has been exceeded, and has not timed out yet
return true;
}
diff --git a/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/MFAEndpoint.cs b/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/MFAEndpoint.cs
index 6ebb024..df20084 100644
--- a/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/MFAEndpoint.cs
+++ b/plugins/VNLib.Plugins.Essentials.Accounts/src/Endpoints/MFAEndpoint.cs
@@ -162,11 +162,13 @@ namespace VNLib.Plugins.Essentials.Accounts.Endpoints
//generate a new secret (passing the buffer which will get copied to an array because the pw bytes can be modified during encryption)
byte[] secretBuffer = user.MFAGenreateTOTPSecret(MultiFactor);
//Alloc output buffer
- UnsafeMemoryHandle<byte> outputBuffer = Memory.UnsafeAlloc<byte>(4096, true);
+ UnsafeMemoryHandle<byte> outputBuffer = MemoryUtil.UnsafeAlloc<byte>(4096, true);
+
try
{
//Encrypt the secret for the client
ERRNO count = entity.Session.TryEncryptClientData(secretBuffer, outputBuffer.Span);
+
if (!count)
{
webm.Result = "There was an error updating your credentials";
@@ -174,6 +176,7 @@ namespace VNLib.Plugins.Essentials.Accounts.Endpoints
Log.Warn("TOTP secret encryption failed, for requested user {uid}", entity.Session.UserID);
break;
}
+
webm.Result = new TOTPUpdateMessage()
{
Issuer = MultiFactor.IssuerName,
@@ -183,6 +186,7 @@ namespace VNLib.Plugins.Essentials.Accounts.Endpoints
//Convert the secret to base64 string to send to client
Base64EncSecret = Convert.ToBase64String(outputBuffer.Span[..(int)count])
};
+
//set success flag
webm.Success = true;
}