Merge pull request #260 from meysamhadeli/fix/fix-scope-validation-in-apis

fix: Fix scope validation in claims for all endpoints
This commit is contained in:
Meysam Hadeli 2023-05-19 02:44:50 +03:30 committed by GitHub
commit f6639d772f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 52 additions and 25 deletions

View File

@ -20,9 +20,6 @@ public static class ServiceCollectionExtensions
IConfiguration configuration, IConfiguration configuration,
params Assembly[] assemblies) params Assembly[] assemblies)
{ {
// https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/openapi
services.AddEndpointsApiExplorer();
services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>(); services.AddTransient<IConfigureOptions<SwaggerGenOptions>, ConfigureSwaggerOptions>();
services.AddOptions<SwaggerOptions>().Bind(configuration.GetSection(nameof(SwaggerOptions))) services.AddOptions<SwaggerOptions>().Bind(configuration.GetSection(nameof(SwaggerOptions)))
.ValidateDataAnnotations(); .ValidateDataAnnotations();
@ -41,20 +38,30 @@ public static class ServiceCollectionExtensions
options.AddEnumsWithValuesFixFilters(); options.AddEnumsWithValuesFixFilters();
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
BearerFormat = "JWT",
Scheme = "oauth2",
Name = "Bearer",
In = ParameterLocation.Header
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement options.AddSecurityRequirement(new OpenApiSecurityRequirement
{ {
{ {
new OpenApiSecurityScheme new OpenApiSecurityScheme
{ {
Reference = new OpenApiReference {Type = ReferenceType.SecurityScheme, Id = "Bearer"}, Reference = new OpenApiReference
Scheme = "oauth2", {
Name = "Bearer", Type=ReferenceType.SecurityScheme,
In = ParameterLocation.Header Id="Bearer"
}
}, },
new List<string>() new string[]{}
} }
}); });
options.ResolveConflictingActions(apiDescriptions => apiDescriptions.First()); options.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
////https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/467 ////https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/467
@ -65,7 +72,7 @@ public static class ServiceCollectionExtensions
// options.EnableAnnotations(); // options.EnableAnnotations();
}); });
services.Configure<SwaggerGeneratorOptions>(o => o.InferSecuritySchemes = true); // services.Configure<SwaggerGeneratorOptions>(o => o.InferSecuritySchemes = true);
static string XmlCommentsFilePath(Assembly assembly) static string XmlCommentsFilePath(Assembly assembly)
{ {

View File

@ -60,7 +60,9 @@ public class TestFixture<TEntryPoint> : IAsyncLifetime
var claims = var claims =
new Dictionary<string, object> new Dictionary<string, object>
{ {
{ ClaimTypes.Name, "test@sample.com" }, { ClaimTypes.Role, "admin" }, { ClaimTypes.Name, "test@sample.com" },
{ ClaimTypes.Role, "admin" },
{"scope", "flight-api"}
}; };
var httpClient = _factory?.CreateClient(); var httpClient = _factory?.CreateClient();
httpClient.SetFakeBearerToken(claims); httpClient.SetFakeBearerToken(claims);

View File

@ -7,6 +7,7 @@ using BuildingBlocks.Core.Event;
using BuildingBlocks.Core.Model; using BuildingBlocks.Core.Model;
using BuildingBlocks.EventStoreDB.Repository; using BuildingBlocks.EventStoreDB.Repository;
using BuildingBlocks.Web; using BuildingBlocks.Web;
using Duende.IdentityServer.EntityFramework.Entities;
using Elasticsearch.Net; using Elasticsearch.Net;
using Exceptions; using Exceptions;
using Flight; using Flight;
@ -50,7 +51,7 @@ public class CreateBookingEndpoint : IMinimalEndpoint
return Results.Ok(response); return Results.Ok(response);
}) })
.RequireAuthorization() .RequireAuthorization(nameof(ApiScope))
.WithName("CreateBooking") .WithName("CreateBooking")
.WithApiVersionSet(builder.NewApiVersionSet("Booking").Build()) .WithApiVersionSet(builder.NewApiVersionSet("Booking").Build())
.Produces<CreateBookingResponseDto>() .Produces<CreateBookingResponseDto>()

View File

