From f02e9b79537462d0754f3b877dfe8e622dfaf373 Mon Sep 17 00:00:00 2001 From: Felipe Augusto Date: Wed, 17 Jan 2024 10:03:17 -0300 Subject: [PATCH 1/3] feat: Auth using Microsoft Entra ID --- .../Controllers/v1/CachorrosController.cs | 2 ++ .../Swagger/ConfigureSwaggerOptions.cs | 28 +++++++++++++++++++ src/DEPLOY.Cachorro.Api/Program.cs | 7 ++++- src/DEPLOY.Cachorro.Api/appsettings.json | 7 ++++- 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/DEPLOY.Cachorro.Api/Controllers/v1/CachorrosController.cs b/src/DEPLOY.Cachorro.Api/Controllers/v1/CachorrosController.cs index 4ca1cbe..39865c4 100644 --- a/src/DEPLOY.Cachorro.Api/Controllers/v1/CachorrosController.cs +++ b/src/DEPLOY.Cachorro.Api/Controllers/v1/CachorrosController.cs @@ -1,5 +1,6 @@ using Asp.Versioning; using DEPLOY.Cachorro.Repository; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Swashbuckle.AspNetCore.Annotations; @@ -9,6 +10,7 @@ namespace DEPLOY.Cachorro.Api.Controllers.v1 [ApiController] [ApiVersion("1.0")] [Route("api/v{version:apiVersion}/[controller]")] + [Authorize] public class CachorrosController : ControllerBase { public readonly CachorroDbContext _context; diff --git a/src/DEPLOY.Cachorro.Api/Extensions/Swagger/ConfigureSwaggerOptions.cs b/src/DEPLOY.Cachorro.Api/Extensions/Swagger/ConfigureSwaggerOptions.cs index 0515567..abb84f0 100644 --- a/src/DEPLOY.Cachorro.Api/Extensions/Swagger/ConfigureSwaggerOptions.cs +++ b/src/DEPLOY.Cachorro.Api/Extensions/Swagger/ConfigureSwaggerOptions.cs @@ -1,5 +1,6 @@ using Asp.Versioning; using Asp.Versioning.ApiExplorer; +using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.Extensions.Options; using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; @@ -12,6 +13,8 @@ namespace DEPLOY.Cachorro.Api.Extensions.Swagger [ExcludeFromCodeCoverage] public class ConfigureSwaggerOptions : IConfigureOptions { + public const string AuthenticationScheme = "JWT"; + public const string HeaderName = "Authorization"; private readonly IApiVersionDescriptionProvider provider; public ConfigureSwaggerOptions(IApiVersionDescriptionProvider provider) => this.provider = provider; @@ -22,6 +25,31 @@ public void Configure(SwaggerGenOptions options) { options.SwaggerDoc(description.GroupName, CreateInfoForApiVersion(description)); } + + options.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme, new OpenApiSecurityScheme + { + Name = ConfigureSwaggerOptions.HeaderName, + In = ParameterLocation.Header, + Description = "Informe o token JWT com Bearer no formato: Bearer {token}", + Type = SecuritySchemeType.ApiKey, + BearerFormat = ConfigureSwaggerOptions.AuthenticationScheme, + Scheme = JwtBearerDefaults.AuthenticationScheme + }); + + options.AddSecurityRequirement(new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = JwtBearerDefaults.AuthenticationScheme + } + }, + new string[]{} + } + }); } private static OpenApiInfo CreateInfoForApiVersion(ApiVersionDescription description) diff --git a/src/DEPLOY.Cachorro.Api/Program.cs b/src/DEPLOY.Cachorro.Api/Program.cs index bba595c..b94759b 100644 --- a/src/DEPLOY.Cachorro.Api/Program.cs +++ b/src/DEPLOY.Cachorro.Api/Program.cs @@ -3,6 +3,8 @@ using DEPLOY.Cachorro.Api.Extensions.KeyVault; using DEPLOY.Cachorro.Api.Extensions.Swagger; using DEPLOY.Cachorro.Api.Extensions.Telemetria; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.Identity.Web; using System.Diagnostics.CodeAnalysis; using System.Text.Json.Serialization; @@ -15,6 +17,9 @@ public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); + builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd")); + builder.Services.AddControllers() .AddJsonOptions(opt => { @@ -34,7 +39,7 @@ public static void Main(string[] args) builder.Logging.AddLogExtension(builder.Configuration); builder.Services.AddDatabaseExtension(builder.Configuration); builder.Services.AddTelemetriaExtension(builder.Configuration); - builder.Services.AddSwaggerExtension(); + builder.Services.AddSwaggerExtension(); builder.Configuration.AddAppConfigurationExtension(builder.Services); var app = builder.Build(); diff --git a/src/DEPLOY.Cachorro.Api/appsettings.json b/src/DEPLOY.Cachorro.Api/appsettings.json index 9dd5923..4d84ab5 100644 --- a/src/DEPLOY.Cachorro.Api/appsettings.json +++ b/src/DEPLOY.Cachorro.Api/appsettings.json @@ -27,5 +27,10 @@ "maxDelay": 2, "maxRetries": 10 } + }, + "AzureAd": { + "Instance": "", + "ClientId": "", + "TenantId": "" } -} \ No newline at end of file +} From 179184fe8ac3b2f88762ed58d150b0406456a6f6 Mon Sep 17 00:00:00 2001 From: Felipe Augusto Date: Wed, 17 Jan 2024 10:05:01 -0300 Subject: [PATCH 2/3] feat: Auth using Microsoft Entra ID --- src/DEPLOY.Cachorro.Api/Program.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/DEPLOY.Cachorro.Api/Program.cs b/src/DEPLOY.Cachorro.Api/Program.cs index b94759b..2144d6b 100644 --- a/src/DEPLOY.Cachorro.Api/Program.cs +++ b/src/DEPLOY.Cachorro.Api/Program.cs @@ -49,6 +49,7 @@ public static void Main(string[] args) app.UseHttpsRedirection(); + app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); From d50a5a88bd7bcad745925b50834f6a9cfb9c309a Mon Sep 17 00:00:00 2001 From: Felipe Augusto Date: Fri, 26 Jan 2024 06:49:13 -0300 Subject: [PATCH 3/3] feat: update code and docs --- README.md | 27 +++++++++++++++++++ .../Extensions/Auth/AuthExtension.cs | 20 ++++++++++++++ .../Extensions/KeyVault/KeyVaultExtension.cs | 6 ++--- src/DEPLOY.Cachorro.Api/Program.cs | 9 ++++--- 4 files changed, 54 insertions(+), 8 deletions(-) create mode 100644 src/DEPLOY.Cachorro.Api/Extensions/Auth/AuthExtension.cs diff --git a/README.md b/README.md index 58f0102..c898906 100644 --- a/README.md +++ b/README.md @@ -154,6 +154,33 @@ Data Source=127.0.0.1,1433;Initial Catalog=Cachorro;User Id=sa;Password=Abcd1234 ``` +# Azure Entra ID + +``` + +https://learn.microsoft.com/en-us/entra/identity-platform/v2-overview +``` + +``` +https://learn.microsoft.com/en-us/entra/identity-platform/quickstart-register-app +``` + +``` +https://learn.microsoft.com/en-us/entra/identity-platform/scopes-oidc +``` + +``` + +https://learn.microsoft.com/en-us/entra/identity-platform/scenario-protected-web-api-app-configuration?tabs=aspnetcore#bearer-token + +``` + +``` + +https://learn.microsoft.com/en-us/entra/identity-platform/scenario-web-app-sign-user-app-configuration?tabs=aspnet + +``` +


