From 76779afd2e5dd7a67a5a99a0309f3dfb8efb2b3c Mon Sep 17 00:00:00 2001 From: csimonapastore Date: Wed, 26 Feb 2025 22:23:15 +0100 Subject: [PATCH] Adding authentication and authorization flow --- MainProject.Tests/JsonData/appsettings.json | 15 +++ .../JsonData/invalidCryptAppsettings.json | 42 +++++++ MainProject.Tests/Utils/CryptoUtils_Tests.cs | 108 ++++++++++++++++++ MainProject.Tests/Utils/ProgramUtils_Tests.cs | 8 -- MainProject/Controllers/AuthController.cs | 62 ++++++++++ MainProject/Controllers/BaseController.cs | 6 + .../Attributes/JwtAuthorizationAttribute .cs | 32 ++++++ MainProject/MainProject.csproj | 15 ++- .../Models/Api/Common/Role/UserRole.cs | 9 ++ .../Api/Common/User/AuthenticatedUser.cs | 19 +++ .../Api/Data/Auth/AuthenticateRequestData.cs | 13 +++ .../Api/Request/Auth/AuthenticateRequest.cs | 14 +++ MainProject/Models/Database/SqlServer/Base.cs | 1 + MainProject/Models/Settings/AppSettings.cs | 2 + .../Models/Settings/EncryptionSettings.cs | 8 ++ MainProject/Models/Settings/JWTSettings.cs | 12 ++ MainProject/Services/AuthService.cs | 38 ++++++ MainProject/Services/BaseService.cs | 24 ++++ MainProject/Services/JwtService.cs | 32 ++++++ MainProject/Utils/CryptoUtils.cs | 59 ++++++++++ MainProject/Utils/ProgramUtils.cs | 51 ++++++++- MainProject/appsettings.json | 11 +- 22 files changed, 562 insertions(+), 19 deletions(-) create mode 100644 MainProject.Tests/JsonData/invalidCryptAppsettings.json create mode 100644 MainProject.Tests/Utils/CryptoUtils_Tests.cs create mode 100644 MainProject/Controllers/AuthController.cs create mode 100644 MainProject/Core/Attributes/JwtAuthorizationAttribute .cs create mode 100644 MainProject/Models/Api/Common/Role/UserRole.cs create mode 100644 MainProject/Models/Api/Common/User/AuthenticatedUser.cs create mode 100644 MainProject/Models/Api/Data/Auth/AuthenticateRequestData.cs create mode 100644 MainProject/Models/Api/Request/Auth/AuthenticateRequest.cs create mode 100644 MainProject/Models/Settings/EncryptionSettings.cs create mode 100644 MainProject/Models/Settings/JWTSettings.cs create mode 100644 MainProject/Services/AuthService.cs create mode 100644 MainProject/Services/BaseService.cs create mode 100644 MainProject/Services/JwtService.cs create mode 100644 MainProject/Utils/CryptoUtils.cs diff --git a/MainProject.Tests/JsonData/appsettings.json b/MainProject.Tests/JsonData/appsettings.json index 58c3663..80450dd 100644 --- a/MainProject.Tests/JsonData/appsettings.json +++ b/MainProject.Tests/JsonData/appsettings.json @@ -21,6 +21,21 @@ "Name": "MIT License", "Url": "https://github.com/csimonapastore/BasicDotnetTemplate/blob/main/LICENSE.md" } + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "JWTSettings": { + "ValidAudience": "http://localhost:4200", + "ValidIssuer": "http://localhost:5000", + "Secret": "JWTAuthenticationHIGHsecuredPasswordVVVp1OH7Xzyr", + "ExpiredAfterMinsOfInactivity": 15 + }, + "EncryptionSettings": { + "Salt": "S7VIidfXQf1tOQYX" } } diff --git a/MainProject.Tests/JsonData/invalidCryptAppsettings.json b/MainProject.Tests/JsonData/invalidCryptAppsettings.json new file mode 100644 index 0000000..3c2dc8e --- /dev/null +++ b/MainProject.Tests/JsonData/invalidCryptAppsettings.json @@ -0,0 +1,42 @@ +{ + "AppSettings" : + { + "Settings": { + "Name": "MainProject", + "Version": "v1.0", + "Description": "This template contains basic configuration for a .Net 8 backend" + }, + "DatabaseSettings": { + "SqlServerConnectionString": "SQLSERVER_DB_SERVER", + "MongoDbConnectionString": "MONGO_DB_SERVER", + "PostgreSQLConnectionString": "POSTGRESQL_DB_SERVER" + }, + "OpenApiSettings": { + "TermsOfServiceUrl": "", + "OpenApiContact": { + "Name": "", + "Url": "" + }, + "OpenApiLicense": { + "Name": "MIT License", + "Url": "https://github.com/csimonapastore/BasicDotnetTemplate/blob/main/LICENSE.md" + } + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "JWTSettings": { + "ValidAudience": "http://localhost:4200", + "ValidIssuer": "http://localhost:5000", + "Secret": "JWTAuthenticationHIGHsecuredPasswordVVVp1OH7Xzyr", + "ExpiredAfterMinsOfInactivity": 15 + }, + "EncryptionSettings": { + "Salt": "AAAAA" + } + } + +} \ No newline at end of file diff --git a/MainProject.Tests/Utils/CryptoUtils_Tests.cs b/MainProject.Tests/Utils/CryptoUtils_Tests.cs new file mode 100644 index 0000000..8e255fb --- /dev/null +++ b/MainProject.Tests/Utils/CryptoUtils_Tests.cs @@ -0,0 +1,108 @@ +using System; +using BasicDotnetTemplate.MainProject.Models.Settings; +using Microsoft.AspNetCore.Builder; +using BasicDotnetTemplate.MainProject.Utils; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Configuration; + + +namespace BasicDotnetTemplate.MainProject.Tests; + +[TestClass] +public class CryptoUtils_Tests +{ + [TestMethod] + public void Decrypt_Success() + { + try + { + string encryptedData = "d2ejdI1f4GYpq2kTB1nmeQkZXqR3QSxH8Yqkl7iv7zgfQ13qG/0dUUsreG/WGHWRBE5mVWaV43A="; + WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty()); + AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData"); + CryptUtils cryptoUtils = new CryptUtils(appSettings); + var decryptedData = cryptoUtils.Decrypt(encryptedData); + var isEqual = decryptedData == "ThisIsASuccessfullTest"; + Assert.IsTrue(isEqual); + } + catch (Exception ex) + { + Console.WriteLine(ex.InnerException); + Assert.Fail($"An exception was thrown: {ex.Message}"); + } + } + + [TestMethod] + public void Decrypt_Error() + { + try + { + string encryptedData = "d1ejdI1f4GYpq2kTB1nmeQkZXqR3QSxH8Yqkl7iv7zgfQ13qG/0dUUsreG/WGHWRBE5mVWaV43A="; + WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty()); + AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData"); + CryptUtils cryptoUtils = new CryptUtils(appSettings); + var decryptedData = cryptoUtils.Decrypt(encryptedData); + var isEqual = decryptedData == "ThisIsASuccessfullTest"; + Assert.IsFalse(isEqual); + } + catch (Exception ex) + { + Console.WriteLine(ex.InnerException); + Assert.Fail($"An exception was thrown: {ex.Message}"); + } + } + + [TestMethod] + public void Decrypt_ArgumentException() + { + try + { + string encryptedData = "d1ejdI1f4GYpq2kTB1nmeQkZXqR3QSxH8Yqkl7iv7zgfQ13qG/0dUUsreG/WGHWRBE5mVWaV43A="; + WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty()); + AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData", "invalidCryptAppsettings.json"); + CryptUtils cryptoUtils = new CryptUtils(appSettings); + try + { + var decryptedData = cryptoUtils.Decrypt(encryptedData); + Assert.Fail($"Expected exception instead of response: {decryptedData}"); + } + catch (ArgumentException argumentException) + { + Assert.IsInstanceOfType(argumentException, typeof(ArgumentException)); + } + catch (Exception exception) + { + Assert.IsInstanceOfType(exception, typeof(ArgumentException)); + } + } + catch (Exception ex) + { + Console.WriteLine(ex.InnerException); + Assert.Fail($"An exception was thrown: {ex.Message}"); + } + } + + [TestMethod] + public void Decrypt_Empty() + { + try + { + string encryptedData = "WGHWRBE5mVWaV="; + WebApplicationBuilder builder = WebApplication.CreateBuilder(Array.Empty()); + AppSettings appSettings = ProgramUtils.AddConfiguration(ref builder, System.AppDomain.CurrentDomain.BaseDirectory + "/JsonData"); + CryptUtils cryptoUtils = new CryptUtils(appSettings); + var decryptedData = cryptoUtils.Decrypt(encryptedData); + var isEqual = decryptedData == String.Empty; + Assert.IsTrue(isEqual); + } + catch (Exception ex) + { + Console.WriteLine(ex.InnerException); + Assert.Fail($"An exception was thrown: {ex.Message}"); + } + } + +} + + + + diff --git a/MainProject.Tests/Utils/ProgramUtils_Tests.cs b/MainProject.Tests/Utils/ProgramUtils_Tests.cs index 7397366..9d85e62 100644 --- a/MainProject.Tests/Utils/ProgramUtils_Tests.cs +++ b/MainProject.Tests/Utils/ProgramUtils_Tests.cs @@ -1,11 +1,3 @@ -using System; -using System.Reflection; -using System.Net; -using System.Net.Http; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using BasicDotnetTemplate.MainProject; -using BasicDotnetTemplate.MainProject.Models.Api.Response; -using Microsoft.Extensions.DependencyModel.Resolution; using BasicDotnetTemplate.MainProject.Models.Settings; using Microsoft.AspNetCore.Builder; using BasicDotnetTemplate.MainProject.Utils; diff --git a/MainProject/Controllers/AuthController.cs b/MainProject/Controllers/AuthController.cs new file mode 100644 index 0000000..5fd107e --- /dev/null +++ b/MainProject/Controllers/AuthController.cs @@ -0,0 +1,62 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using BasicDotnetTemplate.MainProject.Core.Attributes; +using BasicDotnetTemplate.MainProject.Models.Api.Request.Auth; +using BasicDotnetTemplate.MainProject.Models.Api.Response; +using BasicDotnetTemplate.MainProject.Services; + +namespace BasicDotnetTemplate.MainProject.Controllers +{ + [Route("[controller]")] + public class AuthController : BaseController + { + private IAuthService _authService; + public AuthController( + IConfiguration configuration, + IAuthService authService + ) : base(configuration) + { + this._authService = authService; + } + + [HttpPost("authenticate")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task AuthenticateAsync([FromBody] AuthenticateRequest request) + { + try + { + if ( + request == null || + request.Data == null || + String.IsNullOrEmpty(request.Data.Username) || + String.IsNullOrEmpty(request.Data.Password) + ) + { + return BadRequest("Request is not well formed"); + } + var data = await this._authService.AuthenticateAsync(request.Data); + + if (data == null) + { + return NotFound(); + } + + return Success(String.Empty, data); + } + catch (Exception exception) + { + var message = "Something went wrong"; + if (!String.IsNullOrEmpty(exception?.Message)) + { + message += $". {exception?.Message}"; + } + return InternalServerError(message); + } + + } + } +} \ No newline at end of file diff --git a/MainProject/Controllers/BaseController.cs b/MainProject/Controllers/BaseController.cs index 0bd4c27..640ad79 100644 --- a/MainProject/Controllers/BaseController.cs +++ b/MainProject/Controllers/BaseController.cs @@ -37,6 +37,12 @@ namespace BasicDotnetTemplate.MainProject.Controllers return StatusCode((int)HttpStatusCode.OK, CreateResponse(HttpStatusCode.OK, message, data)); } + protected IActionResult NotModified(string message, object? data = null) + { + message = String.IsNullOrEmpty(message) ? "Not modified" : message; + return StatusCode((int)HttpStatusCode.NotModified, CreateResponse(HttpStatusCode.NotModified, message, data)); + } + protected IActionResult NotFound(string message, object? data = null) { message = String.IsNullOrEmpty(message) ? "Not found" : message; diff --git a/MainProject/Core/Attributes/JwtAuthorizationAttribute .cs b/MainProject/Core/Attributes/JwtAuthorizationAttribute .cs new file mode 100644 index 0000000..2a7121f --- /dev/null +++ b/MainProject/Core/Attributes/JwtAuthorizationAttribute .cs @@ -0,0 +1,32 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.IdentityModel.Tokens; +using System; +using System.IdentityModel.Tokens.Jwt; +using System.Linq; +using System.Text; +using Microsoft.AspNetCore.Authorization; + +namespace BasicDotnetTemplate.MainProject.Core.Attributes +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)] + public class JwtAuthorizationAttribute : Attribute, IAuthorizationFilter + { + private readonly string? _policyName; + + public JwtAuthorizationAttribute() { } + public JwtAuthorizationAttribute(string policyName) + { + _policyName = policyName; + } + + public void OnAuthorization(AuthorizationFilterContext context) + { + return; + + + } + } +} diff --git a/MainProject/MainProject.csproj b/MainProject/MainProject.csproj index 7aab2b7..3abde16 100644 --- a/MainProject/MainProject.csproj +++ b/MainProject/MainProject.csproj @@ -2,6 +2,7 @@ Exe + Debug net8.0 enable enable @@ -13,18 +14,22 @@ all - - - + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all + diff --git a/MainProject/Models/Api/Common/Role/UserRole.cs b/MainProject/Models/Api/Common/Role/UserRole.cs new file mode 100644 index 0000000..a57914a --- /dev/null +++ b/MainProject/Models/Api/Common/Role/UserRole.cs @@ -0,0 +1,9 @@ +namespace BasicDotnetTemplate.MainProject.Models.Api.Common.Role; + +public class UserRole +{ +#nullable enable + public string? Guid { get; set; } + public string? Name { get; set; } +#nullable disable +} diff --git a/MainProject/Models/Api/Common/User/AuthenticatedUser.cs b/MainProject/Models/Api/Common/User/AuthenticatedUser.cs new file mode 100644 index 0000000..9ce6669 --- /dev/null +++ b/MainProject/Models/Api/Common/User/AuthenticatedUser.cs @@ -0,0 +1,19 @@ +using BasicDotnetTemplate.MainProject.Models.Api.Common.Role; + +namespace BasicDotnetTemplate.MainProject.Models.Api.Common.User; + +public class AuthenticatedUser +{ +#nullable enable + public string? Guid { get; set; } + public string? Username { get; set; } + public string? FirstName { get; set; } + public string? LastName { get; set; } + public string? Email { get; set; } + public UserRole? Role { get; set; } +#nullable disable +} + + + + diff --git a/MainProject/Models/Api/Data/Auth/AuthenticateRequestData.cs b/MainProject/Models/Api/Data/Auth/AuthenticateRequestData.cs new file mode 100644 index 0000000..18901f7 --- /dev/null +++ b/MainProject/Models/Api/Data/Auth/AuthenticateRequestData.cs @@ -0,0 +1,13 @@ +namespace BasicDotnetTemplate.MainProject.Models.Api.Data.Auth; + +public class AuthenticateRequestData +{ +#nullable enable + public string? Username { get; set; } + public string? Password { get; set; } +#nullable disable +} + + + + diff --git a/MainProject/Models/Api/Request/Auth/AuthenticateRequest.cs b/MainProject/Models/Api/Request/Auth/AuthenticateRequest.cs new file mode 100644 index 0000000..f7a8e52 --- /dev/null +++ b/MainProject/Models/Api/Request/Auth/AuthenticateRequest.cs @@ -0,0 +1,14 @@ +using BasicDotnetTemplate.MainProject.Models.Api.Data.Auth; + +namespace BasicDotnetTemplate.MainProject.Models.Api.Request.Auth; + +public class AuthenticateRequest +{ +#nullable enable + public AuthenticateRequestData? Data { get; set; } +#nullable disable +} + + + + diff --git a/MainProject/Models/Database/SqlServer/Base.cs b/MainProject/Models/Database/SqlServer/Base.cs index 6569442..c80e49b 100644 --- a/MainProject/Models/Database/SqlServer/Base.cs +++ b/MainProject/Models/Database/SqlServer/Base.cs @@ -3,6 +3,7 @@ namespace BasicDotnetTemplate.MainProject.Models.Database.SqlServer public class Base { public int Id { get; set; } + public string Guid { get; set; } public DateTime CreationTime { get; set; } public int CreationUserId { get; set; } public DateTime UpdateTime { get; set; } diff --git a/MainProject/Models/Settings/AppSettings.cs b/MainProject/Models/Settings/AppSettings.cs index 86dec6d..a804c8e 100644 --- a/MainProject/Models/Settings/AppSettings.cs +++ b/MainProject/Models/Settings/AppSettings.cs @@ -7,6 +7,8 @@ public class AppSettings public PrivateSettings? PrivateSettings { get; set; } public OpenApiSettings? OpenApiSettings { get; set; } public DatabaseSettings? DatabaseSettings { get; set; } + public JWTSettings? JWTSettings { get; set; } + public EncryptionSettings? EncryptionSettings { get; set; } #nullable disable } \ No newline at end of file diff --git a/MainProject/Models/Settings/EncryptionSettings.cs b/MainProject/Models/Settings/EncryptionSettings.cs new file mode 100644 index 0000000..d157fe9 --- /dev/null +++ b/MainProject/Models/Settings/EncryptionSettings.cs @@ -0,0 +1,8 @@ +namespace BasicDotnetTemplate.MainProject.Models.Settings; + +public class EncryptionSettings +{ +#nullable enable + public string? Salt { get; set; } +#nullable disable +} \ No newline at end of file diff --git a/MainProject/Models/Settings/JWTSettings.cs b/MainProject/Models/Settings/JWTSettings.cs new file mode 100644 index 0000000..f6b9deb --- /dev/null +++ b/MainProject/Models/Settings/JWTSettings.cs @@ -0,0 +1,12 @@ +namespace BasicDotnetTemplate.MainProject.Models.Settings; + +public class JWTSettings +{ +#nullable enable + public string? ValidAudience { get; set; } + public string? ValidIssuer { get; set; } + public string? Secret { get; set; } + public int? ExpiredAfterMinsOfInactivity { get; set; } + +#nullable disable +} \ No newline at end of file diff --git a/MainProject/Services/AuthService.cs b/MainProject/Services/AuthService.cs new file mode 100644 index 0000000..b2b68f1 --- /dev/null +++ b/MainProject/Services/AuthService.cs @@ -0,0 +1,38 @@ + +using BasicDotnetTemplate.MainProject.Models.Api.Data.Auth; +using BasicDotnetTemplate.MainProject.Models.Api.Common.User; +using BasicDotnetTemplate.MainProject.Utils; + +namespace BasicDotnetTemplate.MainProject.Services; + +public interface IAuthService +{ + Task AuthenticateAsync(AuthenticateRequestData data); +} + +public class AuthService : BaseService, IAuthService +{ + protected CryptUtils _cryptUtils; + + public AuthService( + IConfiguration configuration + ) : base(configuration) + { + _cryptUtils = new CryptUtils(_appSettings); + } + + public async Task AuthenticateAsync(AuthenticateRequestData data) + { + AuthenticatedUser? authenticatedUser = null; + var decryptedUsername = _cryptUtils.Decrypt(data.Username ?? String.Empty); + var decryptedPassword = _cryptUtils.Decrypt(data.Password ?? String.Empty); + + if (!String.IsNullOrEmpty(decryptedUsername) && !String.IsNullOrEmpty(decryptedPassword)) + { + + } + + return authenticatedUser; + } +} + diff --git a/MainProject/Services/BaseService.cs b/MainProject/Services/BaseService.cs new file mode 100644 index 0000000..3930d6b --- /dev/null +++ b/MainProject/Services/BaseService.cs @@ -0,0 +1,24 @@ +using Microsoft.IdentityModel.Tokens; +using System; +using System.Collections.Generic; +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Text; +using System.Threading.Tasks; +using BasicDotnetTemplate.MainProject.Models.Settings; + +namespace BasicDotnetTemplate.MainProject.Services; + +public class BaseService +{ + protected readonly IConfiguration _configuration; + protected readonly AppSettings _appSettings; + + public BaseService(IConfiguration configuration) + { + _configuration = configuration; + _appSettings = new AppSettings(); + _configuration.GetSection("AppSettings").Bind(_appSettings); + } +} + diff --git a/MainProject/Services/JwtService.cs b/MainProject/Services/JwtService.cs new file mode 100644 index 0000000..cf6f561 --- /dev/null +++ b/MainProject/Services/JwtService.cs @@ -0,0 +1,32 @@ +using Microsoft.IdentityModel.Tokens; +using System; +using System.Collections.Generic; +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Text; + +namespace BasicDotnetTemplate.MainProject.Services; + +public interface IJwtService +{ + +} + +public class JwtService : BaseService, IJwtService +{ + private readonly string _jwtKey; + private readonly string _jwtIssuer; + private readonly string _jwtAudience; + + public JwtService( + IConfiguration configuration + ) : base(configuration) + { + _jwtKey = _appSettings?.JWTSettings?.Secret ?? String.Empty; + _jwtIssuer = _appSettings?.JWTSettings?.ValidIssuer ?? String.Empty; + _jwtAudience = _appSettings?.JWTSettings?.ValidAudience ?? String.Empty; + } + + +} + diff --git a/MainProject/Utils/CryptoUtils.cs b/MainProject/Utils/CryptoUtils.cs new file mode 100644 index 0000000..5298ad6 --- /dev/null +++ b/MainProject/Utils/CryptoUtils.cs @@ -0,0 +1,59 @@ +using System; +using System.Security.Cryptography; +using System.Text; +using BasicDotnetTemplate.MainProject.Models.Settings; + +namespace BasicDotnetTemplate.MainProject.Utils; +public class CryptUtils +{ + private readonly string secretKey; + private const int M = 16; + private const int N = 32; + private readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger(); + public CryptUtils(AppSettings appSettings) + { + secretKey = appSettings.EncryptionSettings?.Salt ?? String.Empty; + } + + public string Decrypt(string encryptedData) + { + var decrypted = String.Empty; + + if (String.IsNullOrEmpty(this.secretKey) || this.secretKey.Length < M) + { + throw new ArgumentException("Unable to proceed with decryption due to invalid settings"); + } + + if (!String.IsNullOrEmpty(encryptedData) && encryptedData.Length > N) + { + var iv = encryptedData.Substring(0, M); + + var cipherText = encryptedData.Substring(N); + var fullCipher = Convert.FromBase64String(cipherText); + + using (var aes = Aes.Create()) + { + aes.Key = Encoding.UTF8.GetBytes(this.secretKey); + aes.IV = Encoding.UTF8.GetBytes(iv); + + using (var decryptor = aes.CreateDecryptor(aes.Key, aes.IV)) + { + using (var msDecrypt = new MemoryStream(fullCipher)) + { + using (var cryptoStream = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) + { + using (var srDecrypt = new StreamReader(cryptoStream)) + { + decrypted = srDecrypt.ReadToEnd(); + } + } + } + } + } + } + + return decrypted; + } + +} + diff --git a/MainProject/Utils/ProgramUtils.cs b/MainProject/Utils/ProgramUtils.cs index 22587c1..22b04dd 100644 --- a/MainProject/Utils/ProgramUtils.cs +++ b/MainProject/Utils/ProgramUtils.cs @@ -4,6 +4,7 @@ using MongoDB.Driver; using NLog; using BasicDotnetTemplate.MainProject.Core.Database; using BasicDotnetTemplate.MainProject.Models.Settings; +using BasicDotnetTemplate.MainProject.Services; @@ -41,7 +42,6 @@ public static class ProgramUtils return appSettings; } - public static OpenApiInfo CreateOpenApiInfo(AppSettings appSettings) { OpenApiInfo openApiInfo = new OpenApiInfo @@ -83,11 +83,53 @@ public static class ProgramUtils builder.Services.AddSwaggerGen(options => { options.SwaggerDoc("v1", CreateOpenApiInfo(appSettings)); + + options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme + { + Description = "Inserisci il Bearer Token nel formato **'Bearer {token}'**", + Name = "Authorization", + In = ParameterLocation.Header, + Type = SecuritySchemeType.Http, + Scheme = "Bearer" + }); + + options.AddSecurityDefinition("ApiKey", new OpenApiSecurityScheme + { + Description = "Inserisci la tua API Key nel campo appropriato.", + Name = "ApiKey", + In = ParameterLocation.Header, + Type = SecuritySchemeType.ApiKey + }); + + options.AddSecurityRequirement(new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = "Bearer" + } + }, + new string[] {} + }, + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = "ApiKey" + } + }, + new string[] {} + } + }); }); Logger.Info("[ProgramUtils][AddOpenApi] Ended swagger doc"); } - public static void AddServices(ref WebApplicationBuilder builder) { Logger.Info("[ProgramUtils][AddServices] Adding services"); @@ -99,7 +141,6 @@ public static class ProgramUtils Logger.Info("[ProgramUtils][AddServices] Done services"); } - public static void AddMiddlewares(ref WebApplication app) { Logger.Info("[ProgramUtils][AddMiddlewares] Adding middlewares"); @@ -126,7 +167,6 @@ public static class ProgramUtils Logger.Info("[ProgramUtils][AddMiddlewares] Done middlewares"); } - public static void AddDbContext(ref WebApplicationBuilder builder, AppSettings appSettings) { Logger.Info("[ProgramUtils][AddDbContext] Adding DbContext"); @@ -168,10 +208,11 @@ public static class ProgramUtils messages = String.IsNullOrEmpty(messages) ? "No context" : messages; Logger.Info($"[ProgramUtils][AddDbContext] {messages} added"); } - public static void AddScopes(ref WebApplicationBuilder builder) { Logger.Info("[ProgramUtils][AddScopes] Adding scopes"); + builder.Services.AddScoped(); + builder.Services.AddScoped(); Logger.Info("[ProgramUtils][AddScopes] Done scopes"); } diff --git a/MainProject/appsettings.json b/MainProject/appsettings.json index 0fb5b09..3fcf5e6 100644 --- a/MainProject/appsettings.json +++ b/MainProject/appsettings.json @@ -3,7 +3,7 @@ { "Settings": { "Name": "MainProject", - "Version": "v1.0", + "Version": "v1", "Description": "This template contains basic configuration for a .Net 8 backend" }, "DatabaseSettings": { @@ -27,6 +27,15 @@ "Default": "Information", "Microsoft.AspNetCore": "Warning" } + }, + "JWTSettings": { + "ValidAudience": "http://localhost:4200", + "ValidIssuer": "http://localhost:5000", + "Secret": "JWTAuthenticationHIGHsecuredPasswordVVVp1OH7Xzyr", + "ExpiredAfterMinsOfInactivity": 15 + }, + "EncryptionSettings": { + "Salt": "S7VIidfXQf1tOQYX" } } } \ No newline at end of file