@ -60,6 +60,7 @@ public static class InfrastructureExtensions
builder.Services.AddPersistMessageProcessor(env); builder.Services.AddPersistMessageProcessor(env);
builder.Services.AddMongoDbContext<BookingReadDbContext>(configuration); builder.Services.AddMongoDbContext<BookingReadDbContext>(configuration);
builder.Services.AddEndpointsApiExplorer();
builder.AddCustomSerilog(env); builder.AddCustomSerilog(env);
builder.Services.AddJwt(); builder.Services.AddJwt();
builder.Services.AddHttpContextAccessor(); builder.Services.AddHttpContextAccessor();

View File

@ -10,6 +10,7 @@ using BuildingBlocks.Web;
using Exceptions; using Exceptions;
using Models; using Models;
using Data; using Data;
using Duende.IdentityServer.EntityFramework.Entities;
using FluentValidation; using FluentValidation;
using MapsterMapper; using MapsterMapper;
using MassTransit; using MassTransit;
@ -50,7 +51,7 @@ public class CreateAircraftEndpoint : IMinimalEndpoint
return Results.Ok(response); return Results.Ok(response);
}) })
.RequireAuthorization() .RequireAuthorization(nameof(ApiScope))
.WithName("CreateAircraft") .WithName("CreateAircraft")
.WithApiVersionSet(builder.NewApiVersionSet("Flight").Build()) .WithApiVersionSet(builder.NewApiVersionSet("Flight").Build())
.Produces<CreateAircraftResponseDto>() .Produces<CreateAircraftResponseDto>()

View File

@ -9,6 +9,7 @@ using BuildingBlocks.Core.Event;
using BuildingBlocks.Web; using BuildingBlocks.Web;
using Exceptions; using Exceptions;
using Data; using Data;
using Duende.IdentityServer.EntityFramework.Entities;
using FluentValidation; using FluentValidation;
using MapsterMapper; using MapsterMapper;
using MassTransit; using MassTransit;
@ -48,7 +49,7 @@ public class CreateAirportEndpoint : IMinimalEndpoint
return Results.Ok(response); return Results.Ok(response);
}) })
.RequireAuthorization() .RequireAuthorization(nameof(ApiScope))
.WithName("CreateAirport") .WithName("CreateAirport")
.WithApiVersionSet(builder.NewApiVersionSet("Flight").Build()) .WithApiVersionSet(builder.NewApiVersionSet("Flight").Build())
.Produces<CreateAirportResponseDto>() .Produces<CreateAirportResponseDto>()

View File

@ -67,6 +67,7 @@ public static class InfrastructureExtensions
builder.Services.AddMongoDbContext<FlightReadDbContext>(configuration); builder.Services.AddMongoDbContext<FlightReadDbContext>(configuration);
builder.Services.AddPersistMessageProcessor(env); builder.Services.AddPersistMessageProcessor(env);
builder.Services.AddEndpointsApiExplorer();
builder.AddCustomSerilog(env); builder.AddCustomSerilog(env);
builder.Services.AddJwt(); builder.Services.AddJwt();
builder.Services.AddCustomSwagger(configuration, typeof(FlightRoot).Assembly); builder.Services.AddCustomSwagger(configuration, typeof(FlightRoot).Assembly);

View File

@ -8,6 +8,7 @@ using BuildingBlocks.Core.CQRS;
using BuildingBlocks.Core.Event; using BuildingBlocks.Core.Event;
using BuildingBlocks.Web; using BuildingBlocks.Web;
using Data; using Data;
using Duende.IdentityServer.EntityFramework.Entities;
using Exceptions; using Exceptions;
using FluentValidation; using FluentValidation;
using MapsterMapper; using MapsterMapper;
@ -54,7 +55,7 @@ public class CreateFlightEndpoint : IMinimalEndpoint
return Results.CreatedAtRoute("GetFlightById", new { id = result.Id }, response); return Results.CreatedAtRoute("GetFlightById", new { id = result.Id }, response);
}) })
.RequireAuthorization() .RequireAuthorization(nameof(ApiScope))
.WithName("CreateFlight") .WithName("CreateFlight")
.WithApiVersionSet(builder.NewApiVersionSet("Flight").Build()) .WithApiVersionSet(builder.NewApiVersionSet("Flight").Build())
.Produces<CreateFlightResponseDto>(StatusCodes.Status201Created) .Produces<CreateFlightResponseDto>(StatusCodes.Status201Created)

