diff --git a/DotBased.AspNet.Authority/Attributes/ProtectAttribute.cs b/DotBased.AspNet.Authority/Attributes/ProtectAttribute.cs
index 58775b1..1d1749e 100644
--- a/DotBased.AspNet.Authority/Attributes/ProtectAttribute.cs
+++ b/DotBased.AspNet.Authority/Attributes/ProtectAttribute.cs
@@ -1,7 +1,7 @@
namespace DotBased.AspNet.Authority.Attributes;
///
-/// Indicates to protect the property before saving to the repository.
+/// Indicates to protect the property before saving/loading to the repository.
///
[AttributeUsage(AttributeTargets.Property)]
public class ProtectAttribute : Attribute
diff --git a/DotBased.AspNet.Authority/AuthorityProviderExtensions.cs b/DotBased.AspNet.Authority/AuthorityProviderExtensions.cs
index 82326b0..b99a7ec 100644
--- a/DotBased.AspNet.Authority/AuthorityProviderExtensions.cs
+++ b/DotBased.AspNet.Authority/AuthorityProviderExtensions.cs
@@ -1,20 +1,41 @@
-using DotBased.AspNet.Authority.Interfaces;
+using DotBased.AspNet.Authority.Crypto;
+using DotBased.AspNet.Authority.Models.Authority;
using DotBased.AspNet.Authority.Models.Options;
+using DotBased.AspNet.Authority.Services;
+using DotBased.AspNet.Authority.Validators;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.DependencyInjection.Extensions;
namespace DotBased.AspNet.Authority;
public static class AuthorityProviderExtensions
{
- public static AuthorityBuilder AddAuthorityProvider(this IServiceCollection services, Action optionsAction) where TModel : class
+ public static AuthorityBuilder AddAuthority(this IServiceCollection services, Action? optionsAction = null)
+ => services.AddAuthority(optionsAction);
+
+ public static AuthorityBuilder AddAuthority(this IServiceCollection services, Action? optionsAction = null)
+ where TUser : class where TGroup : class where TRole : class
{
- services.AddOptions();
- // Configure required classes, services, etc.
- services.Configure(optionsAction);
+ if (optionsAction != null)
+ {
+ services.AddOptions();
+ services.Configure(optionsAction);
+ }
+ services.TryAddScoped();
+ services.TryAddScoped();
+ services.TryAddScoped, PasswordOptionsValidator>();
+ services.TryAddScoped, UserValidator>();
+ /*services.TryAddScoped();
+ services.TryAddScoped();
+ services.TryAddScoped();*/
+ services.TryAddScoped();
+ services.TryAddScoped>();
+ services.TryAddScoped>();
+ services.TryAddScoped>();
return new AuthorityBuilder(services);
}
- public static AuthorityBuilder AddAuthorityStore(this AuthorityBuilder authorityBuilder) where TStore : IAuthorityRepository
+ public static AuthorityBuilder AddAuthorityRepository(this AuthorityBuilder authorityBuilder) where TRepository : class
{
return authorityBuilder;
}
diff --git a/DotBased.AspNet.Authority/Crypto/Cryptographer.cs b/DotBased.AspNet.Authority/Crypto/Cryptographer.cs
new file mode 100644
index 0000000..d6a3416
--- /dev/null
+++ b/DotBased.AspNet.Authority/Crypto/Cryptographer.cs
@@ -0,0 +1,14 @@
+namespace DotBased.AspNet.Authority.Crypto;
+
+public class Cryptographer : ICryptographer
+{
+ public Task EncryptAsync(string data)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Task DecryptAsync(string data)
+ {
+ throw new NotImplementedException();
+ }
+}
\ No newline at end of file
diff --git a/DotBased.AspNet.Authority/Crypto/ICryptographer.cs b/DotBased.AspNet.Authority/Crypto/ICryptographer.cs
new file mode 100644
index 0000000..a043271
--- /dev/null
+++ b/DotBased.AspNet.Authority/Crypto/ICryptographer.cs
@@ -0,0 +1,7 @@
+namespace DotBased.AspNet.Authority.Crypto;
+
+public interface ICryptographer
+{
+ public Task EncryptAsync(string data);
+ public Task DecryptAsync(string data);
+}
\ No newline at end of file
diff --git a/DotBased.AspNet.Authority/Crypto/IPasswordHasher.cs b/DotBased.AspNet.Authority/Crypto/IPasswordHasher.cs
new file mode 100644
index 0000000..23cd3ef
--- /dev/null
+++ b/DotBased.AspNet.Authority/Crypto/IPasswordHasher.cs
@@ -0,0 +1,6 @@
+namespace DotBased.AspNet.Authority.Crypto;
+
+public interface IPasswordHasher
+{
+ public Task HashPasswordAsync(string password);
+}
\ No newline at end of file
diff --git a/DotBased.AspNet.Authority/Crypto/PasswordHasher.cs b/DotBased.AspNet.Authority/Crypto/PasswordHasher.cs
new file mode 100644
index 0000000..38ad043
--- /dev/null
+++ b/DotBased.AspNet.Authority/Crypto/PasswordHasher.cs
@@ -0,0 +1,9 @@
+namespace DotBased.AspNet.Authority.Crypto;
+
+public class PasswordHasher : IPasswordHasher
+{
+ public async Task HashPasswordAsync(string password)
+ {
+ throw new NotImplementedException();
+ }
+}
\ No newline at end of file
diff --git a/DotBased.AspNet.Authority/DotBased.AspNet.Authority.csproj b/DotBased.AspNet.Authority/DotBased.AspNet.Authority.csproj
index f056f35..53d8b22 100644
--- a/DotBased.AspNet.Authority/DotBased.AspNet.Authority.csproj
+++ b/DotBased.AspNet.Authority/DotBased.AspNet.Authority.csproj
@@ -17,7 +17,6 @@
-
diff --git a/DotBased.AspNet.Authority/Interfaces/IAttributeRepository.cs b/DotBased.AspNet.Authority/Interfaces/IAttributeRepository.cs
deleted file mode 100644
index d0f90d1..0000000
--- a/DotBased.AspNet.Authority/Interfaces/IAttributeRepository.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace DotBased.AspNet.Authority.Interfaces;
-
-public interface IAttributeRepository
-{
-
-}
\ No newline at end of file
diff --git a/DotBased.AspNet.Authority/Interfaces/IAuthorityRepository.cs b/DotBased.AspNet.Authority/Interfaces/IAuthorityRepository.cs
deleted file mode 100644
index 3f09635..0000000
--- a/DotBased.AspNet.Authority/Interfaces/IAuthorityRepository.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace DotBased.AspNet.Authority.Interfaces;
-
-public interface IAuthorityRepository
-{
-
-}
\ No newline at end of file
diff --git a/DotBased.AspNet.Authority/Interfaces/IRoleRepository.cs b/DotBased.AspNet.Authority/Interfaces/IRoleRepository.cs
deleted file mode 100644
index 9ad9dc8..0000000
--- a/DotBased.AspNet.Authority/Interfaces/IRoleRepository.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace DotBased.AspNet.Authority.Interfaces;
-
-public interface IRoleRepository
-{
-
-}
\ No newline at end of file
diff --git a/DotBased.AspNet.Authority/Models/Options/AuthorityOptions.cs b/DotBased.AspNet.Authority/Models/Options/AuthorityOptions.cs
index 77f631c..6ab3e04 100644
--- a/DotBased.AspNet.Authority/Models/Options/AuthorityOptions.cs
+++ b/DotBased.AspNet.Authority/Models/Options/AuthorityOptions.cs
@@ -6,5 +6,6 @@ public class AuthorityOptions
public LockoutOptions Lockout { get; set; } = new();
public PasswordOptions Password { get; set; } = new();
public ProviderOptions Provider { get; set; } = new();
+ public RepositoryOptions Repository { get; set; } = new();
public UserOptions User { get; set; } = new();
}
\ No newline at end of file
diff --git a/DotBased.AspNet.Authority/Models/Options/RepositoryOptions.cs b/DotBased.AspNet.Authority/Models/Options/RepositoryOptions.cs
new file mode 100644
index 0000000..454af3e
--- /dev/null
+++ b/DotBased.AspNet.Authority/Models/Options/RepositoryOptions.cs
@@ -0,0 +1,10 @@
+namespace DotBased.AspNet.Authority.Models.Options;
+
+public class RepositoryOptions
+{
+ ///
+ /// Use data encryption when a property has the defined.
+ /// Default: true
+ ///
+ public bool UseDataProtection { get; set; } = true;
+}
\ No newline at end of file
diff --git a/DotBased.AspNet.Authority/Models/Validation/ValidationError.cs b/DotBased.AspNet.Authority/Models/Validation/ValidationError.cs
new file mode 100644
index 0000000..d65c178
--- /dev/null
+++ b/DotBased.AspNet.Authority/Models/Validation/ValidationError.cs
@@ -0,0 +1,24 @@
+namespace DotBased.AspNet.Authority.Models.Validation;
+
+public class ValidationError
+{
+ public ValidationError(string validator, string errorCode, string description)
+ {
+ Validator = validator;
+ ErrorCode = errorCode;
+ Description = description;
+ }
+
+ ///
+ /// The validator name that generated this error.
+ ///
+ public string Validator { get; }
+ ///
+ /// The error code
+ ///
+ public string ErrorCode { get; }
+ ///
+ /// Error description
+ ///
+ public string Description { get; }
+}
\ No newline at end of file
diff --git a/DotBased.AspNet.Authority/Models/Validation/ValidationResult.cs b/DotBased.AspNet.Authority/Models/Validation/ValidationResult.cs
new file mode 100644
index 0000000..aea2d80
--- /dev/null
+++ b/DotBased.AspNet.Authority/Models/Validation/ValidationResult.cs
@@ -0,0 +1,21 @@
+namespace DotBased.AspNet.Authority.Models.Validation;
+
+public class ValidationResult
+{
+ public ValidationResult(bool success, IEnumerable? errors = null)
+ {
+ if (errors != null)
+ {
+ Errors = errors.ToList();
+ }
+ Success = success;
+ }
+
+ public bool Success { get; }
+ public IReadOnlyList Errors { get; } = [];
+
+ public static ValidationResult Failed(IEnumerable errors) => new(false, errors);
+ public static ValidationResult Ok() => new(true);
+
+ public override string ToString() => Success ? "Success" : $"Failed ({Errors.Count} errors)";
+}
\ No newline at end of file
diff --git a/DotBased.AspNet.Authority/Repositories/AuthorityRepository.cs b/DotBased.AspNet.Authority/Repositories/AuthorityRepository.cs
deleted file mode 100644
index 239c114..0000000
--- a/DotBased.AspNet.Authority/Repositories/AuthorityRepository.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace DotBased.AspNet.Authority.Repositories;
-
-public class AuthorityRepository // Inherit the repository interfaces?
-{
-
-}
\ No newline at end of file
diff --git a/DotBased.AspNet.Authority/Repositories/IAttributeRepository.cs b/DotBased.AspNet.Authority/Repositories/IAttributeRepository.cs
new file mode 100644
index 0000000..92272f3
--- /dev/null
+++ b/DotBased.AspNet.Authority/Repositories/IAttributeRepository.cs
@@ -0,0 +1,6 @@
+namespace DotBased.AspNet.Authority.Repositories;
+
+public interface IAttributeRepository where TAttribute : class where TId : IEquatable
+{
+
+}
\ No newline at end of file
diff --git a/DotBased.AspNet.Authority/Repositories/IAuthorityRepository.cs b/DotBased.AspNet.Authority/Repositories/IAuthorityRepository.cs
new file mode 100644
index 0000000..8c0af84
--- /dev/null
+++ b/DotBased.AspNet.Authority/Repositories/IAuthorityRepository.cs
@@ -0,0 +1,7 @@
+namespace DotBased.AspNet.Authority.Repositories;
+
+public interface IAuthorityRepository
+{
+ public Task GetVersion();
+ public Task SetVersion(int version);
+}
\ No newline at end of file
diff --git a/DotBased.AspNet.Authority/Repositories/IGroupRepository.cs b/DotBased.AspNet.Authority/Repositories/IGroupRepository.cs
new file mode 100644
index 0000000..667f839
--- /dev/null
+++ b/DotBased.AspNet.Authority/Repositories/IGroupRepository.cs
@@ -0,0 +1,6 @@
+namespace DotBased.AspNet.Authority.Repositories;
+
+public interface IGroupRepository where TGroup : class where TId : IEquatable
+{
+
+}
\ No newline at end of file
diff --git a/DotBased.AspNet.Authority/Repositories/IRoleRepository.cs b/DotBased.AspNet.Authority/Repositories/IRoleRepository.cs
new file mode 100644
index 0000000..e3c9b4c
--- /dev/null
+++ b/DotBased.AspNet.Authority/Repositories/IRoleRepository.cs
@@ -0,0 +1,6 @@
+namespace DotBased.AspNet.Authority.Repositories;
+
+public interface IRoleRepository where TRole : class where TId : IEquatable
+{
+
+}
\ No newline at end of file
diff --git a/DotBased.AspNet.Authority/Interfaces/IUserRepository.cs b/DotBased.AspNet.Authority/Repositories/IUserRepository.cs
similarity index 85%
rename from DotBased.AspNet.Authority/Interfaces/IUserRepository.cs
rename to DotBased.AspNet.Authority/Repositories/IUserRepository.cs
index c2c420c..23c4c6e 100644
--- a/DotBased.AspNet.Authority/Interfaces/IUserRepository.cs
+++ b/DotBased.AspNet.Authority/Repositories/IUserRepository.cs
@@ -1,4 +1,4 @@
-namespace DotBased.AspNet.Authority.Interfaces;
+namespace DotBased.AspNet.Authority.Repositories;
public interface IUserRepository where TUser : class where TId : IEquatable
{
diff --git a/DotBased.AspNet.Authority/Services/AuthorityGroupManager.cs b/DotBased.AspNet.Authority/Services/AuthorityGroupManager.cs
new file mode 100644
index 0000000..b8db5ea
--- /dev/null
+++ b/DotBased.AspNet.Authority/Services/AuthorityGroupManager.cs
@@ -0,0 +1,6 @@
+namespace DotBased.AspNet.Authority.Services;
+
+public class AuthorityGroupManager
+{
+
+}
\ No newline at end of file
diff --git a/DotBased.AspNet.Authority/Services/AuthorityManager.cs b/DotBased.AspNet.Authority/Services/AuthorityManager.cs
index 3cb5eb7..2cf9d19 100644
--- a/DotBased.AspNet.Authority/Services/AuthorityManager.cs
+++ b/DotBased.AspNet.Authority/Services/AuthorityManager.cs
@@ -1,6 +1,100 @@
+using System.Reflection;
+using DotBased.AspNet.Authority.Attributes;
+using DotBased.AspNet.Authority.Crypto;
+using DotBased.AspNet.Authority.Models.Options;
+using DotBased.AspNet.Authority.Repositories;
+using DotBased.Logging;
+using Microsoft.Extensions.Options;
+
namespace DotBased.AspNet.Authority.Services;
-public class AuthorityManager
+public class AuthorityManager
{
+ public AuthorityManager(
+ IOptions options,
+ IServiceProvider services,
+ IAuthorityRepository repository,
+ ICryptographer cryptographer)
+ {
+ _logger = LogService.RegisterLogger();
+ Options = options.Value ?? new AuthorityOptions();
+ Services = services;
+ Repository = repository;
+ Cryptographer = cryptographer;
+ }
+
+ private readonly ILogger _logger;
+
+ public IServiceProvider Services { get; }
+ public AuthorityOptions Options { get; }
+ public IAuthorityRepository Repository { get; }
+ public ICryptographer Cryptographer { get; }
+
+
public long GenerateVersion() => DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+
+ ///
+ /// Protect or unprotect the properties with the
+ ///
+ /// The data model
+ /// True for protection false for unprotection.
+ /// The class with the properties to protect.
+ public async Task HandlePropertyProtection(TModel data, bool protection)
+ {
+ var props = GetProtectedPropertiesValues(data);
+ if (Cryptographer == null)
+ {
+ _logger.Warning("No cryptographer specified! Cannot encrypt/decrypt properties.");
+ return;
+ }
+ if (props.Count == 0)
+ {
+ return;
+ }
+
+ var handledProperties = 0;
+ foreach (var property in props)
+ {
+ if (property.PropertyType != typeof(string))
+ {
+ _logger.Warning("Property({PropName}) with type: {PropType} detected, encrypting only supports strings! Skipping property!", property.Name, property.PropertyType);
+ continue;
+ }
+
+ string? cryptString;
+ if (protection)
+ {
+ cryptString = await Cryptographer.EncryptAsync(property.GetValue(data)?.ToString() ?? string.Empty);
+ }
+ else
+ {
+ cryptString = await Cryptographer.DecryptAsync(property.GetValue(data)?.ToString() ?? string.Empty);
+ }
+
+ if (cryptString == null)
+ {
+ _logger.Warning("{Protection} failed for property {PropName}", protection ? "Encyption" : "Decyption", property.Name);
+ continue;
+ }
+ property.SetValue(data, cryptString);
+ handledProperties++;
+ }
+ _logger.Debug("{HandledPropCount}/{TotalPropCount} protection properties handled!", handledProperties, props.Count);
+ }
+
+ public bool IsPropertieProtected(string propertieName)
+ {
+ var protectedProperties = GetProtectedProperties();
+ var propertieFound = protectedProperties.Where(propInfo => propInfo.Name == propertieName);
+ return propertieFound.Any();
+ }
+
+ public List GetProtectedPropertiesValues(TModel model)
+ {
+ var protectedProperties = GetProtectedProperties();
+ return protectedProperties.Count != 0 ? protectedProperties : [];
+ }
+
+ public List GetProtectedProperties()
+ => typeof(TModel).GetProperties().Where(p => Attribute.IsDefined(p, typeof(ProtectAttribute))).ToList();
}
\ No newline at end of file
diff --git a/DotBased.AspNet.Authority/Services/AuthorityRoleManager.cs b/DotBased.AspNet.Authority/Services/AuthorityRoleManager.cs
new file mode 100644
index 0000000..d3b8e7d
--- /dev/null
+++ b/DotBased.AspNet.Authority/Services/AuthorityRoleManager.cs
@@ -0,0 +1,6 @@
+namespace DotBased.AspNet.Authority.Services;
+
+public class AuthorityRoleManager
+{
+
+}
\ No newline at end of file
diff --git a/DotBased.AspNet.Authority/Services/AuthorityUserManager.cs b/DotBased.AspNet.Authority/Services/AuthorityUserManager.cs
new file mode 100644
index 0000000..a02c8f3
--- /dev/null
+++ b/DotBased.AspNet.Authority/Services/AuthorityUserManager.cs
@@ -0,0 +1,28 @@
+using DotBased.AspNet.Authority.Validators;
+using DotBased.Logging;
+
+namespace DotBased.AspNet.Authority.Services;
+
+public class AuthorityUserManager
+{
+ public AuthorityUserManager(
+ AuthorityManager manager,
+ IEnumerable>? passwordValidators,
+ IEnumerable>? userValidators)
+ {
+ _logger = LogService.RegisterLogger>();
+ AuthorityManager = manager;
+ if (passwordValidators != null)
+ PasswordValidators = passwordValidators;
+ if (userValidators != null)
+ UserValidators = userValidators;
+ }
+
+ private readonly ILogger _logger;
+ public AuthorityManager AuthorityManager { get; }
+
+ public IEnumerable> PasswordValidators { get; } = [];
+ public IEnumerable> UserValidators { get; } = [];
+
+
+}
\ No newline at end of file
diff --git a/DotBased.AspNet.Authority/Validators/IPasswordValidator.cs b/DotBased.AspNet.Authority/Validators/IPasswordValidator.cs
index 2fe5b5c..07590ae 100644
--- a/DotBased.AspNet.Authority/Validators/IPasswordValidator.cs
+++ b/DotBased.AspNet.Authority/Validators/IPasswordValidator.cs
@@ -1,6 +1,9 @@
+using DotBased.AspNet.Authority.Models.Validation;
+using DotBased.AspNet.Authority.Services;
+
namespace DotBased.AspNet.Authority.Validators;
public interface IPasswordValidator
{
-
+ public Task ValidatePasswordAsync(AuthorityUserManager userManager, string password);
}
\ No newline at end of file
diff --git a/DotBased.AspNet.Authority/Validators/IUserValidator.cs b/DotBased.AspNet.Authority/Validators/IUserValidator.cs
index cb7e245..96511d6 100644
--- a/DotBased.AspNet.Authority/Validators/IUserValidator.cs
+++ b/DotBased.AspNet.Authority/Validators/IUserValidator.cs
@@ -1,6 +1,6 @@
namespace DotBased.AspNet.Authority.Validators;
-public interface IUserValidator
+public interface IUserValidator
{
}
\ No newline at end of file
diff --git a/DotBased.AspNet.Authority/Validators/PasswordOptionsValidator.cs b/DotBased.AspNet.Authority/Validators/PasswordOptionsValidator.cs
new file mode 100644
index 0000000..1360d3e
--- /dev/null
+++ b/DotBased.AspNet.Authority/Validators/PasswordOptionsValidator.cs
@@ -0,0 +1,66 @@
+using DotBased.AspNet.Authority.Models.Validation;
+using DotBased.AspNet.Authority.Services;
+using DotBased.Extensions;
+
+namespace DotBased.AspNet.Authority.Validators;
+
+///
+/// Validates the password against the options that is configured.
+///
+/// The user model used.
+public class PasswordOptionsValidator : IPasswordValidator
+{
+ private const string ValidatorId = "Authority.Validator.Password.Options";
+ private const string ValidationBase = "Authority.Validation.Password";
+
+ public async Task ValidatePasswordAsync(AuthorityUserManager userManager, string password)
+ {
+ if (userManager == null)
+ {
+ throw new ArgumentNullException(nameof(userManager), "User manager is not provided!");
+ }
+ var passwordOptions = userManager.AuthorityManager.Options.Password;
+ var errors = new List();
+
+ if (password.IsNullOrEmpty() || password.Length < passwordOptions.RequiredLength)
+ {
+ errors.Add(new ValidationError(ValidatorId, $"{ValidationBase}.Required.Length", $"Password needs to have a minimum length of {passwordOptions.RequiredLength}"));
+ }
+
+ if (passwordOptions.RequireDigit && !ContainsDigit(password))
+ {
+ errors.Add(new ValidationError(ValidatorId, $"{ValidationBase}.Required.Digit", "Password must contain a digit!"));
+ }
+
+ if (passwordOptions.RequireNonAlphanumeric && ContainsNonAlphanumeric(password))
+ {
+ errors.Add(new ValidationError(ValidatorId, $"{ValidationBase}.Required.NonAlphanumeric", "Password must contain a non alphanumeric character."));
+ }
+
+ if (passwordOptions.RequireLowercase && password.Any(char.IsLower))
+ {
+ errors.Add(new ValidationError(ValidatorId, $"{ValidationBase}.Required.Lowercase", "Password must contains at least one lowercase character."));
+ }
+
+ if (passwordOptions.RequireUppercase && password.Any(char.IsUpper))
+ {
+ errors.Add(new ValidationError(ValidatorId, $"{ValidationBase}.Required.Uppercase", "Password must contains at least one uppercase character."));
+ }
+
+ if (passwordOptions.PasswordBlackList.Count != 0 && passwordOptions.PasswordBlackList.Contains(password, passwordOptions.PasswordBlackListComparer))
+ {
+ errors.Add(new ValidationError(ValidatorId, $"{ValidationBase}.Blacklisted", "Given password is not allowed (blacklisted)"));
+ }
+
+ if (passwordOptions.MinimalUniqueChars > 0 && password.Distinct().Count() < passwordOptions.MinimalUniqueChars)
+ {
+ errors.Add(new ValidationError(ValidatorId, $"{ValidationBase}.UniqueChars", $"Password must contain at least {passwordOptions.MinimalUniqueChars} unique chars."));
+ }
+
+ return await Task.FromResult(errors.Count > 0 ? ValidationResult.Failed(errors) : ValidationResult.Ok());
+ }
+
+ private bool ContainsDigit(string strVal) => strVal.Any(char.IsDigit);
+
+ private bool ContainsNonAlphanumeric(string strVal) => !strVal.Any(char.IsLetterOrDigit);
+}
\ No newline at end of file
diff --git a/DotBased.AspNet.Authority/Validators/PasswordValidator.cs b/DotBased.AspNet.Authority/Validators/PasswordValidator.cs
deleted file mode 100644
index 33ce063..0000000
--- a/DotBased.AspNet.Authority/Validators/PasswordValidator.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace DotBased.AspNet.Authority.Validators;
-
-public class PasswordValidator
-{
-
-}
\ No newline at end of file
diff --git a/DotBased.AspNet.Authority/Validators/UserValidator.cs b/DotBased.AspNet.Authority/Validators/UserValidator.cs
index 1175fc8..219bccb 100644
--- a/DotBased.AspNet.Authority/Validators/UserValidator.cs
+++ b/DotBased.AspNet.Authority/Validators/UserValidator.cs
@@ -1,6 +1,6 @@
namespace DotBased.AspNet.Authority.Validators;
-public class UserValidator
+public class UserValidator : IUserValidator
{
}
\ No newline at end of file
diff --git a/DotBased.AspNet.Authority/Verifiers/IUserVerifier.cs b/DotBased.AspNet.Authority/Verifiers/IUserVerifier.cs
index c41347f..d6e5120 100644
--- a/DotBased.AspNet.Authority/Verifiers/IUserVerifier.cs
+++ b/DotBased.AspNet.Authority/Verifiers/IUserVerifier.cs
@@ -1,6 +1,6 @@
namespace DotBased.AspNet.Authority.Verifiers;
-public class IUserVerifier
+public interface IUserVerifier
{
}
\ No newline at end of file
diff --git a/TestWebApi/Program.cs b/TestWebApi/Program.cs
index f18c0ae..323ca0c 100644
--- a/TestWebApi/Program.cs
+++ b/TestWebApi/Program.cs
@@ -1,3 +1,4 @@
+using DotBased.AspNet.Authority;
using DotBased.Logging;
using DotBased.Logging.MEL;
using DotBased.Logging.Serilog;
@@ -19,6 +20,11 @@ LogService.AddLogAdapter(new BasedSerilogAdapter(serilogLogger));
builder.Logging.ClearProviders();
builder.Logging.AddDotBasedLoggerProvider(LogService.Options);
+builder.Services.AddAuthority(options =>
+{
+
+});
+
/*builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = BasedAuthenticationDefaults.BasedAuthenticationScheme;