@ -1,9 +0,0 @@ | |||
namespace Microsoft.eShopOnContainers.Services.Identity.API | |||
{ | |||
public class AppSettings | |||
{ | |||
public string MvcClient { get; set; } | |||
public bool UseCustomizationData { get; set; } | |||
} | |||
} |
@ -0,0 +1,49 @@ | |||
namespace WebhookClient; | |||
internal static class Extensions | |||
{ | |||
public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) | |||
{ | |||
var identityUrl = configuration.GetValue<string>("IdentityUrl"); | |||
var callBackUrl = configuration.GetValue<string>("CallBackUrl"); | |||
// Add Authentication services | |||
services.AddAuthentication(options => | |||
{ | |||
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; | |||
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; | |||
}) | |||
.AddCookie(setup => setup.ExpireTimeSpan = TimeSpan.FromHours(2)) | |||
.AddOpenIdConnect(options => | |||
{ | |||
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; | |||
options.Authority = identityUrl.ToString(); | |||
options.SignedOutRedirectUri = callBackUrl.ToString(); | |||
options.ClientId = "webhooksclient"; | |||
options.ClientSecret = "secret"; | |||
options.ResponseType = "code"; | |||
options.SaveTokens = true; | |||
options.GetClaimsFromUserInfoEndpoint = true; | |||
options.RequireHttpsMetadata = false; | |||
options.Scope.Add("openid"); | |||
options.Scope.Add("webhooks"); | |||
}); | |||
return services; | |||
} | |||
public static IServiceCollection AddHttpClientServices(this IServiceCollection services, IConfiguration configuration) | |||
{ | |||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); | |||
services.AddTransient<HttpClientAuthorizationDelegatingHandler>(); | |||
services.AddHttpClient("extendedhandlerlifetime").SetHandlerLifetime(Timeout.InfiniteTimeSpan); | |||
//add http client services | |||
services.AddHttpClient("GrantClient") | |||
.SetHandlerLifetime(TimeSpan.FromMinutes(5)) | |||
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>(); | |||
return services; | |||
} | |||
} |
@ -1,6 +1,71 @@ | |||
CreateWebHostBuilder(args).Build().Run(); | |||
var builder = WebApplication.CreateBuilder(args); | |||
builder.Services.AddSession(opt => | |||
{ | |||
opt.Cookie.Name = ".eShopWebhooks.Session"; | |||
}) | |||
.Configure<WebhookClientOptions>(builder.Configuration) | |||
.AddHttpClientServices(builder.Configuration) | |||
.AddCustomAuthentication(builder.Configuration) | |||
.AddTransient<IWebhooksClient, WebhooksClient>() | |||
.AddSingleton<IHooksRepository, InMemoryHooksRepository>() | |||
.AddMvc(); | |||
builder.Services.AddControllers(); | |||
var app = builder.Build(); | |||
IWebHostBuilder CreateWebHostBuilder(string[] args) => | |||
WebHost.CreateDefaultBuilder(args) | |||
.UseStartup<Startup>(); | |||
var pathBase = app.Configuration["PATH_BASE"]; | |||
if (!string.IsNullOrEmpty(pathBase)) | |||
{ | |||
app.UsePathBase(pathBase); | |||
} | |||
if (!app.Environment.IsDevelopment()) | |||
{ | |||
app.UseExceptionHandler("/Error"); | |||
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. | |||
} | |||
app.Map("/check", capp => | |||
{ | |||
capp.Run(async (context) => | |||
{ | |||
if ("OPTIONS".Equals(context.Request.Method, StringComparison.InvariantCultureIgnoreCase)) | |||
{ | |||
var validateToken = bool.TrueString.Equals(builder.Configuration["ValidateToken"], StringComparison.InvariantCultureIgnoreCase); | |||
var header = context.Request.Headers[HeaderNames.WebHookCheckHeader]; | |||
var value = header.FirstOrDefault(); | |||
var tokenToValidate = builder.Configuration["Token"]; | |||
if (!validateToken || value == tokenToValidate) | |||
{ | |||
if (!string.IsNullOrWhiteSpace(tokenToValidate)) | |||
{ | |||
context.Response.Headers.Add(HeaderNames.WebHookCheckHeader, tokenToValidate); | |||
} | |||
context.Response.StatusCode = (int)HttpStatusCode.OK; | |||
} | |||
else | |||
{ | |||
await context.Response.WriteAsync("Invalid token"); | |||
context.Response.StatusCode = (int)HttpStatusCode.BadRequest; | |||
} | |||
} | |||
else | |||
{ | |||
context.Response.StatusCode = (int)HttpStatusCode.BadRequest; | |||
} | |||
}); | |||
}); | |||
// 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 | |||
app.UseCookiePolicy(new CookiePolicyOptions { MinimumSameSitePolicy = SameSiteMode.Lax }); | |||
app.UseStaticFiles(); | |||
app.UseSession(); | |||
app.UseRouting(); | |||
app.UseAuthentication(); | |||
app.UseAuthorization(); | |||
app.MapDefaultControllerRoute(); | |||
app.MapRazorPages(); | |||
await app.RunAsync(); |
@ -1,144 +0,0 @@ | |||
namespace WebhookClient; | |||
public class Startup | |||
{ | |||
public Startup(IConfiguration configuration) | |||
{ | |||
Configuration = configuration; | |||
} | |||
public IConfiguration Configuration { get; } | |||
// This method gets called by the runtime. Use this method to add services to the container. | |||
public void ConfigureServices(IServiceCollection services) | |||
{ | |||
services.AddSession(opt => | |||
{ | |||
opt.Cookie.Name = ".eShopWebhooks.Session"; | |||
}) | |||
.AddConfiguration(Configuration) | |||
.AddHttpClientServices(Configuration) | |||
.AddCustomAuthentication(Configuration) | |||
.AddTransient<IWebhooksClient, WebhooksClient>() | |||
.AddSingleton<IHooksRepository, InMemoryHooksRepository>() | |||
.AddMvc(); | |||
services.AddControllers(); | |||
} | |||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. | |||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) | |||
{ | |||
var pathBase = Configuration["PATH_BASE"]; | |||
if (!string.IsNullOrEmpty(pathBase)) | |||
{ | |||
app.UsePathBase(pathBase); | |||
} | |||
if (!env.IsDevelopment()) | |||
{ | |||
app.UseExceptionHandler("/Error"); | |||
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. | |||
} | |||
app.Map("/check", capp => | |||
{ | |||
capp.Run(async (context) => | |||
{ | |||
if ("OPTIONS".Equals(context.Request.Method, StringComparison.InvariantCultureIgnoreCase)) | |||
{ | |||
var validateToken = bool.TrueString.Equals(Configuration["ValidateToken"], StringComparison.InvariantCultureIgnoreCase); | |||
var header = context.Request.Headers[HeaderNames.WebHookCheckHeader]; | |||
var value = header.FirstOrDefault(); | |||
var tokenToValidate = Configuration["Token"]; | |||
if (!validateToken || value == tokenToValidate) | |||
{ | |||
if (!string.IsNullOrWhiteSpace(tokenToValidate)) | |||
{ | |||
context.Response.Headers.Add(HeaderNames.WebHookCheckHeader, tokenToValidate); | |||
} | |||
context.Response.StatusCode = (int)HttpStatusCode.OK; | |||
} | |||
else | |||
{ | |||
await context.Response.WriteAsync("Invalid token"); | |||
context.Response.StatusCode = (int)HttpStatusCode.BadRequest; | |||
} | |||
} | |||
else | |||
{ | |||
context.Response.StatusCode = (int)HttpStatusCode.BadRequest; | |||
} | |||
}); | |||
}); | |||
// 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 | |||
app.UseCookiePolicy(new CookiePolicyOptions { MinimumSameSitePolicy = SameSiteMode.Lax }); | |||
app.UseStaticFiles(); | |||
app.UseSession(); | |||
app.UseRouting(); | |||
app.UseAuthentication(); | |||
app.UseAuthorization(); | |||
app.UseEndpoints(endpoints => | |||
{ | |||
endpoints.MapDefaultControllerRoute(); | |||
endpoints.MapRazorPages(); | |||
}); | |||
} | |||
} | |||
static class ServiceExtensions | |||
{ | |||
public static IServiceCollection AddConfiguration(this IServiceCollection services, IConfiguration configuration) | |||
{ | |||
services.Configure<Settings>(configuration); | |||
return services; | |||
} | |||
public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) | |||
{ | |||
var identityUrl = configuration.GetValue<string>("IdentityUrl"); | |||
var callBackUrl = configuration.GetValue<string>("CallBackUrl"); | |||
// Add Authentication services | |||
services.AddAuthentication(options => | |||
{ | |||
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; | |||
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; | |||
}) | |||
.AddCookie(setup => setup.ExpireTimeSpan = TimeSpan.FromHours(2)) | |||
.AddOpenIdConnect(options => | |||
{ | |||
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; | |||
options.Authority = identityUrl.ToString(); | |||
options.SignedOutRedirectUri = callBackUrl.ToString(); | |||
options.ClientId = "webhooksclient"; | |||
options.ClientSecret = "secret"; | |||
options.ResponseType = "code"; | |||
options.SaveTokens = true; | |||
options.GetClaimsFromUserInfoEndpoint = true; | |||
options.RequireHttpsMetadata = false; | |||
options.Scope.Add("openid"); | |||
options.Scope.Add("webhooks"); | |||
}); | |||
return services; | |||
} | |||
public static IServiceCollection AddHttpClientServices(this IServiceCollection services, IConfiguration configuration) | |||
{ | |||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); | |||
services.AddTransient<HttpClientAuthorizationDelegatingHandler>(); | |||
services.AddHttpClient("extendedhandlerlifetime").SetHandlerLifetime(Timeout.InfiniteTimeSpan); | |||
//add http client services | |||
services.AddHttpClient("GrantClient") | |||
.SetHandlerLifetime(TimeSpan.FromMinutes(5)) | |||
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>(); | |||
return services; | |||
} | |||
} |
@ -1,6 +1,6 @@ | |||
namespace WebhookClient; | |||
public class Settings | |||
public class WebhookClientOptions | |||
{ | |||
public string Token { get; set; } | |||
public string IdentityUrl { get; set; } |