View File

@ -8,6 +8,7 @@ using BuildingBlocks.Core.CQRS;
using BuildingBlocks.Core.Event; using BuildingBlocks.Core.Event;
using BuildingBlocks.Web; using BuildingBlocks.Web;
using Data; using Data;
using Duende.IdentityServer.EntityFramework.Entities;
using Exceptions; using Exceptions;
using FluentValidation; using FluentValidation;
using MediatR; using MediatR;
@ -35,7 +36,7 @@ public class DeleteFlightEndpoint : IMinimalEndpoint
return Results.NoContent(); return Results.NoContent();
}) })
.RequireAuthorization() .RequireAuthorization(nameof(ApiScope))
.WithName("DeleteFlight") .WithName("DeleteFlight")
.WithApiVersionSet(builder.NewApiVersionSet("Flight").Build()) .WithApiVersionSet(builder.NewApiVersionSet("Flight").Build())
.Produces(StatusCodes.Status204NoContent) .Produces(StatusCodes.Status204NoContent)

View File

@ -11,6 +11,7 @@ using BuildingBlocks.Core.CQRS;
using BuildingBlocks.Web; using BuildingBlocks.Web;
using Data; using Data;
using Dtos; using Dtos;
using Duende.IdentityServer.EntityFramework.Entities;
using Exceptions; using Exceptions;
using MapsterMapper; using MapsterMapper;
using MediatR; using MediatR;
@ -42,8 +43,7 @@ public class GetAvailableFlightsEndpoint : IMinimalEndpoint
return Results.Ok(response); return Results.Ok(response);
}) })
.WithOpenApi() .RequireAuthorization(nameof(ApiScope))
.RequireAuthorization()
.WithName("GetAvailableFlights") .WithName("GetAvailableFlights")
.WithApiVersionSet(builder.NewApiVersionSet("Flight").Build()) .WithApiVersionSet(builder.NewApiVersionSet("Flight").Build())
.Produces<GetAvailableFlightsResponseDto>() .Produces<GetAvailableFlightsResponseDto>()

View File

@ -8,6 +8,7 @@ using BuildingBlocks.Core.CQRS;
using BuildingBlocks.Web; using BuildingBlocks.Web;
using Data; using Data;
using Dtos; using Dtos;
using Duende.IdentityServer.EntityFramework.Entities;
using Exceptions; using Exceptions;
using FluentValidation; using FluentValidation;
using MapsterMapper; using MapsterMapper;
@ -37,7 +38,7 @@ public class GetFlightByIdEndpoint : IMinimalEndpoint
return Results.Ok(response); return Results.Ok(response);
}) })
.RequireAuthorization() .RequireAuthorization(nameof(ApiScope))
.WithName("GetFlightById") .WithName("GetFlightById")
.WithApiVersionSet(builder.NewApiVersionSet("Flight").Build()) .WithApiVersionSet(builder.NewApiVersionSet("Flight").Build())
.Produces<GetFlightByIdResponseDto>() .Produces<GetFlightByIdResponseDto>()

View File

@ -9,6 +9,7 @@ using BuildingBlocks.Core.CQRS;
using BuildingBlocks.Core.Event; using BuildingBlocks.Core.Event;
using BuildingBlocks.Web; using BuildingBlocks.Web;
using Data; using Data;
using Duende.IdentityServer.EntityFramework.Entities;
using Exceptions; using Exceptions;
using Flight.Flights.Features.CreatingFlight.V1; using Flight.Flights.Features.CreatingFlight.V1;
using FluentValidation; using FluentValidation;
@ -52,7 +53,7 @@ public class UpdateFlightEndpoint : IMinimalEndpoint
return Results.NoContent(); return Results.NoContent();
}) })
.RequireAuthorization() .RequireAuthorization(nameof(ApiScope))
.WithName("UpdateFlight") .WithName("UpdateFlight")
.WithApiVersionSet(builder.NewApiVersionSet("Flight").Build()) .WithApiVersionSet(builder.NewApiVersionSet("Flight").Build())
.Produces(StatusCodes.Status204NoContent) .Produces(StatusCodes.Status204NoContent)