diff --git a/src/DEPLOY.Cachorro.Api/Extensions/Auth/AuthExtension.cs b/src/DEPLOY.Cachorro.Api/Extensions/Auth/AuthExtension.cs new file mode 100644 index 0000000..6fb429a --- /dev/null +++ b/src/DEPLOY.Cachorro.Api/Extensions/Auth/AuthExtension.cs @@ -0,0 +1,20 @@ +using Azure.Identity; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.Extensions.Azure; +using Microsoft.Identity.Web; +using System.Diagnostics.CodeAnalysis; + +namespace DEPLOY.Cachorro.Api.Extensions.Auth +{ + [ExcludeFromCodeCoverage] + public static class AuthExtension + { + public static void AddAuthExtension( + this IServiceCollection services, + IConfiguration configuration) + { + services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddMicrosoftIdentityWebApi(configuration.GetSection("AzureAd")); + } + } +} diff --git a/src/DEPLOY.Cachorro.Api/Extensions/KeyVault/KeyVaultExtension.cs b/src/DEPLOY.Cachorro.Api/Extensions/KeyVault/KeyVaultExtension.cs index ccc6cac..4ce7b51 100644 --- a/src/DEPLOY.Cachorro.Api/Extensions/KeyVault/KeyVaultExtension.cs +++ b/src/DEPLOY.Cachorro.Api/Extensions/KeyVault/KeyVaultExtension.cs @@ -7,8 +7,8 @@ namespace DEPLOY.Cachorro.Api.Extensions.KeyVault [ExcludeFromCodeCoverage] public static class KeyVaultExtension { - public static IServiceCollection AddKeyVaultExtension( - this IServiceCollection services, + public static void AddKeyVaultExtension( + this IServiceCollection services, IConfiguration configuration) { services.AddAzureClients(clientBuilder => @@ -18,8 +18,6 @@ public static IServiceCollection AddKeyVaultExtension( clientBuilder.UseCredential(new DefaultAzureCredential()); }); - - return services; } } } diff --git a/src/DEPLOY.Cachorro.Api/Program.cs b/src/DEPLOY.Cachorro.Api/Program.cs index 2144d6b..732fd77 100644 --- a/src/DEPLOY.Cachorro.Api/Program.cs +++ b/src/DEPLOY.Cachorro.Api/Program.cs @@ -3,8 +3,7 @@ using DEPLOY.Cachorro.Api.Extensions.KeyVault; using DEPLOY.Cachorro.Api.Extensions.Swagger; using DEPLOY.Cachorro.Api.Extensions.Telemetria; -using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.Identity.Web; +using DEPLOY.Cachorro.Api.Extensions.Auth; using System.Diagnostics.CodeAnalysis; using System.Text.Json.Serialization; @@ -17,13 +16,15 @@ public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); - builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) - .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd")); + builder.Services.AddAuthExtension(builder.Configuration); builder.Services.AddControllers() .AddJsonOptions(opt => { opt.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); + opt.JsonSerializerOptions.WriteIndented = true; + opt.JsonSerializerOptions.PropertyNameCaseInsensitive = true; + }); builder.Services.AddRouting(opt =>