2023-05-09 07:05:39 -07:00

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);
}
}
}