View File

@ -23,6 +23,7 @@ public class RegisterNewUserConsumerHandler : IConsumer<UserCreated>
public Task Consume(ConsumeContext<UserCreated> context) public Task Consume(ConsumeContext<UserCreated> context)
{ {
_logger.LogInformation($"this is a test consumer for {nameof(UserCreated).Underscore()} in {_options.Name}"); _logger.LogInformation($"this is a test consumer for {nameof(UserCreated).Underscore()} in {_options.Name}");
_logger.LogInformation($"we got this message: {context?.Message}");
return Task.CompletedTask; return Task.CompletedTask;
} }
} }

View File

@ -7,6 +7,7 @@ using Ardalis.GuardClauses;
using BuildingBlocks.Core.CQRS; using BuildingBlocks.Core.CQRS;
using BuildingBlocks.Core.Event; using BuildingBlocks.Core.Event;
using BuildingBlocks.Web; using BuildingBlocks.Web;
using Duende.IdentityServer.EntityFramework.Entities;
using Flight.Data; using Flight.Data;
using Flight.Seats.Exceptions; using Flight.Seats.Exceptions;
using Flight.Seats.Models; using Flight.Seats.Models;
@ -40,7 +41,7 @@ public class CreateSeatEndpoint : IMinimalEndpoint
public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder builder) public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder builder)
{ {
builder.MapPost($"{EndpointConfig.BaseApiPath}/flight/seat", CreateSeat) builder.MapPost($"{EndpointConfig.BaseApiPath}/flight/seat", CreateSeat)
.RequireAuthorization() .RequireAuthorization(nameof(ApiScope))
.WithName("CreateSeat") .WithName("CreateSeat")
.WithApiVersionSet(builder.NewApiVersionSet("Flight").Build()) .WithApiVersionSet(builder.NewApiVersionSet("Flight").Build())
.Produces<CreateSeatResponseDto>() .Produces<CreateSeatResponseDto>()

View File

@ -10,6 +10,7 @@ using BuildingBlocks.Core.CQRS;
using BuildingBlocks.Web; using BuildingBlocks.Web;
using Data; using Data;
using Dtos; using Dtos;
using Duende.IdentityServer.EntityFramework.Entities;
using Exceptions; using Exceptions;
using FluentValidation; using FluentValidation;
using MapsterMapper; using MapsterMapper;
@ -30,7 +31,7 @@ public class GetAvailableSeatsEndpoint : IMinimalEndpoint
public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder builder) public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder builder)
{ {
builder.MapGet($"{EndpointConfig.BaseApiPath}/flight/get-available-seats/{{id}}", GetAvailableSeats) builder.MapGet($"{EndpointConfig.BaseApiPath}/flight/get-available-seats/{{id}}", GetAvailableSeats)
.RequireAuthorization() .RequireAuthorization(nameof(ApiScope))
.WithName("GetAvailableSeats") .WithName("GetAvailableSeats")
.WithApiVersionSet(builder.NewApiVersionSet("Flight").Build()) .WithApiVersionSet(builder.NewApiVersionSet("Flight").Build())
.Produces<GetAvailableSeatsResponseDto>() .Produces<GetAvailableSeatsResponseDto>()

View File

@ -8,6 +8,7 @@ using BuildingBlocks.Core.CQRS;
using BuildingBlocks.Core.Event; using BuildingBlocks.Core.Event;
using BuildingBlocks.Web; using BuildingBlocks.Web;
using Data; using Data;
using Duende.IdentityServer.EntityFramework.Entities;
using Exceptions; using Exceptions;
using FluentValidation; using FluentValidation;
using MapsterMapper; using MapsterMapper;
@ -33,7 +34,7 @@ public class ReserveSeatEndpoint : IMinimalEndpoint
public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder builder) public IEndpointRouteBuilder MapEndpoint(IEndpointRouteBuilder builder)
{ {
builder.MapPost($"{EndpointConfig.BaseApiPath}/flight/reserve-seat", ReserveSeat) builder.MapPost($"{EndpointConfig.BaseApiPath}/flight/reserve-seat", ReserveSeat)
.RequireAuthorization() .RequireAuthorization(nameof(ApiScope))
.WithName("ReserveSeat") .WithName("ReserveSeat")
.WithApiVersionSet(builder.NewApiVersionSet("Flight").Build()) .WithApiVersionSet(builder.NewApiVersionSet("Flight").Build())
.Produces<ReserveSeatResponseDto>() .Produces<ReserveSeatResponseDto>()

View File

@ -59,7 +59,7 @@ public static class Config
Constants.StandardScopes.FlightApi, Constants.StandardScopes.FlightApi,
Constants.StandardScopes.PassengerApi, Constants.StandardScopes.PassengerApi,
Constants.StandardScopes.BookingApi, Constants.StandardScopes.BookingApi,
new(Constants.StandardScopes.IdentityApi) Constants.StandardScopes.IdentityApi
} }
} }
}; };

