@ -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; | namespace WebhookClient; | ||||
public class Settings | |||||
public class WebhookClientOptions | |||||
{ | { | ||||
public string Token { get; set; } | public string Token { get; set; } | ||||
public string IdentityUrl { get; set; } | public string IdentityUrl { get; set; } |