aboutsummaryrefslogtreecommitdiff
path: root/Plugins/OAuth2ClientApplications/src/Endpoints/ApplicationEndpoint.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Plugins/OAuth2ClientApplications/src/Endpoints/ApplicationEndpoint.cs')
-rw-r--r--Plugins/OAuth2ClientApplications/src/Endpoints/ApplicationEndpoint.cs64
1 files changed, 57 insertions, 7 deletions
diff --git a/Plugins/OAuth2ClientApplications/src/Endpoints/ApplicationEndpoint.cs b/Plugins/OAuth2ClientApplications/src/Endpoints/ApplicationEndpoint.cs
index a548ae0..4b770ca 100644
--- a/Plugins/OAuth2ClientApplications/src/Endpoints/ApplicationEndpoint.cs
+++ b/Plugins/OAuth2ClientApplications/src/Endpoints/ApplicationEndpoint.cs
@@ -43,10 +43,14 @@ using VNLib.Plugins.Extensions.Validation;
using VNLib.Plugins.Extensions.Loading;
using VNLib.Plugins.Extensions.Loading.Sql;
using VNLib.Plugins.Extensions.Data.Extensions;
+using VNLib.Plugins.Essentials.Users;
+using VNLib.Plugins.Extensions.Loading.Users;
using static VNLib.Plugins.Essentials.Statics;
+
namespace OAuth2ClientApplications.Endpoints
{
+
[ConfigurationName("applications")]
internal sealed class ApplicationEndpoint : ProtectedWebEndpoint
{
@@ -54,6 +58,7 @@ namespace OAuth2ClientApplications.Endpoints
private readonly ApplicationStore Applications;
private readonly int MaxAppsPerUser;
private readonly string MaxAppOverloadMessage;
+ private readonly IUserManager Users;
private static readonly UserAppValidator Validator = new();
@@ -68,6 +73,8 @@ namespace OAuth2ClientApplications.Endpoints
//Load apps
Applications = new(plugin.GetContextOptions(), plugin.GetOrCreateSingleton<ManagedPasswordHashing>());
+ Users = plugin.GetOrCreateSingleton<UserManager>();
+
//Complie overload message
MaxAppOverloadMessage = $"You have reached the limit of {MaxAppsPerUser} applications, this application cannot be created";
}
@@ -116,6 +123,7 @@ namespace OAuth2ClientApplications.Endpoints
webm.Result = "OAuth is only available for internal user accounts";
return VirtualClose(entity, webm, HttpStatusCode.Forbidden);
}
+
if (entity.QueryArgs.IsArgumentSet("action", "create"))
{
return await CreateAppAsync(entity);
@@ -134,11 +142,17 @@ namespace OAuth2ClientApplications.Endpoints
//Update message will include a challenge and an app id
string? appId = update.RootElement.GetPropString("Id");
- if (string.IsNullOrWhiteSpace(appId))
+ if (webm.Assert(!string.IsNullOrWhiteSpace(appId), "Application with the specified id does not exist"))
{
- return VfReturnType.NotFound;
+ return VirtualClose(entity, webm, HttpStatusCode.NotFound);
}
-
+
+ //validate the user's password
+ if (await ValidateUserPassword(entity, update, webm) == false)
+ {
+ return VirtualClose(entity, webm, HttpStatusCode.Unauthorized);
+ }
+
//Update the app's secret
using PrivateString? secret = await Applications.UpdateSecretAsync(entity.Session.UserID, appId);
@@ -173,13 +187,19 @@ namespace OAuth2ClientApplications.Endpoints
}
//Update message will include a challenge and an app id
- string? appId = update.RootElement.GetPropString("Id");
-
+ string? appId = update.RootElement.GetPropString("Id");
+
if (string.IsNullOrWhiteSpace(appId))
{
return VfReturnType.NotFound;
- }
-
+ }
+
+ //validate the password
+ if(await ValidateUserPassword(entity, update, webm) == false)
+ {
+ return VirtualClose(entity, webm, HttpStatusCode.Unauthorized);
+ }
+
//Try to delete the app
if (await Applications.DeleteAsync(appId, entity.Session.UserID))
{
@@ -307,6 +327,36 @@ namespace OAuth2ClientApplications.Endpoints
return VfReturnType.VirtualSkip;
}
+ private async Task<bool> ValidateUserPassword(HttpEntity entity, JsonDocument request, WebMessage webm)
+ {
+ //Get password from request and capture it as a private string
+ using PrivateString? rawPassword = PrivateString.ToPrivateString(request.RootElement.GetPropString("password"), true);
+
+ if (webm.Assert(rawPassword != null, "Please enter your account password"))
+ {
+ //Must sent a 401 to indicate that the password is required
+ return false;
+ }
+
+ //Get the current user from the store
+ using IUser? user = await Users.GetUserFromIDAsync(entity.Session.UserID, entity.EventCancellation);
+
+ if (webm.Assert(user != null, "Please check your password"))
+ {
+ return false;
+ }
+
+ //Validate the password against the user
+ bool isPasswordValid = await Users.ValidatePasswordAsync(user, rawPassword, PassValidateFlags.None, entity.EventCancellation) == UserPassValResult.Success;
+
+ if (webm.Assert(isPasswordValid, "Please check your password"))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
private static string ParsePermissions(string permissions)
{
StringBuilder builder = new();