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/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/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/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..732fd77 100644 --- a/src/DEPLOY.Cachorro.Api/Program.cs +++ b/src/DEPLOY.Cachorro.Api/Program.cs @@ -3,6 +3,7 @@ using DEPLOY.Cachorro.Api.Extensions.KeyVault; using DEPLOY.Cachorro.Api.Extensions.Swagger; using DEPLOY.Cachorro.Api.Extensions.Telemetria; +using DEPLOY.Cachorro.Api.Extensions.Auth; using System.Diagnostics.CodeAnalysis; using System.Text.Json.Serialization; @@ -15,10 +16,15 @@ public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); + 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 => @@ -34,7 +40,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(); @@ -44,6 +50,7 @@ public static void Main(string[] args) app.UseHttpsRedirection(); + app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); 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 +}