From c1e343346d5f8d4dd801dbe7712e0e986a3da0a0 Mon Sep 17 00:00:00 2001 From: Maksym Sadovnychyy Date: Thu, 27 Oct 2022 00:06:41 +0200 Subject: [PATCH] (feat): white list tokens policy completed --- db/DML/{user.json => users.json} | 2 +- webapi/Core/DomainObjects/Contact.cs | 2 +- webapi/Core/DomainObjects/Documents/User.cs | 2 +- webapi/CryptoProvider/AesKey.cs | 17 ++++ webapi/CryptoProvider/AesService.cs | 77 ++++++++++++++++++ .../CryptoProvider.csproj} | 5 +- .../HashService.cs | 16 ++-- .../Collections/UserDataProvider.cs | 14 +++- .../Converters/EnumerationListSerializer.cs | 55 +++++++++++++ .../Converters/EnumerationSerializer.cs | 61 ++------------ webapi/DataProviders/DataProviders.csproj | 6 +- .../Extensions/ServiceCollectionExtensions.cs | 2 + webapi/DataProviders/Mappings.cs | 2 +- .../IImageProcessingContextExtensions.cs | 0 .../Extensions/ServiceCollectionExtensions.cs | 0 .../ImageProvider/Fonts/FontStylesEnum.cs | 0 .../ImageProvider/Fonts/FontsEnum.cs | 0 .../Fonts/Montserrat/Montserrat-Black.ttf | Bin .../Montserrat/Montserrat-BlackItalic.ttf | Bin .../Fonts/Montserrat/Montserrat-Bold.ttf | Bin .../Montserrat/Montserrat-BoldItalic.ttf | Bin .../Fonts/Montserrat/Montserrat-ExtraBold.ttf | Bin .../Montserrat/Montserrat-ExtraBoldItalic.ttf | Bin .../Montserrat/Montserrat-ExtraLight.ttf | Bin .../Montserrat-ExtraLightItalic.ttf | Bin .../Fonts/Montserrat/Montserrat-Italic.ttf | Bin .../Fonts/Montserrat/Montserrat-Light.ttf | Bin .../Montserrat/Montserrat-LightItalic.ttf | Bin .../Fonts/Montserrat/Montserrat-Medium.ttf | Bin .../Montserrat/Montserrat-MediumItalic.ttf | Bin .../Fonts/Montserrat/Montserrat-Regular.ttf | Bin .../Fonts/Montserrat/Montserrat-SemiBold.ttf | Bin .../Montserrat/Montserrat-SemiBoldItalic.ttf | Bin .../Fonts/Montserrat/Montserrat-Thin.ttf | Bin .../Montserrat/Montserrat-ThinItalic.ttf | Bin .../ImageProvider/ImageBuilder.cs | 0 .../ImageProvider/ImageProvider.cs | 5 -- .../ImageProvider/ImageProvider.csproj | 5 +- webapi/ReverseProxy/ReverseProxy.csproj | 4 +- .../FileSecurityService.csproj | 2 +- .../Extensions/ServiceCollectionExtensions.cs | 11 --- webapi/Services/JWTService/JWTService.csproj | 4 +- webapi/Tests/Core/CoreTests.csproj | 8 +- .../Tests/Extensions/ExtensionsTests.csproj | 6 +- webapi/WeatherForecast.sln | 16 ++-- webapi/WeatherForecast/Configuration.cs | 8 +- .../Controllers/AuthenticationController.cs | 23 ++++-- .../Controllers/BlogItemController.cs | 2 +- .../Controllers/BlogItemsController.cs | 2 +- .../Controllers/CategoryItemController.cs | 2 +- .../Controllers/CategoryItemsController.cs | 2 +- .../Controllers/FileController.cs | 2 +- .../Controllers/FilesController.cs | 2 +- .../Controllers/PasswordController.cs | 2 +- .../Controllers/ShopCartItemController.cs | 2 +- .../Controllers/ShopCartItemsController.cs | 2 +- .../Controllers/ShopItemController.cs | 2 +- .../Controllers/ShopItemsController.cs | 2 +- .../Controllers/UserController.cs | 2 +- .../Policies/WhitelistToken.cs | 55 +++++++++++++ .../Services/AutheticationService.cs | 77 ++++++++++++------ .../Services/PasswordService.cs | 8 +- webapi/WeatherForecast/Startup.cs | 14 +++- webapi/WeatherForecast/WeatherForecast.csproj | 16 ++-- webapi/WeatherForecast/appsettings.json | 5 ++ 65 files changed, 376 insertions(+), 176 deletions(-) rename db/DML/{user.json => users.json} (97%) create mode 100644 webapi/CryptoProvider/AesKey.cs create mode 100644 webapi/CryptoProvider/AesService.cs rename webapi/{Services/HashService/HashService.csproj => CryptoProvider/CryptoProvider.csproj} (53%) rename webapi/{Services/HashService => CryptoProvider}/HashService.cs (63%) create mode 100644 webapi/DataProviders/Converters/EnumerationListSerializer.cs rename webapi/{Services => }/ImageProvider/Extensions/IImageProcessingContextExtensions.cs (100%) rename webapi/{Services => }/ImageProvider/Extensions/ServiceCollectionExtensions.cs (100%) rename webapi/{Services => }/ImageProvider/Fonts/FontStylesEnum.cs (100%) rename webapi/{Services => }/ImageProvider/Fonts/FontsEnum.cs (100%) rename webapi/{Services => }/ImageProvider/Fonts/Montserrat/Montserrat-Black.ttf (100%) rename webapi/{Services => }/ImageProvider/Fonts/Montserrat/Montserrat-BlackItalic.ttf (100%) rename webapi/{Services => }/ImageProvider/Fonts/Montserrat/Montserrat-Bold.ttf (100%) rename webapi/{Services => }/ImageProvider/Fonts/Montserrat/Montserrat-BoldItalic.ttf (100%) rename webapi/{Services => }/ImageProvider/Fonts/Montserrat/Montserrat-ExtraBold.ttf (100%) rename webapi/{Services => }/ImageProvider/Fonts/Montserrat/Montserrat-ExtraBoldItalic.ttf (100%) rename webapi/{Services => }/ImageProvider/Fonts/Montserrat/Montserrat-ExtraLight.ttf (100%) rename webapi/{Services => }/ImageProvider/Fonts/Montserrat/Montserrat-ExtraLightItalic.ttf (100%) rename webapi/{Services => }/ImageProvider/Fonts/Montserrat/Montserrat-Italic.ttf (100%) rename webapi/{Services => }/ImageProvider/Fonts/Montserrat/Montserrat-Light.ttf (100%) rename webapi/{Services => }/ImageProvider/Fonts/Montserrat/Montserrat-LightItalic.ttf (100%) rename webapi/{Services => }/ImageProvider/Fonts/Montserrat/Montserrat-Medium.ttf (100%) rename webapi/{Services => }/ImageProvider/Fonts/Montserrat/Montserrat-MediumItalic.ttf (100%) rename webapi/{Services => }/ImageProvider/Fonts/Montserrat/Montserrat-Regular.ttf (100%) rename webapi/{Services => }/ImageProvider/Fonts/Montserrat/Montserrat-SemiBold.ttf (100%) rename webapi/{Services => }/ImageProvider/Fonts/Montserrat/Montserrat-SemiBoldItalic.ttf (100%) rename webapi/{Services => }/ImageProvider/Fonts/Montserrat/Montserrat-Thin.ttf (100%) rename webapi/{Services => }/ImageProvider/Fonts/Montserrat/Montserrat-ThinItalic.ttf (100%) rename webapi/{Services => }/ImageProvider/ImageBuilder.cs (100%) rename webapi/{Services => }/ImageProvider/ImageProvider.cs (94%) rename webapi/{Services => }/ImageProvider/ImageProvider.csproj (94%) delete mode 100644 webapi/Services/HashService/Extensions/ServiceCollectionExtensions.cs create mode 100644 webapi/WeatherForecast/Policies/WhitelistToken.cs diff --git a/db/DML/user.json b/db/DML/users.json similarity index 97% rename from db/DML/user.json rename to db/DML/users.json index db731e8..9defac9 100644 --- a/db/DML/user.json +++ b/db/DML/users.json @@ -7,7 +7,7 @@ "created": { "$date": "2022-01-01T00:00:00.000Z" }, - "nickaName": "admin", + "username": "admin", "passwords": { "password": { "hash": "pznndK3nv9bftf/qQxqBy4VjH7Ow9vx2Kd6376oJuqQ=", diff --git a/webapi/Core/DomainObjects/Contact.cs b/webapi/Core/DomainObjects/Contact.cs index e9f7827..311ee81 100644 --- a/webapi/Core/DomainObjects/Contact.cs +++ b/webapi/Core/DomainObjects/Contact.cs @@ -3,7 +3,7 @@ using Core.Enumerations; namespace Core.DomainObjects { public class Contact : DomainObjectBase { - public ContactTypes ContactType { get; set; } + public ContactTypes Type { get; set; } public string Value { get; set; } public bool Confirmed { get; set; } diff --git a/webapi/Core/DomainObjects/Documents/User.cs b/webapi/Core/DomainObjects/Documents/User.cs index 171e3f9..c3732bc 100644 --- a/webapi/Core/DomainObjects/Documents/User.cs +++ b/webapi/Core/DomainObjects/Documents/User.cs @@ -8,7 +8,7 @@ namespace Core.DomainObjects { public DateTime Created { get; set; } - public string NickName { get; set; } + public string Username { get; set; } public Passwords Passwords { get; set; } diff --git a/webapi/CryptoProvider/AesKey.cs b/webapi/CryptoProvider/AesKey.cs new file mode 100644 index 0000000..2ed988f --- /dev/null +++ b/webapi/CryptoProvider/AesKey.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CryptoProvider { + public interface IAesKey { + public string? IV { get; set; } + public string? Key { get; set; } + } + + public class AesKey : IAesKey { + public string? IV { get; set; } + public string? Key { get; set; } + } +} \ No newline at end of file diff --git a/webapi/CryptoProvider/AesService.cs b/webapi/CryptoProvider/AesService.cs new file mode 100644 index 0000000..b2d2d13 --- /dev/null +++ b/webapi/CryptoProvider/AesService.cs @@ -0,0 +1,77 @@ +using System.Text; +using System.Security.Cryptography; + + +namespace CryptoProvider { + + public static class AesService { + + public static IAesKey GenerateKey() { + using var aes = Aes.Create(); + + aes.GenerateIV(); + aes.GenerateKey(); + + return new AesKey { + IV = Convert.ToBase64String(aes.IV), + Key = Convert.ToBase64String(aes.Key) + }; + } + + public static string EncryptString(string key, string plainText) => + EncryptStringCore(new byte[16], Convert.FromBase64String(key), plainText); + + public static string EncryptString(string iv, string key, string plainText) => + EncryptStringCore(Convert.FromBase64String(iv), Convert.FromBase64String(key), plainText); + + public static string DecryptString(string key, string cipherText) => + DecryptStringCore(new byte[16], Convert.FromBase64String(key), cipherText); + + public static string DecryptString(string iv, string key, string cipherText) => + DecryptStringCore(Convert.FromBase64String(iv), Convert.FromBase64String(key), cipherText); + + #region Core methods + private static string EncryptStringCore(byte[] iv, byte[] key, string plainText) { + byte[] array; + + using var aes = Aes.Create(); + + aes.Key = key; + aes.IV = iv; + + var encryptor = aes.CreateEncryptor(aes.Key, aes.IV); + + using var memoryStream = new MemoryStream(); + using var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write); + using var streamWriter = new StreamWriter(cryptoStream); + + streamWriter.Write(plainText); + streamWriter.Flush(); + cryptoStream.FlushFinalBlock(); + + array = memoryStream.ToArray(); + + return Convert.ToBase64String(array); + } + + private static string DecryptStringCore(byte [] iv, byte [] key, string cipherText) { + byte[] buffer = Convert.FromBase64String(cipherText); + + using var aes = Aes.Create(); + + + aes.Key = key; + aes.IV = iv; + + var decryptor = aes.CreateDecryptor(aes.Key, aes.IV); + + using var memoryStream = new MemoryStream(buffer); + using var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read); + using var streamReader = new StreamReader(cryptoStream); + + return streamReader.ReadToEnd(); + + } + #endregion + } +} diff --git a/webapi/Services/HashService/HashService.csproj b/webapi/CryptoProvider/CryptoProvider.csproj similarity index 53% rename from webapi/Services/HashService/HashService.csproj rename to webapi/CryptoProvider/CryptoProvider.csproj index f69d928..e6e43bc 100644 --- a/webapi/Services/HashService/HashService.csproj +++ b/webapi/CryptoProvider/CryptoProvider.csproj @@ -7,10 +7,7 @@ - - - - + diff --git a/webapi/Services/HashService/HashService.cs b/webapi/CryptoProvider/HashService.cs similarity index 63% rename from webapi/Services/HashService/HashService.cs rename to webapi/CryptoProvider/HashService.cs index 87afdee..88f74ac 100644 --- a/webapi/Services/HashService/HashService.cs +++ b/webapi/CryptoProvider/HashService.cs @@ -2,14 +2,10 @@ using System.Security.Cryptography; using Microsoft.AspNetCore.Cryptography.KeyDerivation; -namespace HashService { +namespace CryptoProvider { - public interface IHashService { - (string, string) CreateSaltedHash(string value); - bool ValidateHash(string value, string salt, string hash); - } - public class HashService : IHashService { - private string CreateSalt() { + public static class HashService { + private static string CreateSalt() { byte[] randomBytes = new byte[128 / 8]; using (var generator = RandomNumberGenerator.Create()) { generator.GetBytes(randomBytes); @@ -17,7 +13,7 @@ namespace HashService { } } - private string CreateHash(string value, string salt) { + private static string CreateHash(string value, string salt) { var valueBytes = KeyDerivation.Pbkdf2( password: value, salt: Encoding.UTF8.GetBytes(salt), @@ -28,14 +24,14 @@ namespace HashService { return Convert.ToBase64String(valueBytes); } - public (string, string) CreateSaltedHash(string value) { + public static (string, string) CreateSaltedHash(string value) { var salt = CreateSalt(); var hash = CreateHash(value, salt); return (salt, hash); } - public bool ValidateHash(string value, string salt, string hash) => + public static bool ValidateHash(string value, string salt, string hash) => CreateHash(value, salt) == hash; } } diff --git a/webapi/DataProviders/Collections/UserDataProvider.cs b/webapi/DataProviders/Collections/UserDataProvider.cs index 8287bb0..8e8a630 100644 --- a/webapi/DataProviders/Collections/UserDataProvider.cs +++ b/webapi/DataProviders/Collections/UserDataProvider.cs @@ -15,7 +15,9 @@ namespace DataProviders.Collections { public interface IUserDataProvider { (User?, IDomainResult) Get(Guid userId); - (User?, IDomainResult) GetByNickName(string nickName); + (User?, IDomainResult) GetByUsername(string nickName); + + (Guid?, IDomainResult) Update(User user); } public class UserDataProvider : CollectionDataProviderBase, IUserDataProvider { @@ -29,7 +31,7 @@ namespace DataProviders.Collections { ISessionService sessionService) : base(logger, client, idGenerator, sessionService) { } - public (User?, IDomainResult) Get( Guid userId) { + public (User?, IDomainResult) Get(Guid userId) { var (list, result) = GetWithPredicate(x => x.Id == userId, _collectionName); if (!result.IsSuccess || list == null) @@ -38,13 +40,17 @@ namespace DataProviders.Collections { return (list.First(), result); } - public (User?, IDomainResult) GetByNickName(string nickName) { - var (list, result) = GetWithPredicate(x => x.NickName == nickName, _collectionName); + public (User?, IDomainResult) GetByUsername(string username) { + var (list, result) = GetWithPredicate(x => x.Username == username, _collectionName); if (!result.IsSuccess || list == null) return (null, result); return (list.First(), result); } + + public (Guid?, IDomainResult) Update(User user) => + UpdateWithPredicate(user, x => x.Id == user.Id, _collectionName); + } } diff --git a/webapi/DataProviders/Converters/EnumerationListSerializer.cs b/webapi/DataProviders/Converters/EnumerationListSerializer.cs new file mode 100644 index 0000000..a14b884 --- /dev/null +++ b/webapi/DataProviders/Converters/EnumerationListSerializer.cs @@ -0,0 +1,55 @@ +using MongoDB.Bson; +using MongoDB.Bson.IO; +using MongoDB.Bson.Serialization; +using Core.Abstractions; + +namespace DataProviders.Converters { + public class EnumerationListSerializer : IBsonSerializer>, IBsonArraySerializer where T : Enumeration { + private List Deserialize(IBsonReader reader) { + var type = reader.GetCurrentBsonType(); + var response = new List(); + + switch (type) { + case BsonType.Array: + reader.ReadStartArray(); + while (reader.ReadBsonType() != BsonType.EndOfDocument) { + response.Add(Enumeration.FromValue(BsonSerializer.Deserialize(reader))); + } + + reader.ReadEndArray(); + return response; + + default: + throw new NotImplementedException($"No implementation to deserialize {type}"); + } + } + private void Serialize(IBsonWriter writer, List values) { + if (values != null) { + writer.WriteStartArray(); + + foreach (var value in values) { + writer.WriteInt32(value.Id); + } + + writer.WriteEndArray(); + } + + } + + public Type ValueType { get => typeof(List); } + + public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) => Deserialize(context.Reader); + public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value) => Serialize(context.Writer, (List)value); + + List IBsonSerializer>.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) => Deserialize(context.Reader); + public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, List value) => Serialize(context.Writer, value); + + public bool TryGetItemSerializationInfo(out BsonSerializationInfo serializationInfo) { + string elementName = null; + var serializer = BsonSerializer.LookupSerializer(typeof(string)); + var nominalType = typeof(string); + serializationInfo = new BsonSerializationInfo(elementName, serializer, nominalType); + return true; + } + } +} diff --git a/webapi/DataProviders/Converters/EnumerationSerializer.cs b/webapi/DataProviders/Converters/EnumerationSerializer.cs index ccde615..4410cfd 100644 --- a/webapi/DataProviders/Converters/EnumerationSerializer.cs +++ b/webapi/DataProviders/Converters/EnumerationSerializer.cs @@ -6,65 +6,22 @@ using Core.Abstractions; namespace DataProviders.Converters { public class EnumerationSerializer : IBsonSerializer where T : Enumeration { + private T Deserialize(IBsonReader reader) => Enumeration.FromValue(BsonSerializer.Deserialize(reader)); private void Serialize(IBsonWriter writer, T value) => BsonSerializer.Serialize(writer, value.Id); public Type ValueType { get => typeof(T); } - public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) => Deserialize(context.Reader); - public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value) => Serialize(context.Writer, (T)value); + public T Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) => + Deserialize(context.Reader); + public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, T value) => + Serialize(context.Writer, value); - T IBsonSerializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) => Deserialize(context.Reader); - public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, T value) => Serialize(context.Writer, value); - } + public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value) => + Serialize(context.Writer, (T)value); - public class EnumerationListSerializer : IBsonSerializer>, IBsonArraySerializer where T : Enumeration { - private List Deserialize(IBsonReader reader) { - var type = reader.GetCurrentBsonType(); - var response = new List(); - - switch (type) { - case BsonType.Array: - reader.ReadStartArray(); - while (reader.ReadBsonType() != BsonType.EndOfDocument) { - response.Add(Enumeration.FromValue(BsonSerializer.Deserialize(reader))); - } - - reader.ReadEndArray(); - return response; - - default: - throw new NotImplementedException($"No implementation to deserialize {type}"); - } - } - private void Serialize(IBsonWriter writer, List values) { - if (values != null) { - writer.WriteStartArray(); - - foreach (var value in values) { - writer.WriteInt32(value.Id); - } - - writer.WriteEndArray(); - } - - } - - public Type ValueType { get => typeof(List); } - - public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) => Deserialize(context.Reader); - public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value) => Serialize(context.Writer, (List)value); - - List IBsonSerializer>.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) => Deserialize(context.Reader); - public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, List value) => Serialize(context.Writer, value); - - public bool TryGetItemSerializationInfo(out BsonSerializationInfo serializationInfo) { - string elementName = null; - var serializer = BsonSerializer.LookupSerializer(typeof(string)); - var nominalType = typeof(string); - serializationInfo = new BsonSerializationInfo(elementName, serializer, nominalType); - return true; - } + object IBsonSerializer.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) => + Deserialize(context.Reader); } } diff --git a/webapi/DataProviders/DataProviders.csproj b/webapi/DataProviders/DataProviders.csproj index 125abff..2d23766 100644 --- a/webapi/DataProviders/DataProviders.csproj +++ b/webapi/DataProviders/DataProviders.csproj @@ -8,10 +8,10 @@ - + - - + + diff --git a/webapi/DataProviders/Extensions/ServiceCollectionExtensions.cs b/webapi/DataProviders/Extensions/ServiceCollectionExtensions.cs index dc1d34a..100181e 100644 --- a/webapi/DataProviders/Extensions/ServiceCollectionExtensions.cs +++ b/webapi/DataProviders/Extensions/ServiceCollectionExtensions.cs @@ -13,6 +13,8 @@ namespace DataProviders.Extensions public static void RegisterDataproviders(this IServiceCollection services, IDataProvidersConfig appSettings) { var config = appSettings.Database; + if (config == null) throw new NullReferenceException(); + services.AddSingleton(x => new MongoClient(config.ConnectionString)); services.AddSingleton(); diff --git a/webapi/DataProviders/Mappings.cs b/webapi/DataProviders/Mappings.cs index 28794d8..4eb7da9 100644 --- a/webapi/DataProviders/Mappings.cs +++ b/webapi/DataProviders/Mappings.cs @@ -87,7 +87,7 @@ namespace DataProviders { BsonClassMap.RegisterClassMap(cm => { cm.AutoMap(); - cm.GetMemberMap(c => c.ContactType) + cm.GetMemberMap(c => c.Type) .SetSerializer(new EnumerationSerializer()); }); } diff --git a/webapi/Services/ImageProvider/Extensions/IImageProcessingContextExtensions.cs b/webapi/ImageProvider/Extensions/IImageProcessingContextExtensions.cs similarity index 100% rename from webapi/Services/ImageProvider/Extensions/IImageProcessingContextExtensions.cs rename to webapi/ImageProvider/Extensions/IImageProcessingContextExtensions.cs diff --git a/webapi/Services/ImageProvider/Extensions/ServiceCollectionExtensions.cs b/webapi/ImageProvider/Extensions/ServiceCollectionExtensions.cs similarity index 100% rename from webapi/Services/ImageProvider/Extensions/ServiceCollectionExtensions.cs rename to webapi/ImageProvider/Extensions/ServiceCollectionExtensions.cs diff --git a/webapi/Services/ImageProvider/Fonts/FontStylesEnum.cs b/webapi/ImageProvider/Fonts/FontStylesEnum.cs similarity index 100% rename from webapi/Services/ImageProvider/Fonts/FontStylesEnum.cs rename to webapi/ImageProvider/Fonts/FontStylesEnum.cs diff --git a/webapi/Services/ImageProvider/Fonts/FontsEnum.cs b/webapi/ImageProvider/Fonts/FontsEnum.cs similarity index 100% rename from webapi/Services/ImageProvider/Fonts/FontsEnum.cs rename to webapi/ImageProvider/Fonts/FontsEnum.cs diff --git a/webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-Black.ttf b/webapi/ImageProvider/Fonts/Montserrat/Montserrat-Black.ttf similarity index 100% rename from webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-Black.ttf rename to webapi/ImageProvider/Fonts/Montserrat/Montserrat-Black.ttf diff --git a/webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-BlackItalic.ttf b/webapi/ImageProvider/Fonts/Montserrat/Montserrat-BlackItalic.ttf similarity index 100% rename from webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-BlackItalic.ttf rename to webapi/ImageProvider/Fonts/Montserrat/Montserrat-BlackItalic.ttf diff --git a/webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-Bold.ttf b/webapi/ImageProvider/Fonts/Montserrat/Montserrat-Bold.ttf similarity index 100% rename from webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-Bold.ttf rename to webapi/ImageProvider/Fonts/Montserrat/Montserrat-Bold.ttf diff --git a/webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-BoldItalic.ttf b/webapi/ImageProvider/Fonts/Montserrat/Montserrat-BoldItalic.ttf similarity index 100% rename from webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-BoldItalic.ttf rename to webapi/ImageProvider/Fonts/Montserrat/Montserrat-BoldItalic.ttf diff --git a/webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-ExtraBold.ttf b/webapi/ImageProvider/Fonts/Montserrat/Montserrat-ExtraBold.ttf similarity index 100% rename from webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-ExtraBold.ttf rename to webapi/ImageProvider/Fonts/Montserrat/Montserrat-ExtraBold.ttf diff --git a/webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-ExtraBoldItalic.ttf b/webapi/ImageProvider/Fonts/Montserrat/Montserrat-ExtraBoldItalic.ttf similarity index 100% rename from webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-ExtraBoldItalic.ttf rename to webapi/ImageProvider/Fonts/Montserrat/Montserrat-ExtraBoldItalic.ttf diff --git a/webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-ExtraLight.ttf b/webapi/ImageProvider/Fonts/Montserrat/Montserrat-ExtraLight.ttf similarity index 100% rename from webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-ExtraLight.ttf rename to webapi/ImageProvider/Fonts/Montserrat/Montserrat-ExtraLight.ttf diff --git a/webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-ExtraLightItalic.ttf b/webapi/ImageProvider/Fonts/Montserrat/Montserrat-ExtraLightItalic.ttf similarity index 100% rename from webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-ExtraLightItalic.ttf rename to webapi/ImageProvider/Fonts/Montserrat/Montserrat-ExtraLightItalic.ttf diff --git a/webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-Italic.ttf b/webapi/ImageProvider/Fonts/Montserrat/Montserrat-Italic.ttf similarity index 100% rename from webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-Italic.ttf rename to webapi/ImageProvider/Fonts/Montserrat/Montserrat-Italic.ttf diff --git a/webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-Light.ttf b/webapi/ImageProvider/Fonts/Montserrat/Montserrat-Light.ttf similarity index 100% rename from webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-Light.ttf rename to webapi/ImageProvider/Fonts/Montserrat/Montserrat-Light.ttf diff --git a/webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-LightItalic.ttf b/webapi/ImageProvider/Fonts/Montserrat/Montserrat-LightItalic.ttf similarity index 100% rename from webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-LightItalic.ttf rename to webapi/ImageProvider/Fonts/Montserrat/Montserrat-LightItalic.ttf diff --git a/webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-Medium.ttf b/webapi/ImageProvider/Fonts/Montserrat/Montserrat-Medium.ttf similarity index 100% rename from webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-Medium.ttf rename to webapi/ImageProvider/Fonts/Montserrat/Montserrat-Medium.ttf diff --git a/webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-MediumItalic.ttf b/webapi/ImageProvider/Fonts/Montserrat/Montserrat-MediumItalic.ttf similarity index 100% rename from webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-MediumItalic.ttf rename to webapi/ImageProvider/Fonts/Montserrat/Montserrat-MediumItalic.ttf diff --git a/webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-Regular.ttf b/webapi/ImageProvider/Fonts/Montserrat/Montserrat-Regular.ttf similarity index 100% rename from webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-Regular.ttf rename to webapi/ImageProvider/Fonts/Montserrat/Montserrat-Regular.ttf diff --git a/webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-SemiBold.ttf b/webapi/ImageProvider/Fonts/Montserrat/Montserrat-SemiBold.ttf similarity index 100% rename from webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-SemiBold.ttf rename to webapi/ImageProvider/Fonts/Montserrat/Montserrat-SemiBold.ttf diff --git a/webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-SemiBoldItalic.ttf b/webapi/ImageProvider/Fonts/Montserrat/Montserrat-SemiBoldItalic.ttf similarity index 100% rename from webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-SemiBoldItalic.ttf rename to webapi/ImageProvider/Fonts/Montserrat/Montserrat-SemiBoldItalic.ttf diff --git a/webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-Thin.ttf b/webapi/ImageProvider/Fonts/Montserrat/Montserrat-Thin.ttf similarity index 100% rename from webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-Thin.ttf rename to webapi/ImageProvider/Fonts/Montserrat/Montserrat-Thin.ttf diff --git a/webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-ThinItalic.ttf b/webapi/ImageProvider/Fonts/Montserrat/Montserrat-ThinItalic.ttf similarity index 100% rename from webapi/Services/ImageProvider/Fonts/Montserrat/Montserrat-ThinItalic.ttf rename to webapi/ImageProvider/Fonts/Montserrat/Montserrat-ThinItalic.ttf diff --git a/webapi/Services/ImageProvider/ImageBuilder.cs b/webapi/ImageProvider/ImageBuilder.cs similarity index 100% rename from webapi/Services/ImageProvider/ImageBuilder.cs rename to webapi/ImageProvider/ImageBuilder.cs diff --git a/webapi/Services/ImageProvider/ImageProvider.cs b/webapi/ImageProvider/ImageProvider.cs similarity index 94% rename from webapi/Services/ImageProvider/ImageProvider.cs rename to webapi/ImageProvider/ImageProvider.cs index e6f87da..e6fef6e 100644 --- a/webapi/Services/ImageProvider/ImageProvider.cs +++ b/webapi/ImageProvider/ImageProvider.cs @@ -2,11 +2,6 @@ using ImageProvider.Fonts; using Microsoft.Extensions.Logging; using SixLabors.Fonts; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace ImageProvider { diff --git a/webapi/Services/ImageProvider/ImageProvider.csproj b/webapi/ImageProvider/ImageProvider.csproj similarity index 94% rename from webapi/Services/ImageProvider/ImageProvider.csproj rename to webapi/ImageProvider/ImageProvider.csproj index 0b5b0d5..c4bd933 100644 --- a/webapi/Services/ImageProvider/ImageProvider.csproj +++ b/webapi/ImageProvider/ImageProvider.csproj @@ -8,14 +8,15 @@ - + + - + diff --git a/webapi/ReverseProxy/ReverseProxy.csproj b/webapi/ReverseProxy/ReverseProxy.csproj index 05a71f8..861f987 100644 --- a/webapi/ReverseProxy/ReverseProxy.csproj +++ b/webapi/ReverseProxy/ReverseProxy.csproj @@ -10,7 +10,7 @@ - - + + diff --git a/webapi/Services/FileSecurityService/FileSecurityService.csproj b/webapi/Services/FileSecurityService/FileSecurityService.csproj index 0725fb7..e8dc104 100644 --- a/webapi/Services/FileSecurityService/FileSecurityService.csproj +++ b/webapi/Services/FileSecurityService/FileSecurityService.csproj @@ -8,7 +8,7 @@ - + diff --git a/webapi/Services/HashService/Extensions/ServiceCollectionExtensions.cs b/webapi/Services/HashService/Extensions/ServiceCollectionExtensions.cs deleted file mode 100644 index 540cdbb..0000000 --- a/webapi/Services/HashService/Extensions/ServiceCollectionExtensions.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; - -namespace HashService.Extensions { - public static class ServiceCollectionExtensions { - - public static void RegisterHashService(this IServiceCollection services) { - - services.AddSingleton(); - } - } -} diff --git a/webapi/Services/JWTService/JWTService.csproj b/webapi/Services/JWTService/JWTService.csproj index 26e8c73..3550de9 100644 --- a/webapi/Services/JWTService/JWTService.csproj +++ b/webapi/Services/JWTService/JWTService.csproj @@ -8,9 +8,9 @@ - + - + diff --git a/webapi/Tests/Core/CoreTests.csproj b/webapi/Tests/Core/CoreTests.csproj index 35847cf..caf0f16 100644 --- a/webapi/Tests/Core/CoreTests.csproj +++ b/webapi/Tests/Core/CoreTests.csproj @@ -12,11 +12,11 @@ - + - - - + + + diff --git a/webapi/Tests/Extensions/ExtensionsTests.csproj b/webapi/Tests/Extensions/ExtensionsTests.csproj index 4112c56..310858a 100644 --- a/webapi/Tests/Extensions/ExtensionsTests.csproj +++ b/webapi/Tests/Extensions/ExtensionsTests.csproj @@ -9,10 +9,10 @@ - + - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/webapi/WeatherForecast.sln b/webapi/WeatherForecast.sln index a797124..80d85bb 100644 --- a/webapi/WeatherForecast.sln +++ b/webapi/WeatherForecast.sln @@ -7,8 +7,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WeatherForecast", "WeatherF EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Services", "Services", "{113EE574-E047-4727-AA36-841F845504D5}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HashService", "Services\HashService\HashService.csproj", "{B8F84A37-B54B-4606-9BC3-6FEB96A5A34B}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JWTService", "Services\JWTService\JWTService.csproj", "{B717D8BD-BCCA-4515-9A62-CA3BE802D0F7}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core", "Core\Core.csproj", "{BCDED8EB-97B0-4067-BB0A-23F94D1A1288}" @@ -25,7 +23,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExtensionsTests", "Tests\Ex EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoreTests", "Tests\Core\CoreTests.csproj", "{04CB9827-AA6D-4708-A26D-8420C842506D}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageProvider", "Services\ImageProvider\ImageProvider.csproj", "{16552644-D7EE-4B4A-A725-79909A8103DE}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageProvider", "ImageProvider\ImageProvider.csproj", "{16552644-D7EE-4B4A-A725-79909A8103DE}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FileSecurityService", "Services\FileSecurityService\FileSecurityService.csproj", "{AD515653-9145-4894-9017-0ABA5A5892F4}" EndProject @@ -33,6 +31,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReverseProxy", "ReverseProx EndProject Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{7FC6F0BA-2DCB-4B53-A3B3-61CEEF42B9D0}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CryptoProvider", "CryptoProvider\CryptoProvider.csproj", "{E90379CB-BC2D-452F-9F92-24A7B46195D4}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -43,10 +43,6 @@ Global {065AC673-3C4D-4C08-B1A9-3C3A1467B3A7}.Debug|Any CPU.Build.0 = Debug|Any CPU {065AC673-3C4D-4C08-B1A9-3C3A1467B3A7}.Release|Any CPU.ActiveCfg = Release|Any CPU {065AC673-3C4D-4C08-B1A9-3C3A1467B3A7}.Release|Any CPU.Build.0 = Release|Any CPU - {B8F84A37-B54B-4606-9BC3-6FEB96A5A34B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B8F84A37-B54B-4606-9BC3-6FEB96A5A34B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B8F84A37-B54B-4606-9BC3-6FEB96A5A34B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B8F84A37-B54B-4606-9BC3-6FEB96A5A34B}.Release|Any CPU.Build.0 = Release|Any CPU {B717D8BD-BCCA-4515-9A62-CA3BE802D0F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B717D8BD-BCCA-4515-9A62-CA3BE802D0F7}.Debug|Any CPU.Build.0 = Debug|Any CPU {B717D8BD-BCCA-4515-9A62-CA3BE802D0F7}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -91,16 +87,18 @@ Global {7FC6F0BA-2DCB-4B53-A3B3-61CEEF42B9D0}.Debug|Any CPU.Build.0 = Debug|Any CPU {7FC6F0BA-2DCB-4B53-A3B3-61CEEF42B9D0}.Release|Any CPU.ActiveCfg = Release|Any CPU {7FC6F0BA-2DCB-4B53-A3B3-61CEEF42B9D0}.Release|Any CPU.Build.0 = Release|Any CPU + {E90379CB-BC2D-452F-9F92-24A7B46195D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E90379CB-BC2D-452F-9F92-24A7B46195D4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E90379CB-BC2D-452F-9F92-24A7B46195D4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E90379CB-BC2D-452F-9F92-24A7B46195D4}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {B8F84A37-B54B-4606-9BC3-6FEB96A5A34B} = {113EE574-E047-4727-AA36-841F845504D5} {B717D8BD-BCCA-4515-9A62-CA3BE802D0F7} = {113EE574-E047-4727-AA36-841F845504D5} {43315A1D-9E09-4398-84B9-A9D9D623AE5A} = {216302C2-64DE-4AE7-BC14-BDAC5B732472} {04CB9827-AA6D-4708-A26D-8420C842506D} = {216302C2-64DE-4AE7-BC14-BDAC5B732472} - {16552644-D7EE-4B4A-A725-79909A8103DE} = {113EE574-E047-4727-AA36-841F845504D5} {AD515653-9145-4894-9017-0ABA5A5892F4} = {113EE574-E047-4727-AA36-841F845504D5} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution diff --git a/webapi/WeatherForecast/Configuration.cs b/webapi/WeatherForecast/Configuration.cs index 2ebf90b..688c861 100644 --- a/webapi/WeatherForecast/Configuration.cs +++ b/webapi/WeatherForecast/Configuration.cs @@ -1,4 +1,5 @@ -using DataProviders; +using CryptoProvider; +using DataProviders; using JWTService; namespace WeatherForecast { @@ -13,6 +14,11 @@ namespace WeatherForecast { /// public JwtConfig? JwtConfig { get; set; } + /// + /// + /// + public AesKey? JwtTokenEncryption { get; set; } + /// /// /// diff --git a/webapi/WeatherForecast/Controllers/AuthenticationController.cs b/webapi/WeatherForecast/Controllers/AuthenticationController.cs index 7f6ca7f..83e1cf3 100644 --- a/webapi/WeatherForecast/Controllers/AuthenticationController.cs +++ b/webapi/WeatherForecast/Controllers/AuthenticationController.cs @@ -11,7 +11,7 @@ namespace WeatherForecast.Controllers; /// /// /// -[AllowAnonymous] + [ApiController] [Route("api/[controller]")] public class AuthenticationController : ControllerBase { @@ -29,15 +29,26 @@ public class AuthenticationController : ControllerBase { } /// - /// + /// By providing username and password user obtains jwt token /// - /// /// /// - [HttpPost("{siteId}")] - public IActionResult Post([FromRoute] Guid siteId, [FromBody] AuthenticationRequestModel requestData) { - var result = _authenticationService.Post(siteId, requestData); + [AllowAnonymous] + [HttpPost()] + public IActionResult Post([FromBody] AuthenticationRequestModel requestData) { + var result = _authenticationService.Post(requestData); return result.ToActionResult(); } + + /// + /// + /// + /// + [Authorize(Policy = "WhitelistToken")] + [HttpGet()] + + public IActionResult Get() { + return Ok(); + } } diff --git a/webapi/WeatherForecast/Controllers/BlogItemController.cs b/webapi/WeatherForecast/Controllers/BlogItemController.cs index 4c157bf..8d22e11 100644 --- a/webapi/WeatherForecast/Controllers/BlogItemController.cs +++ b/webapi/WeatherForecast/Controllers/BlogItemController.cs @@ -11,7 +11,7 @@ namespace WeatherForecast.Controllers; /// /// /// -[Authorize(Policy = "")] +[Authorize(Policy = "WhitelistToken")] [ApiController] [Route("api/[controller]")] public class BlogItemController : ControllerBase { diff --git a/webapi/WeatherForecast/Controllers/BlogItemsController.cs b/webapi/WeatherForecast/Controllers/BlogItemsController.cs index 8e59ca6..c883d1c 100644 --- a/webapi/WeatherForecast/Controllers/BlogItemsController.cs +++ b/webapi/WeatherForecast/Controllers/BlogItemsController.cs @@ -10,7 +10,7 @@ namespace WeatherForecast.Controllers; /// /// /// -[Authorize(Policy = "")] +[Authorize(Policy = "WhitelistToken")] [ApiController] [Route("api/[controller]")] public class BlogItemsController : ControllerBase { diff --git a/webapi/WeatherForecast/Controllers/CategoryItemController.cs b/webapi/WeatherForecast/Controllers/CategoryItemController.cs index 0688340..d8af455 100644 --- a/webapi/WeatherForecast/Controllers/CategoryItemController.cs +++ b/webapi/WeatherForecast/Controllers/CategoryItemController.cs @@ -11,7 +11,7 @@ namespace WeatherForecast.Controllers; /// /// /// -[Authorize] +[Authorize(Policy = "WhitelistToken")] [ApiController] [Route("api/[controller]")] public class CategoryItemController : ControllerBase { diff --git a/webapi/WeatherForecast/Controllers/CategoryItemsController.cs b/webapi/WeatherForecast/Controllers/CategoryItemsController.cs index 64c2667..15c620e 100644 --- a/webapi/WeatherForecast/Controllers/CategoryItemsController.cs +++ b/webapi/WeatherForecast/Controllers/CategoryItemsController.cs @@ -10,7 +10,7 @@ namespace WeatherForecast.Controllers; /// /// /// -[Authorize] +[Authorize(Policy = "WhitelistToken")] [ApiController] [Route("api/[controller]")] public class CategoryItemsController : ControllerBase { diff --git a/webapi/WeatherForecast/Controllers/FileController.cs b/webapi/WeatherForecast/Controllers/FileController.cs index f675f2c..5f1595f 100644 --- a/webapi/WeatherForecast/Controllers/FileController.cs +++ b/webapi/WeatherForecast/Controllers/FileController.cs @@ -9,7 +9,7 @@ namespace WeatherForecast.Controllers; /// /// /// -[Authorize] +[Authorize(Policy = "WhitelistToken")] [AllowAnonymous] [Route("api/[controller]")] public class FileController : Controller { diff --git a/webapi/WeatherForecast/Controllers/FilesController.cs b/webapi/WeatherForecast/Controllers/FilesController.cs index 69ea626..afcd5cd 100644 --- a/webapi/WeatherForecast/Controllers/FilesController.cs +++ b/webapi/WeatherForecast/Controllers/FilesController.cs @@ -8,7 +8,7 @@ namespace WeatherForecast.Controllers; /// /// /// -[Authorize] +[Authorize(Policy = "WhitelistToken")] [AllowAnonymous] [Route("api/[controller]")] public class FilesController : Controller { diff --git a/webapi/WeatherForecast/Controllers/PasswordController.cs b/webapi/WeatherForecast/Controllers/PasswordController.cs index 7ae8ecd..a5a29dc 100644 --- a/webapi/WeatherForecast/Controllers/PasswordController.cs +++ b/webapi/WeatherForecast/Controllers/PasswordController.cs @@ -10,7 +10,7 @@ namespace WeatherForecast.Controllers; /// /// /// -[Authorize] +[Authorize(Policy = "WhitelistToken")] [Route("api/[controller]")] [ApiController] public class PasswordController : ControllerBase { diff --git a/webapi/WeatherForecast/Controllers/ShopCartItemController.cs b/webapi/WeatherForecast/Controllers/ShopCartItemController.cs index 2ceaa69..f54013c 100644 --- a/webapi/WeatherForecast/Controllers/ShopCartItemController.cs +++ b/webapi/WeatherForecast/Controllers/ShopCartItemController.cs @@ -12,7 +12,7 @@ namespace WeatherForecast.Controllers; /// /// /// -[Authorize] +[Authorize(Policy = "WhitelistToken")] [AllowAnonymous] [Route("api/[controller]")] public class ShopCartItemController : ControllerBase { diff --git a/webapi/WeatherForecast/Controllers/ShopCartItemsController.cs b/webapi/WeatherForecast/Controllers/ShopCartItemsController.cs index 91ebf13..cf842c2 100644 --- a/webapi/WeatherForecast/Controllers/ShopCartItemsController.cs +++ b/webapi/WeatherForecast/Controllers/ShopCartItemsController.cs @@ -11,7 +11,7 @@ namespace WeatherForecast.Controllers; /// /// /// -[Authorize] +[Authorize(Policy = "WhitelistToken")] [AllowAnonymous] [Route("api/[controller]")] public class ShopCartItemsController : ControllerBase { diff --git a/webapi/WeatherForecast/Controllers/ShopItemController.cs b/webapi/WeatherForecast/Controllers/ShopItemController.cs index 1aa681a..eb794e5 100644 --- a/webapi/WeatherForecast/Controllers/ShopItemController.cs +++ b/webapi/WeatherForecast/Controllers/ShopItemController.cs @@ -11,7 +11,7 @@ namespace WeatherForecast.Controllers; /// /// /// -[Authorize] +[Authorize(Policy = "WhitelistToken")] [ApiController] [Route("api/[controller]")] public class ShopItemController : ControllerBase { diff --git a/webapi/WeatherForecast/Controllers/ShopItemsController.cs b/webapi/WeatherForecast/Controllers/ShopItemsController.cs index e920732..92c4af7 100644 --- a/webapi/WeatherForecast/Controllers/ShopItemsController.cs +++ b/webapi/WeatherForecast/Controllers/ShopItemsController.cs @@ -10,7 +10,7 @@ namespace WeatherForecast.Controllers; /// /// /// -[Authorize] +[Authorize(Policy = "WhitelistToken")] [ApiController] [Route("api/[controller]")] public class ShopItemsController : ControllerBase { diff --git a/webapi/WeatherForecast/Controllers/UserController.cs b/webapi/WeatherForecast/Controllers/UserController.cs index dce3c2d..17d706b 100644 --- a/webapi/WeatherForecast/Controllers/UserController.cs +++ b/webapi/WeatherForecast/Controllers/UserController.cs @@ -6,7 +6,7 @@ namespace WeatherForecast.Controllers; /// /// /// -[Authorize] +[Authorize(Policy = "WhitelistToken")] [ApiController] [Route("api/[controller]")] public class UserController : ControllerBase { diff --git a/webapi/WeatherForecast/Policies/WhitelistToken.cs b/webapi/WeatherForecast/Policies/WhitelistToken.cs new file mode 100644 index 0000000..5a0e1aa --- /dev/null +++ b/webapi/WeatherForecast/Policies/WhitelistToken.cs @@ -0,0 +1,55 @@ +using Extensions; +using Microsoft.AspNetCore.Authorization; +using WeatherForecast.Services; + +namespace WeatherForecast.Policies { + /// + /// + /// + public class WhitelistTokenRequirement : IAuthorizationRequirement { + // public string WhiteListToken { get; } + + /// + /// + /// + public WhitelistTokenRequirement() { + // WhiteListToken = whiteListToken; + } + } + + /// + /// + /// + public class WhitelistTokenHandler : AuthorizationHandler { + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly IAuthenticationService _athenticationService; + + /// + /// + /// + /// + /// + public WhitelistTokenHandler( + IHttpContextAccessor httpContextAccessor, + IAuthenticationService athenticationService + ) { + _httpContextAccessor = httpContextAccessor; + _athenticationService = athenticationService; + } + + /// + /// + /// + /// + /// + /// + protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, WhitelistTokenRequirement requirement) { + var request = _httpContextAccessor?.HttpContext?.Request; + + if (request != null && _athenticationService.Get(request.GeBearerToken()).IsSuccess) + context.Succeed(requirement); + + return Task.CompletedTask; + } + } +} diff --git a/webapi/WeatherForecast/Services/AutheticationService.cs b/webapi/WeatherForecast/Services/AutheticationService.cs index eefcd78..db4c973 100644 --- a/webapi/WeatherForecast/Services/AutheticationService.cs +++ b/webapi/WeatherForecast/Services/AutheticationService.cs @@ -3,9 +3,10 @@ using Core.DomainObjects; using DataProviders.Collections; using DomainResults.Common; using ExtensionMethods; -using HashService; +using CryptoProvider; using JWTService; using WeatherForecast.Models.Requests; +using Microsoft.Extensions.Options; namespace WeatherForecast.Services { @@ -17,10 +18,16 @@ namespace WeatherForecast.Services { /// /// /// - /// /// /// - (string?, IDomainResult) Post(Guid siteId, AuthenticationRequestModel requestData); + (string?, IDomainResult) Post(AuthenticationRequestModel requestData); + + /// + /// + /// + /// + /// + IDomainResult Get(string? token); } /// @@ -28,56 +35,59 @@ namespace WeatherForecast.Services { /// public class AutheticationService : ServiceBase, IAuthenticationService { + private readonly IAesKey? _aesKey; private readonly IUserDataProvider _userDataProvider; - private readonly IHashService _hashService; private readonly IJWTService _jwtService; /// /// /// /// + /// /// - /// /// public AutheticationService ( ILogger logger, + IOptions options, IUserDataProvider userDataProvider, - IHashService hashService, IJWTService jwtService ) : base(logger) { + _aesKey = options.Value.JwtTokenEncryption; _userDataProvider = userDataProvider; - _hashService = hashService; _jwtService = jwtService; } /// /// /// - /// /// /// - public (string?, IDomainResult) Post(Guid siteId, AuthenticationRequestModel requestData) { - var opId = Guid.NewGuid(); + public (string?, IDomainResult) Post(AuthenticationRequestModel requestData) { + + if (_aesKey?.IV == null || _aesKey?.Key == null) + return IDomainResult.Failed("IV or Key are not set"); // Retrieve user from database by userName - var (user, getUserResult) = _userDataProvider.GetByNickName(requestData.Username); + var (user, getUserResult) = _userDataProvider.GetByUsername(requestData.Username); if (!getUserResult.IsSuccess || user == null) - return IDomainResult.NotFound(); + return (null, getUserResult); if (user.Passwords.Password == null) - return IDomainResult.Failed($"Opid = [{opId}] Password is not set, create new password."); + return IDomainResult.Failed("Password is not set, create new password."); // Check provided password hash with the stored one - var (salt, hash) = _hashService.CreateSaltedHash(requestData.Password); - if (!_hashService.ValidateHash(requestData.Password, salt, hash)) + var (salt, hash) = HashService.CreateSaltedHash(requestData.Password); + if (!HashService.ValidateHash(requestData.Password, salt, hash)) return IDomainResult.Unauthorized(); // Check password expiration if enabled if (user.Passwords.Expiration.Enabled && DateTime.UtcNow > user.Passwords.Password.Created.AddDays(user.Passwords.Expiration.Days)) { user.Passwords.Expired.Add(user.Passwords.Password.Prototype()); + user.Passwords.Password = null; + user.Tokens = new List(); - return IDomainResult.Failed(); + return IDomainResult.Failed("Password is expired, create new password."); } // Creating JWT token @@ -91,11 +101,15 @@ namespace WeatherForecast.Services { var token = _jwtService.CreateJwtToken(expires, claims); user.Tokens.Add(new Token { - Value = token, + Value = AesService.EncryptString(_aesKey.IV, _aesKey.Key, token), Created = created, Expires = expires, }); + var (_, usdateUserResult) = _userDataProvider.Update(user); + if (!usdateUserResult.IsSuccess) + return IDomainResult.Failed(); + return IDomainResult.Success(token); } @@ -104,7 +118,12 @@ namespace WeatherForecast.Services { /// /// /// - public IDomainResult Get(string token) { + public IDomainResult Get(string? token) { + if (_aesKey?.IV == null || _aesKey?.Key == null) + return IDomainResult.Failed("IV or Key are not set"); + + if (token == null) + return IDomainResult.Failed(); #region Retrieve user id from token claim var (claims, getClaimsResult) = _jwtService.JwtTokenClaims(token); @@ -112,21 +131,27 @@ namespace WeatherForecast.Services { return IDomainResult.Failed(); var userId = claims.SingleOrDefault(x => x.Key == "UserId").Value.ToGuid(); - if(userId == Guid.Empty) + if (userId == Guid.Empty) return IDomainResult.Failed(); #endregion - var (user, getUserRersult) = _userDataProvider.Get(userId); - if(!getUserRersult.IsSuccess || user == null) + + var (user, getUserResult) = _userDataProvider.Get(userId); + if (!getUserResult.IsSuccess || user == null) return IDomainResult.Failed(); - // remove expired tokens - user.Tokens = user.Tokens.Where(x => x.Expires < DateTime.UtcNow).ToList(); + #region Tokens cleanup + var userTokens = user.Tokens.Where(x => x.Expires > DateTime.UtcNow).ToList(); - if (!user.Tokens.Any(x => x.Value == token)) - return IDomainResult.Failed(); + if (user.Tokens.Count != userTokens.Count) { + user.Tokens = userTokens; + _userDataProvider.Update(user); + } + #endregion - return IDomainResult.Success(); + return userTokens.Select(x => AesService.DecryptString(_aesKey.IV, _aesKey.Key, x.Value)).Any(x => string.Compare(x, token) == 0) + ? IDomainResult.Success() + : IDomainResult.Failed(); } } } diff --git a/webapi/WeatherForecast/Services/PasswordService.cs b/webapi/WeatherForecast/Services/PasswordService.cs index d1c89fa..e4e4ea2 100644 --- a/webapi/WeatherForecast/Services/PasswordService.cs +++ b/webapi/WeatherForecast/Services/PasswordService.cs @@ -2,7 +2,7 @@ using DataProviders.Collections; -using HashService; +using CryptoProvider; using JWTService; using WeatherForecast.Models.Requests; using Core.Abstractions; @@ -27,7 +27,7 @@ namespace WeatherForecast.Services { /// public class PasswordService : ServiceBase, IPasswordService { - private readonly IHashService _hashService; + private readonly IUserDataProvider _userDataProvider; /// @@ -39,11 +39,9 @@ namespace WeatherForecast.Services { /// public PasswordService( ILogger logger, - IHashService hashService, IUserDataProvider userDataProvider ) : base(logger) { - _hashService = hashService; _userDataProvider = userDataProvider; } @@ -58,7 +56,7 @@ namespace WeatherForecast.Services { try { - var (salt, hash) = _hashService.CreateSaltedHash(requestData.Password); + var (salt, hash) = HashService.CreateSaltedHash(requestData.Password); diff --git a/webapi/WeatherForecast/Startup.cs b/webapi/WeatherForecast/Startup.cs index f020de4..abd3ff9 100644 --- a/webapi/WeatherForecast/Startup.cs +++ b/webapi/WeatherForecast/Startup.cs @@ -9,8 +9,9 @@ using System.Text.Json.Serialization; using FileSecurityService.Extensions; using ImageProvider.Extensions; using JWTService.Extensions; -using HashService.Extensions; using Core.Middlewares; +using Microsoft.AspNetCore.Authorization; +using WeatherForecast.Policies; namespace WeatherForecast { @@ -75,6 +76,16 @@ namespace WeatherForecast { // https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-context?view=aspnetcore-3.1#use-httpcontext-from-custom-components services.AddHttpContextAccessor(); + #region Policy Authorizations https://docs.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-6.0 + services.AddScoped(); + // services.AddScoped(); + + services.AddAuthorization(options => { + options.AddPolicy("WhitelistToken", policy => policy.Requirements.Add(new WhitelistTokenRequirement())); + // options.AddPolicy("RecaptchaToken", policy => policy.Requirements.Add(new RecaptchaTokenRequirement("/swagger/index.html"))); + }); + #endregion + services.AddScoped(); services.AddScoped(); services.AddScoped(); @@ -96,7 +107,6 @@ namespace WeatherForecast { services.RegisterFileSecurityService(); services.RegisterImageProvider(); services.RegisterJWTService(appSettings); - services.RegisterHashService(); #region Swagger services.ConfigureSwaggerGen(options => { diff --git a/webapi/WeatherForecast/WeatherForecast.csproj b/webapi/WeatherForecast/WeatherForecast.csproj index a147823..fa5e719 100644 --- a/webapi/WeatherForecast/WeatherForecast.csproj +++ b/webapi/WeatherForecast/WeatherForecast.csproj @@ -14,24 +14,24 @@ - - + + - + - - - + + + + + - - diff --git a/webapi/WeatherForecast/appsettings.json b/webapi/WeatherForecast/appsettings.json index 2a0cd54..a12d0e4 100644 --- a/webapi/WeatherForecast/appsettings.json +++ b/webapi/WeatherForecast/appsettings.json @@ -20,6 +20,11 @@ "Expires": "365" }, + "JwtTokenEncryption": { + "IV": "2YJIwoV2C7QpgN8dquznmw==", + "Key": "KBsLNL2/pju3uX6Wtjkf2zUS1TbJ0YiD84zusIyPVUM=" + }, + "Database": { "ConnectionString": "mongodb://root:example@mongo:27017"