Browse Source

More code sharing and clean up WebHooks client

davidfowl/common-services
David Fowler 1 year ago
committed by Reuben Bond
parent
commit
df4eb4c124
7 changed files with 39 additions and 181 deletions
  1. +0
    -44
      src/ApiGateways/Mobile.Bff.Shopping/aggregator/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs
  2. +0
    -40
      src/ApiGateways/Web.Bff.Shopping/aggregator/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs
  3. +12
    -5
      src/Services/Services.Common/HttpClientAuthorizationDelegatingHandler.cs
  4. +1
    -2
      src/Web/WebhookClient/Controllers/WebhooksReceivedController.cs
  5. +16
    -18
      src/Web/WebhookClient/GlobalUsings.cs
  6. +0
    -30
      src/Web/WebhookClient/HttpClientAuthorizationDelegatingHandler.cs
  7. +10
    -42
      src/Web/WebhookClient/Program.cs

+ 0
- 44
src/ApiGateways/Mobile.Bff.Shopping/aggregator/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs View File

@ -1,44 +0,0 @@
namespace Microsoft.eShopOnContainers.Mobile.Shopping.HttpAggregator.Infrastructure;
public class HttpClientAuthorizationDelegatingHandler : DelegatingHandler
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly ILogger<HttpClientAuthorizationDelegatingHandler> _logger;
public HttpClientAuthorizationDelegatingHandler(IHttpContextAccessor httpContextAccessor, ILogger<HttpClientAuthorizationDelegatingHandler> logger)
{
_httpContextAccessor = httpContextAccessor;
_logger = logger;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
request.Version = new System.Version(2, 0);
request.Method = HttpMethod.Get;
var authorizationHeader = _httpContextAccessor.HttpContext
.Request.Headers["Authorization"];
if (!string.IsNullOrEmpty(authorizationHeader))
{
request.Headers.Add("Authorization", new List<string>() { authorizationHeader });
}
var token = await GetToken();
if (token != null)
{
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
}
return await base.SendAsync(request, cancellationToken);
}
async Task<string> GetToken()
{
const string ACCESS_TOKEN = "access_token";
return await _httpContextAccessor.HttpContext
.GetTokenAsync(ACCESS_TOKEN);
}
}

+ 0
- 40
src/ApiGateways/Web.Bff.Shopping/aggregator/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs View File

@ -1,40 +0,0 @@
namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Infrastructure;
public class HttpClientAuthorizationDelegatingHandler
: DelegatingHandler
{
private readonly IHttpContextAccessor _httpContextAccessor;
public HttpClientAuthorizationDelegatingHandler(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var authorizationHeader = _httpContextAccessor.HttpContext
.Request.Headers["Authorization"];
if (!string.IsNullOrWhiteSpace(authorizationHeader))
{
request.Headers.Add("Authorization", new List<string>() { authorizationHeader });
}
var token = await GetTokenAsync();
if (token != null)
{
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
}
return await base.SendAsync(request, cancellationToken);
}
Task<string> GetTokenAsync()
{
const string ACCESS_TOKEN = "access_token";
return _httpContextAccessor.HttpContext
.GetTokenAsync(ACCESS_TOKEN);
}
}

src/Web/WebMVC/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs → src/Services/Services.Common/HttpClientAuthorizationDelegatingHandler.cs View File