View File

@ -58,6 +58,7 @@ public static class InfrastructureExtensions
})); }));
}); });
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddControllers(); builder.Services.AddControllers();
builder.Services.AddPersistMessageProcessor(env); builder.Services.AddPersistMessageProcessor(env);
builder.Services.AddCustomDbContext<IdentityContext>(); builder.Services.AddCustomDbContext<IdentityContext>();

View File

@ -9,6 +9,7 @@ using BuildingBlocks.Contracts.EventBus.Messages;
using BuildingBlocks.Core; using BuildingBlocks.Core;
using BuildingBlocks.Core.CQRS; using BuildingBlocks.Core.CQRS;
using BuildingBlocks.Web; using BuildingBlocks.Web;
using Duende.IdentityServer.EntityFramework.Entities;
using Exceptions; using Exceptions;
using FluentValidation; using FluentValidation;
using MapsterMapper; using MapsterMapper;

View File

@ -64,6 +64,7 @@ public static class InfrastructureExtensions
builder.AddCustomSerilog(env); builder.AddCustomSerilog(env);
builder.Services.AddJwt(); builder.Services.AddJwt();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddCustomSwagger(configuration, typeof(PassengerRoot).Assembly); builder.Services.AddCustomSwagger(configuration, typeof(PassengerRoot).Assembly);
builder.Services.AddCustomVersioning(); builder.Services.AddCustomVersioning();
builder.Services.AddCustomMediatR(); builder.Services.AddCustomMediatR();

View File

@ -10,6 +10,7 @@ using MapsterMapper;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Data; using Data;
using Dtos; using Dtos;
using Duende.IdentityServer.EntityFramework.Entities;
using MassTransit; using MassTransit;
using MediatR; using MediatR;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
@ -48,7 +49,7 @@ public class CompleteRegisterPassengerEndpoint : IMinimalEndpoint
return Results.Ok(response); return Results.Ok(response);
}) })
.RequireAuthorization() .RequireAuthorization(nameof(ApiScope))
.WithName("CompleteRegisterPassenger") .WithName("CompleteRegisterPassenger")
.WithApiVersionSet(builder.NewApiVersionSet("Passenger").Build()) .WithApiVersionSet(builder.NewApiVersionSet("Passenger").Build())
.Produces<CompleteRegisterPassengerResponseDto>() .Produces<CompleteRegisterPassengerResponseDto>()

View File

@ -7,6 +7,7 @@ using FluentValidation;
using MapsterMapper; using MapsterMapper;
using Ardalis.GuardClauses; using Ardalis.GuardClauses;
using BuildingBlocks.Web; using BuildingBlocks.Web;
using Duende.IdentityServer.EntityFramework.Entities;
using Exceptions; using Exceptions;
using MediatR; using MediatR;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
@ -34,7 +35,7 @@ public class GetPassengerByIdEndpoint : IMinimalEndpoint
return Results.Ok(response); return Results.Ok(response);
}) })
.RequireAuthorization() .RequireAuthorization(nameof(ApiScope))
.WithName("GetPassengerById") .WithName("GetPassengerById")
.WithApiVersionSet(builder.NewApiVersionSet("Passenger").Build()) .WithApiVersionSet(builder.NewApiVersionSet("Passenger").Build())
.Produces<GetPassengerByIdResponseDto>() .Produces<GetPassengerByIdResponseDto>()