114 lines
4.9 KiB
C#
114 lines
4.9 KiB
C#
// Fix samesite issue when running eShop from docker-compose locally as by default http protocol is being used
|
|
// Refer to https://github.com/dotnet-architecture/eShopOnContainers/issues/1391
|
|
using Yarp.ReverseProxy.Forwarder;
|
|
|
|
internal static class Extensions
|
|
{
|
|
public static void AddHealthChecks(this IServiceCollection services, IConfiguration configuration)
|
|
{
|
|
services.AddHealthChecks()
|
|
.AddUrlGroup(_ => new Uri(configuration["IdentityUrlHC"]), name: "identityapi-check", tags: new string[] { "identityapi" });
|
|
}
|
|
|
|
public static void AddApplicationSevices(this IServiceCollection services, IConfiguration configuration)
|
|
{
|
|
services.Configure<AppSettings>(configuration)
|
|
.AddSession()
|
|
.AddDistributedMemoryCache();
|
|
|
|
if (configuration["DPConnectionString"] is string redisConnection)
|
|
{
|
|
services.AddDataProtection(opts =>
|
|
{
|
|
opts.ApplicationDiscriminator = "eshop.webmvc";
|
|
})
|
|
.PersistKeysToStackExchangeRedis(ConnectionMultiplexer.Connect(redisConnection), "DataProtection-Keys");
|
|
}
|
|
}
|
|
|
|
// Adds all Http client services
|
|
public static void AddHttpClientServices(this IServiceCollection services)
|
|
{
|
|
// Register delegating handlers
|
|
services.AddTransient<HttpClientAuthorizationDelegatingHandler>()
|
|
.AddTransient<HttpClientRequestIdDelegatingHandler>();
|
|
|
|
// Add http client services
|
|
services.AddHttpClient<IBasketService, BasketService>()
|
|
.SetHandlerLifetime(TimeSpan.FromMinutes(5)) //Sample. Default lifetime is 2 minutes
|
|
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>();
|
|
|
|
services.AddHttpClient<ICatalogService, CatalogService>();
|
|
|
|
services.AddHttpClient<IOrderingService, OrderingService>()
|
|
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
|
|
.AddHttpMessageHandler<HttpClientRequestIdDelegatingHandler>();
|
|
|
|
|
|
//add custom application services
|
|
services.AddTransient<IIdentityParser<ApplicationUser>, IdentityParser>();
|
|
}
|
|
|
|
public static void AddAuthenticationServices(this IServiceCollection services, IConfiguration configuration)
|
|
{
|
|
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub");
|
|
|
|
var identityUrl = configuration.GetRequiredValue("IdentityUrl");
|
|
var callBackUrl = configuration.GetRequiredValue("CallBackUrl");
|
|
var sessionCookieLifetime = configuration.GetValue("SessionCookieLifetimeMinutes", 60);
|
|
|
|
// Add Authentication services
|
|
services.AddAuthentication(options =>
|
|
{
|
|
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
|
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
|
|
})
|
|
.AddCookie(options => options.ExpireTimeSpan = TimeSpan.FromMinutes(sessionCookieLifetime))
|
|
.AddOpenIdConnect(options =>
|
|
{
|
|
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
|
options.Authority = identityUrl;
|
|
options.SignedOutRedirectUri = callBackUrl;
|
|
options.ClientId = "mvc";
|
|
options.ClientSecret = "secret";
|
|
options.ResponseType = "code";
|
|
options.SaveTokens = true;
|
|
options.GetClaimsFromUserInfoEndpoint = true;
|
|
options.RequireHttpsMetadata = false;
|
|
options.Scope.Add("openid");
|
|
options.Scope.Add("profile");
|
|
options.Scope.Add("orders");
|
|
options.Scope.Add("basket");
|
|
options.Scope.Add("webshoppingagg");
|
|
options.Scope.Add("orders.signalrhub");
|
|
options.Scope.Add("webhooks");
|
|
});
|
|
}
|
|
|
|
public static IEndpointConventionBuilder MapForwardSignalR(this WebApplication app)
|
|
{
|
|
// Forward the SignalR traffic to the bff
|
|
var destination = app.Configuration.GetRequiredValue("PurchaseUrl");
|
|
var authTransformer = new BffAuthTransfomer();
|
|
var requestConfig = new ForwarderRequestConfig();
|
|
|
|
return app.MapForwarder("/hub/notificationhub/{**any}", destination, requestConfig, authTransformer);
|
|
}
|
|
|
|
private sealed class BffAuthTransfomer : HttpTransformer
|
|
{
|
|
public override async ValueTask TransformRequestAsync(HttpContext httpContext, HttpRequestMessage proxyRequest, string destinationPrefix, CancellationToken cancellationToken)
|
|
{
|
|
// Set the access token as a bearer token for the outgoing request
|
|
var accessToken = await httpContext.GetTokenAsync("access_token");
|
|
|
|
if (accessToken is not null)
|
|
{
|
|
proxyRequest.Headers.Authorization = new("Bearer", accessToken);
|
|
}
|
|
|
|
await base.TransformRequestAsync(httpContext, proxyRequest, destinationPrefix, cancellationToken);
|
|
}
|
|
}
|
|
}
|