@ -1,4 +1,8 @@
namespace WebMVC.Infrastructure;
using System.Net.Http.Headers;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
namespace Services.Common;
public class HttpClientAuthorizationDelegatingHandler public class HttpClientAuthorizationDelegatingHandler
: DelegatingHandler : DelegatingHandler
@ -12,11 +16,14 @@ public class HttpClientAuthorizationDelegatingHandler
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{ {
var accessToken = await _httpContextAccessor.HttpContext.GetTokenAsync("access_token");
if (accessToken is not null)
if (_httpContextAccessor.HttpContext is HttpContext context)
{ {
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var accessToken = await context.GetTokenAsync("access_token");
if (accessToken is not null)
{
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
}
} }
return await base.SendAsync(request, cancellationToken); return await base.SendAsync(request, cancellationToken);

+ 1
- 2
src/Web/WebhookClient/Controllers/WebhooksReceivedController.cs View File

@ -18,8 +18,7 @@ public class WebhooksReceivedController : Controller
[HttpPost] [HttpPost]
public async Task<IActionResult> NewWebhook(WebhookData hook) public async Task<IActionResult> NewWebhook(WebhookData hook)
{ {
var header = Request.Headers[HeaderNames.WebHookCheckHeader];
var token = header.FirstOrDefault();
string token = Request.Headers[HeaderNames.WebHookCheckHeader];
_logger.LogInformation("Received hook with token {Token}. My token is {MyToken}. Token validation is set to {ValidateToken}", token, _options.Token, _options.ValidateToken); _logger.LogInformation("Received hook with token {Token}. My token is {MyToken}. Token validation is set to {ValidateToken}", token, _options.Token, _options.ValidateToken);


+ 16
- 18
src/Web/WebhookClient/GlobalUsings.cs View File

@ -1,26 +1,24 @@
global using Microsoft.AspNetCore.Authentication;
global using System;
global using System.Collections.Generic;
global using System.Linq;
global using System.Net;
global using System.Net.Http;
global using System.Text.Json;
global using System.Threading.Tasks;
global using Microsoft.AspNetCore.Authentication;
global using Microsoft.AspNetCore.Authentication.Cookies; global using Microsoft.AspNetCore.Authentication.Cookies;
global using Microsoft.AspNetCore.Authentication.OpenIdConnect; global using Microsoft.AspNetCore.Authentication.OpenIdConnect;
global using Microsoft.AspNetCore.Authorization; global using Microsoft.AspNetCore.Authorization;
global using Microsoft.AspNetCore.Builder;
global using Microsoft.AspNetCore.Hosting;
global using Microsoft.AspNetCore.Http;
global using Microsoft.AspNetCore.Mvc; global using Microsoft.AspNetCore.Mvc;
global using System.Threading.Tasks;
global using Microsoft.Extensions.Configuration;
global using Microsoft.Extensions.DependencyInjection;
global using Microsoft.Extensions.Hosting;
global using Microsoft.Extensions.Logging; global using Microsoft.Extensions.Logging;
global using Microsoft.Extensions.Options; global using Microsoft.Extensions.Options;
global using System.Linq;
global using WebhookClient.Models;
global using WebhookClient.Services;
global using System;
global using System.Collections.Generic;
global using System.Net.Http;
global using System.Text.Json;
global using Microsoft.AspNetCore.Http;
global using System.Net.Http.Headers;
global using System.Threading;
global using Services.Common; global using Services.Common;
global using Microsoft.AspNetCore.Hosting;
global using WebhookClient; global using WebhookClient;
global using Microsoft.AspNetCore.Builder;
global using Microsoft.Extensions.Configuration;
global using Microsoft.Extensions.DependencyInjection;
global using Microsoft.Extensions.Hosting;
global using System.Net;
global using WebhookClient.Models;
global using WebhookClient.Services;

+ 0
- 30
src/Web/WebhookClient/HttpClientAuthorizationDelegatingHandler.cs View File

@ -1,30 +0,0 @@
namespace WebhookClient;
public class HttpClientAuthorizationDelegatingHandler : DelegatingHandler
{
private readonly IHttpContextAccessor _httpContextAccessor;
public HttpClientAuthorizationDelegatingHandler(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var authorizationHeader = _httpContextAccessor.HttpContext.Request.Headers["Authorization"];
if (!string.IsNullOrEmpty(authorizationHeader))
{
request.Headers.Add("Authorization", new List<string>() { authorizationHeader });
}
var token = await _httpContextAccessor.HttpContext.GetTokenAsync("access_token");
if (token != null)
{
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
}
return await base.SendAsync(request, cancellationToken);
}
}

+ 10
- 42
src/Web/WebhookClient/Program.cs View File

@ -1,57 +1,25 @@
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
builder.AddServiceDefaults(); builder.AddServiceDefaults();
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.Configure<WebhookClientOptions>(builder.Configuration);
builder.Services.AddHttpClientServices(builder.Configuration);
builder.Services.AddCustomAuthentication(builder.Configuration);
builder.Services.AddTransient<IWebhooksClient, WebhooksClient>();
builder.Services.AddSingleton<IHooksRepository, InMemoryHooksRepository>();
builder.Services.AddRazorPages();
builder.Services.AddControllers(); builder.Services.AddControllers();
var app = builder.Build(); var app = builder.Build();
app.UseServiceDefaults(); app.UseServiceDefaults();
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 // 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 // Refer to https://github.com/dotnet-architecture/eShopOnContainers/issues/1391
app.UseCookiePolicy(new CookiePolicyOptions { MinimumSameSitePolicy = SameSiteMode.Lax }); app.UseCookiePolicy(new CookiePolicyOptions { MinimumSameSitePolicy = SameSiteMode.Lax });
app.UseStaticFiles(); app.UseStaticFiles();
app.UseSession();
app.UseAuthentication(); app.UseAuthentication();
app.UseAuthorization(); app.UseAuthorization();
app.MapDefaultControllerRoute(); app.MapDefaultControllerRoute();


Loading…
Cancel
Save