@ -15,6 +15,7 @@
using Microsoft.AspNetCore.Authentication.JwtBearer ;
using Microsoft.AspNetCore.Authentication.JwtBearer ;
using Microsoft.AspNetCore.Builder ;
using Microsoft.AspNetCore.Builder ;
using Microsoft.AspNetCore.Hosting ;
using Microsoft.AspNetCore.Hosting ;
using Microsoft.AspNetCore.Mvc ;
using Microsoft.Azure.ServiceBus ;
using Microsoft.Azure.ServiceBus ;
using Microsoft.EntityFrameworkCore ;
using Microsoft.EntityFrameworkCore ;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus ;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus ;
@ -47,43 +48,164 @@
public IServiceProvider ConfigureServices ( IServiceCollection services )
public IServiceProvider ConfigureServices ( IServiceCollection services )
{
{
RegisterAppInsights ( services ) ;
services . AddApplicationInsights ( Configuration )
. AddCustomMvc ( )
. AddHealthChecks ( Configuration )
. AddCustomDbContext ( Configuration )
. AddCustomSwagger ( Configuration )
. AddCustomIntegrations ( Configuration )
. AddCustomConfiguration ( Configuration )
. AddEventBus ( Configuration )
. AddCustomAuthentication ( Configuration ) ;
//configure autofac
var container = new ContainerBuilder ( ) ;
container . Populate ( services ) ;
container . RegisterModule ( new MediatorModule ( ) ) ;
container . RegisterModule ( new ApplicationModule ( Configuration [ "ConnectionString" ] ) ) ;
return new AutofacServiceProvider ( container . Build ( ) ) ;
}
public void Configure ( IApplicationBuilder app , ILoggerFactory loggerFactory )
{
loggerFactory . AddAzureWebAppDiagnostics ( ) ;
loggerFactory . AddApplicationInsights ( app . ApplicationServices , LogLevel . Trace ) ;
var pathBase = Configuration [ "PATH_BASE" ] ;
if ( ! string . IsNullOrEmpty ( pathBase ) )
{
loggerFactory . CreateLogger ( "init" ) . LogDebug ( $"Using PATH BASE '{pathBase}'" ) ;
app . UsePathBase ( pathBase ) ;
}
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
app . Map ( "/liveness" , lapp = > lapp . Run ( async ctx = > ctx . Response . StatusCode = 2 0 0 ) ) ;
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
app . UseCors ( "CorsPolicy" ) ;
ConfigureAuth ( app ) ;
app . UseMvcWithDefaultRoute ( ) ;
app . UseSwagger ( )
. UseSwaggerUI ( c = >
{
c . SwaggerEndpoint ( $"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json" , "Ordering.API V1" ) ;
c . OAuthClientId ( "orderingswaggerui" ) ;
c . OAuthAppName ( "Ordering Swagger UI" ) ;
} ) ;
ConfigureEventBus ( app ) ;
}
private void ConfigureEventBus ( IApplicationBuilder app )
{
var eventBus = app . ApplicationServices . GetRequiredService < BuildingBlocks . EventBus . Abstractions . IEventBus > ( ) ;
eventBus . Subscribe < UserCheckoutAcceptedIntegrationEvent , IIntegrationEventHandler < UserCheckoutAcceptedIntegrationEvent > > ( ) ;
eventBus . Subscribe < GracePeriodConfirmedIntegrationEvent , IIntegrationEventHandler < GracePeriodConfirmedIntegrationEvent > > ( ) ;
eventBus . Subscribe < OrderStockConfirmedIntegrationEvent , IIntegrationEventHandler < OrderStockConfirmedIntegrationEvent > > ( ) ;
eventBus . Subscribe < OrderStockRejectedIntegrationEvent , IIntegrationEventHandler < OrderStockRejectedIntegrationEvent > > ( ) ;
eventBus . Subscribe < OrderPaymentFailedIntegrationEvent , IIntegrationEventHandler < OrderPaymentFailedIntegrationEvent > > ( ) ;
eventBus . Subscribe < OrderPaymentSuccededIntegrationEvent , IIntegrationEventHandler < OrderPaymentSuccededIntegrationEvent > > ( ) ;
}
protected virtual void ConfigureAuth ( IApplicationBuilder app )
{
if ( Configuration . GetValue < bool > ( "UseLoadTest" ) )
{
app . UseMiddleware < ByPassAuthMiddleware > ( ) ;
}
app . UseAuthentication ( ) ;
}
}
static class CustomExtensionsMethods
{
public static IServiceCollection AddApplicationInsights ( this IServiceCollection services , IConfiguration configuration )
{
services . AddApplicationInsightsTelemetry ( configuration ) ;
var orchestratorType = configuration . GetValue < string > ( "OrchestratorType" ) ;
if ( orchestratorType ? . ToUpper ( ) = = "K8S" )
{
// Enable K8s telemetry initializer
services . EnableKubernetes ( ) ;
}
if ( orchestratorType ? . ToUpper ( ) = = "SF" )
{
// Enable SF telemetry initializer
services . AddSingleton < ITelemetryInitializer > ( ( serviceProvider ) = >
new FabricTelemetryInitializer ( ) ) ;
}
return services ;
}
public static IServiceCollection AddCustomMvc ( this IServiceCollection services )
{
// Add framework services.
// Add framework services.
services . AddMvc ( options = >
services . AddMvc ( options = >
{
{
options . Filters . Add ( typeof ( HttpGlobalExceptionFilter ) ) ;
options . Filters . Add ( typeof ( HttpGlobalExceptionFilter ) ) ;
} ) . AddControllersAsServices ( ) ; //Injecting Controllers themselves thru DI
} )
. SetCompatibilityVersion ( CompatibilityVersion . Version_2_1 )
. AddControllersAsServices ( ) ; //Injecting Controllers themselves thru DI
//For further info see: http://docs.autofac.org/en/latest/integration/aspnetcore.html#controllers-as-services
//For further info see: http://docs.autofac.org/en/latest/integration/aspnetcore.html#controllers-as-services
services . AddTransient < IOrderingIntegrationEventService , OrderingIntegrationEventService > ( ) ;
services . AddCors ( options = >
{
options . AddPolicy ( "CorsPolicy" ,
builder = > builder . AllowAnyOrigin ( )
. AllowAnyMethod ( )
. AllowAnyHeader ( )
. AllowCredentials ( ) ) ;
} ) ;
return services ;
}
public static IServiceCollection AddHealthChecks ( this IServiceCollection services , IConfiguration configuration )
{
services . AddHealthChecks ( checks = >
services . AddHealthChecks ( checks = >
{
{
var minutes = 1 ;
var minutes = 1 ;
if ( int . TryParse ( Configuration [ "HealthCheck:Timeout" ] , out var minutesParsed ) )
if ( int . TryParse ( c onfiguration[ "HealthCheck:Timeout" ] , out var minutesParsed ) )
{
{
minutes = minutesParsed ;
minutes = minutesParsed ;
}
}
checks . AddSqlCheck ( "OrderingDb" , Configuration [ "ConnectionString" ] , TimeSpan . FromMinutes ( minutes ) ) ;
checks . AddSqlCheck ( "OrderingDb" , c onfiguration[ "ConnectionString" ] , TimeSpan . FromMinutes ( minutes ) ) ;
} ) ;
} ) ;
return services ;
}
public static IServiceCollection AddCustomDbContext ( this IServiceCollection services , IConfiguration configuration )
{
services . AddEntityFrameworkSqlServer ( )
services . AddEntityFrameworkSqlServer ( )
. AddDbContext < OrderingContext > ( options = >
{
options . UseSqlServer ( Configuration [ "ConnectionString" ] ,
sqlServerOptionsAction : sqlOptions = >
{
sqlOptions . MigrationsAssembly ( typeof ( Startup ) . GetTypeInfo ( ) . Assembly . GetName ( ) . Name ) ;
sqlOptions . EnableRetryOnFailure ( maxRetryCount : 1 0 , maxRetryDelay : TimeSpan . FromSeconds ( 3 0 ) , errorNumbersToAdd : null ) ;
} ) ;
} ,
ServiceLifetime . Scoped //Showing explicitly that the DbContext is shared across the HTTP request scope (graph of objects started in the HTTP request)
) ;
. AddDbContext < OrderingContext > ( options = >
{
options . UseSqlServer ( c onfiguration[ "ConnectionString" ] ,
sqlServerOptionsAction : sqlOptions = >
{
sqlOptions . MigrationsAssembly ( typeof ( Startup ) . GetTypeInfo ( ) . Assembly . GetName ( ) . Name ) ;
sqlOptions . EnableRetryOnFailure ( maxRetryCount : 1 0 , maxRetryDelay : TimeSpan . FromSeconds ( 3 0 ) , errorNumbersToAdd : null ) ;
} ) ;
} ,
ServiceLifetime . Scoped //Showing explicitly that the DbContext is shared across the HTTP request scope (graph of objects started in the HTTP request)
) ;
services . AddDbContext < IntegrationEventLogContext > ( options = >
services . AddDbContext < IntegrationEventLogContext > ( options = >
{
{
options . UseSqlServer ( Configuration [ "ConnectionString" ] ,
options . UseSqlServer ( c onfiguration[ "ConnectionString" ] ,
sqlServerOptionsAction : sqlOptions = >
sqlServerOptionsAction : sqlOptions = >
{
{
sqlOptions . MigrationsAssembly ( typeof ( Startup ) . GetTypeInfo ( ) . Assembly . GetName ( ) . Name ) ;
sqlOptions . MigrationsAssembly ( typeof ( Startup ) . GetTypeInfo ( ) . Assembly . GetName ( ) . Name ) ;
@ -91,10 +213,12 @@
sqlOptions . EnableRetryOnFailure ( maxRetryCount : 1 0 , maxRetryDelay : TimeSpan . FromSeconds ( 3 0 ) , errorNumbersToAdd : null ) ;
sqlOptions . EnableRetryOnFailure ( maxRetryCount : 1 0 , maxRetryDelay : TimeSpan . FromSeconds ( 3 0 ) , errorNumbersToAdd : null ) ;
} ) ;
} ) ;
} ) ;
} ) ;
services . Configure < OrderingSettings > ( Configuration ) ;
return services ;
}
public static IServiceCollection AddCustomSwagger ( this IServiceCollection services , IConfiguration configuration )
{
services . AddSwaggerGen ( options = >
services . AddSwaggerGen ( options = >
{
{
options . DescribeAllEnumsAsStrings ( ) ;
options . DescribeAllEnumsAsStrings ( ) ;
@ -110,8 +234,8 @@
{
{
Type = "oauth2" ,
Type = "oauth2" ,
Flow = "implicit" ,
Flow = "implicit" ,
AuthorizationUrl = $"{C onfiguration.GetValue<string>(" IdentityUrlExternal ")}/connect/authorize" ,
TokenUrl = $"{C onfiguration.GetValue<string>(" IdentityUrlExternal ")}/connect/token" ,
AuthorizationUrl = $"{c onfiguration.GetValue<string>(" IdentityUrlExternal ")}/connect/authorize" ,
TokenUrl = $"{c onfiguration.GetValue<string>(" IdentityUrlExternal ")}/connect/token" ,
Scopes = new Dictionary < string , string > ( )
Scopes = new Dictionary < string , string > ( )
{
{
{ "orders" , "Ordering API" }
{ "orders" , "Ordering API" }
@ -121,16 +245,11 @@
options . OperationFilter < AuthorizeCheckOperationFilter > ( ) ;
options . OperationFilter < AuthorizeCheckOperationFilter > ( ) ;
} ) ;
} ) ;
services . AddCors ( options = >
{
options . AddPolicy ( "CorsPolicy" ,
builder = > builder . AllowAnyOrigin ( )
. AllowAnyMethod ( )
. AllowAnyHeader ( )
. AllowCredentials ( ) ) ;
} ) ;
return services ;
}
// Add application services.
public static IServiceCollection AddCustomIntegrations ( this IServiceCollection services , IConfiguration configuration )
{
services . AddSingleton < IHttpContextAccessor , HttpContextAccessor > ( ) ;
services . AddSingleton < IHttpContextAccessor , HttpContextAccessor > ( ) ;
services . AddTransient < IIdentityService , IdentityService > ( ) ;
services . AddTransient < IIdentityService , IdentityService > ( ) ;
services . AddTransient < Func < DbConnection , IIntegrationEventLogService > > (
services . AddTransient < Func < DbConnection , IIntegrationEventLogService > > (
@ -138,13 +257,13 @@
services . AddTransient < IOrderingIntegrationEventService , OrderingIntegrationEventService > ( ) ;
services . AddTransient < IOrderingIntegrationEventService , OrderingIntegrationEventService > ( ) ;
if ( C onfiguration. GetValue < bool > ( "AzureServiceBusEnabled" ) )
if ( c onfiguration. GetValue < bool > ( "AzureServiceBusEnabled" ) )
{
{
services . AddSingleton < IServiceBusPersisterConnection > ( sp = >
services . AddSingleton < IServiceBusPersisterConnection > ( sp = >
{
{
var logger = sp . GetRequiredService < ILogger < DefaultServiceBusPersisterConnection > > ( ) ;
var logger = sp . GetRequiredService < ILogger < DefaultServiceBusPersisterConnection > > ( ) ;
var serviceBusConnectionString = C onfiguration[ "EventBusConnection" ] ;
var serviceBusConnectionString = c onfiguration[ "EventBusConnection" ] ;
var serviceBusConnection = new ServiceBusConnectionStringBuilder ( serviceBusConnectionString ) ;
var serviceBusConnection = new ServiceBusConnectionStringBuilder ( serviceBusConnectionString ) ;
return new DefaultServiceBusPersisterConnection ( serviceBusConnection , logger ) ;
return new DefaultServiceBusPersisterConnection ( serviceBusConnection , logger ) ;
@ -159,152 +278,69 @@
var factory = new ConnectionFactory ( )
var factory = new ConnectionFactory ( )
{
{
HostName = C onfiguration[ "EventBusConnection" ]
HostName = c onfiguration[ "EventBusConnection" ]
} ;
} ;
if ( ! string . IsNullOrEmpty ( C onfiguration[ "EventBusUserName" ] ) )
if ( ! string . IsNullOrEmpty ( c onfiguration[ "EventBusUserName" ] ) )
{
{
factory . UserName = C onfiguration[ "EventBusUserName" ] ;
factory . UserName = c onfiguration[ "EventBusUserName" ] ;
}
}
if ( ! string . IsNullOrEmpty ( C onfiguration[ "EventBusPassword" ] ) )
if ( ! string . IsNullOrEmpty ( c onfiguration[ "EventBusPassword" ] ) )
{
{
factory . Password = C onfiguration[ "EventBusPassword" ] ;
factory . Password = c onfiguration[ "EventBusPassword" ] ;
}
}
var retryCount = 5 ;
var retryCount = 5 ;
if ( ! string . IsNullOrEmpty ( C onfiguration[ "EventBusRetryCount" ] ) )
if ( ! string . IsNullOrEmpty ( c onfiguration[ "EventBusRetryCount" ] ) )
{
{
retryCount = int . Parse ( C onfiguration[ "EventBusRetryCount" ] ) ;
retryCount = int . Parse ( c onfiguration[ "EventBusRetryCount" ] ) ;
}
}
return new DefaultRabbitMQPersistentConnection ( factory , logger , retryCount ) ;
return new DefaultRabbitMQPersistentConnection ( factory , logger , retryCount ) ;
} ) ;
} ) ;
}
}
RegisterEventBus ( services ) ;
ConfigureAuthService ( services ) ;
services . AddOptions ( ) ;
//configure autofac
var container = new ContainerBuilder ( ) ;
container . Populate ( services ) ;
container . RegisterModule ( new MediatorModule ( ) ) ;
container . RegisterModule ( new ApplicationModule ( Configuration [ "ConnectionString" ] ) ) ;
return new AutofacServiceProvider ( container . Build ( ) ) ;
}
public void Configure ( IApplicationBuilder app , ILoggerFactory loggerFactory )
{
loggerFactory . AddConsole ( Configuration . GetSection ( "Logging" ) ) ;
loggerFactory . AddDebug ( ) ;
loggerFactory . AddAzureWebAppDiagnostics ( ) ;
loggerFactory . AddApplicationInsights ( app . ApplicationServices , LogLevel . Trace ) ;
var pathBase = Configuration [ "PATH_BASE" ] ;
if ( ! string . IsNullOrEmpty ( pathBase ) )
{
loggerFactory . CreateLogger ( "init" ) . LogDebug ( $"Using PATH BASE '{pathBase}'" ) ;
app . UsePathBase ( pathBase ) ;
}
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
app . Map ( "/liveness" , lapp = > lapp . Run ( async ctx = > ctx . Response . StatusCode = 2 0 0 ) ) ;
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
app . UseCors ( "CorsPolicy" ) ;
ConfigureAuth ( app ) ;
app . UseMvcWithDefaultRoute ( ) ;
app . UseSwagger ( )
. UseSwaggerUI ( c = >
{
c . SwaggerEndpoint ( $"{ (!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty) }/swagger/v1/swagger.json" , "Ordering.API V1" ) ;
c . OAuthClientId ( "orderingswaggerui" ) ;
c . OAuthAppName ( "Ordering Swagger UI" ) ;
} ) ;
ConfigureEventBus ( app ) ;
}
private void RegisterAppInsights ( IServiceCollection services )
{
services . AddApplicationInsightsTelemetry ( Configuration ) ;
var orchestratorType = Configuration . GetValue < string > ( "OrchestratorType" ) ;
if ( orchestratorType ? . ToUpper ( ) = = "K8S" )
{
// Enable K8s telemetry initializer
services . EnableKubernetes ( ) ;
}
if ( orchestratorType ? . ToUpper ( ) = = "SF" )
{
// Enable SF telemetry initializer
services . AddSingleton < ITelemetryInitializer > ( ( serviceProvider ) = >
new FabricTelemetryInitializer ( ) ) ;
}
return services ;
}
}
private void ConfigureEventBus ( IApplicationBuilder app )
public static IServiceCollection AddCustomConfiguration ( this IServiceCollection services , IConfiguration configuration )
{
{
var eventBus = app . ApplicationServices . GetRequiredService < BuildingBlocks . EventBus . Abstractions . IEventBus > ( ) ;
eventBus . Subscribe < UserCheckoutAcceptedIntegrationEvent , IIntegrationEventHandler < UserCheckoutAcceptedIntegrationEvent > > ( ) ;
eventBus . Subscribe < GracePeriodConfirmedIntegrationEvent , IIntegrationEventHandler < GracePeriodConfirmedIntegrationEvent > > ( ) ;
eventBus . Subscribe < OrderStockConfirmedIntegrationEvent , IIntegrationEventHandler < OrderStockConfirmedIntegrationEvent > > ( ) ;
eventBus . Subscribe < OrderStockRejectedIntegrationEvent , IIntegrationEventHandler < OrderStockRejectedIntegrationEvent > > ( ) ;
eventBus . Subscribe < OrderPaymentFailedIntegrationEvent , IIntegrationEventHandler < OrderPaymentFailedIntegrationEvent > > ( ) ;
eventBus . Subscribe < OrderPaymentSuccededIntegrationEvent , IIntegrationEventHandler < OrderPaymentSuccededIntegrationEvent > > ( ) ;
}
private void ConfigureAuthService ( IServiceCollection services )
{
// prevent from mapping "sub" claim to nameidentifier.
JwtSecurityTokenHandler . DefaultInboundClaimTypeMap . Remove ( "sub" ) ;
var identityUrl = Configuration . GetValue < string > ( "IdentityUrl" ) ;
services . AddAuthentication ( options = >
services . AddOptions ( ) ;
services . Configure < OrderingSettings > ( configuration ) ;
services . Configure < ApiBehaviorOptions > ( options = >
{
{
options . DefaultAuthenticateScheme = JwtBearerDefaults . AuthenticationScheme ;
options . DefaultChallengeScheme = JwtBearerDefaults . AuthenticationScheme ;
options . InvalidModelStateResponseFactory = context = >
{
var problemDetails = new ValidationProblemDetails ( context . ModelState )
{
Instance = context . HttpContext . Request . Path ,
Status = StatusCodes . Status400BadRequest ,
Detail = "Please refer to the errors property for additional details."
} ;
} ) . AddJwtBearer ( options = >
{
options . Authority = identityUrl ;
options . RequireHttpsMetadata = false ;
options . Audience = "orders" ;
return new BadRequestObjectResult ( problemDetails )
{
ContentTypes = { "application/problem+json" , "application/problem+xml" }
} ;
} ;
} ) ;
} ) ;
}
protected virtual void ConfigureAuth ( IApplicationBuilder app )
{
if ( Configuration . GetValue < bool > ( "UseLoadTest" ) )
{
app . UseMiddleware < ByPassAuthMiddleware > ( ) ;
}
app . UseAuthentication ( ) ;
return services ;
}
}
private void Register EventBus ( IServiceCollection services )
public static IServiceCollection AddEventBus ( this IServiceCollection services , IConfiguration configuration )
{
{
var subscriptionClientName = C onfiguration[ "SubscriptionClientName" ] ;
var subscriptionClientName = configuration [ "SubscriptionClientName" ] ;
if ( C onfiguration. GetValue < bool > ( "AzureServiceBusEnabled" ) )
if ( configuration . GetValue < bool > ( "AzureServiceBusEnabled" ) )
{
{
services . AddSingleton < IEventBus , EventBusServiceBus > ( sp = >
services . AddSingleton < IEventBus , EventBusServiceBus > ( sp = >
{
{
var serviceBusPersisterConnection = sp . GetRequiredService < IServiceBusPersisterConnection > ( ) ;
var serviceBusPersisterConnection = sp . GetRequiredService < IServiceBusPersisterConnection > ( ) ;
var iLifetimeScope = sp . GetRequiredService < ILifetimeScope > ( ) ;
var iLifetimeScope = sp . GetRequiredService < ILifetimeScope > ( ) ;
var logger = sp . GetRequiredService < ILogger < EventBusServiceBus > > ( ) ;
var logger = sp . GetRequiredService < ILogger < EventBusServiceBus > > ( ) ;
var eventBusSubcriptionsManager = sp . GetRequiredService < IEventBusSubscriptionsManager > ( ) ;
var eventBusSubcriptionsManager = sp . GetRequiredService < IEventBusSubscriptionsManager > ( ) ;
return new EventBusServiceBus ( serviceBusPersisterConnection , logger ,
return new EventBusServiceBus ( serviceBusPersisterConnection , logger ,
eventBusSubcriptionsManager , subscriptionClientName , iLifetimeScope ) ;
eventBusSubcriptionsManager , subscriptionClientName , iLifetimeScope ) ;
@ -320,9 +356,9 @@
var eventBusSubcriptionsManager = sp . GetRequiredService < IEventBusSubscriptionsManager > ( ) ;
var eventBusSubcriptionsManager = sp . GetRequiredService < IEventBusSubscriptionsManager > ( ) ;
var retryCount = 5 ;
var retryCount = 5 ;
if ( ! string . IsNullOrEmpty ( C onfiguration[ "EventBusRetryCount" ] ) )
if ( ! string . IsNullOrEmpty ( c onfiguration[ "EventBusRetryCount" ] ) )
{
{
retryCount = int . Parse ( C onfiguration[ "EventBusRetryCount" ] ) ;
retryCount = int . Parse ( c onfiguration[ "EventBusRetryCount" ] ) ;
}
}
return new EventBusRabbitMQ ( rabbitMQPersistentConnection , logger , iLifetimeScope , eventBusSubcriptionsManager , subscriptionClientName , retryCount ) ;
return new EventBusRabbitMQ ( rabbitMQPersistentConnection , logger , iLifetimeScope , eventBusSubcriptionsManager , subscriptionClientName , retryCount ) ;
@ -330,6 +366,30 @@
}
}
services . AddSingleton < IEventBusSubscriptionsManager , InMemoryEventBusSubscriptionsManager > ( ) ;
services . AddSingleton < IEventBusSubscriptionsManager , InMemoryEventBusSubscriptionsManager > ( ) ;
return services ;
}
public static IServiceCollection AddCustomAuthentication ( this IServiceCollection services , IConfiguration configuration )
{
// prevent from mapping "sub" claim to nameidentifier.
JwtSecurityTokenHandler . DefaultInboundClaimTypeMap . Remove ( "sub" ) ;
var identityUrl = configuration . GetValue < string > ( "IdentityUrl" ) ;
services . AddAuthentication ( options = >
{
options . DefaultAuthenticateScheme = JwtBearerDefaults . AuthenticationScheme ;
options . DefaultChallengeScheme = JwtBearerDefaults . AuthenticationScheme ;
} ) . AddJwtBearer ( options = >
{
options . Authority = identityUrl ;
options . RequireHttpsMetadata = false ;
options . Audience = "orders" ;
} ) ;
return services ;
}
}
}
}
}
}