From c82e3385f467e5c74e0bb46025e552e53683b17b Mon Sep 17 00:00:00 2001 From: Vijay Bikka Date: Tue, 24 Dec 2019 00:34:24 -0800 Subject: [PATCH] Add user token to GRPC call. --- .../aggregator/Services/BasketService.cs | 20 +++++++++-- .../aggregator/Services/IIdentityService.cs | 11 +++++++ .../aggregator/Services/IdentityService.cs | 33 +++++++++++++++++++ .../Web.Bff.Shopping/aggregator/Startup.cs | 3 +- .../Basket/Basket.API/Basket.API.csproj | 2 +- .../Controllers/BasketController.cs | 19 +---------- .../Basket/Basket.API/Grpc/BasketService.cs | 31 ++++++++++++++++- .../Basket.API/Services/IdentityService.cs | 2 +- 8 files changed, 96 insertions(+), 25 deletions(-) create mode 100644 src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IIdentityService.cs create mode 100644 src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IdentityService.cs diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/BasketService.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/BasketService.cs index b289e98d6..5d5b7edb8 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/BasketService.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/BasketService.cs @@ -7,6 +7,10 @@ using Grpc.Net.Client; using System.Linq; using GrpcBasket; using System.Net.Http; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Authentication; +using Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Infrastructure; +using System.Net.Http.Headers; namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services { @@ -15,12 +19,14 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services private readonly UrlsConfig _urls; public readonly HttpClient _httpClient; private readonly ILogger _logger; + private readonly IIdentityService _identityService; - public BasketService(HttpClient httpClient, IOptions config, ILogger logger) + public BasketService(HttpClient httpClient, IOptions config, ILogger logger, IIdentityService identityService) { _urls = config.Value; _httpClient = httpClient; _logger = logger; + _identityService = identityService; } @@ -44,9 +50,17 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services var client = new Basket.BasketClient(channel); _logger.LogDebug("Grpc update basket currentBasket {@currentBasket}", currentBasket); var request = MapToCustomerBasketRequest(currentBasket); - _logger.LogDebug("Grpc update basket request {@request}", request); - return await client.UpdateBasketAsync(request); + //Get token from httpcontext and create Authorization header + var token = _identityService.GetUserToken(); + var headers = new Grpc.Core.Metadata + { + { "Authorization", $"Bearer {token.Result}" } + }; + + //Add GRPC Metadata parameter containing authorization attribute to service call. + _logger.LogDebug("Grpc update basket request {@request}", request); + return await client.UpdateBasketAsync(request,headers); }); } diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IIdentityService.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IIdentityService.cs new file mode 100644 index 000000000..07424865f --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IIdentityService.cs @@ -0,0 +1,11 @@ +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services +{ + public interface IIdentityService + { + string GetUserIdentity(); + string GetUserName(); + Task GetUserToken(); + } +} diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IdentityService.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IdentityService.cs new file mode 100644 index 000000000..b85f21f87 --- /dev/null +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Services/IdentityService.cs @@ -0,0 +1,33 @@ +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Http; +using System; +using System.Security.Claims; +using System.Threading.Tasks; + +namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator.Services +{ + public class IdentityService : IIdentityService + { + private IHttpContextAccessor _context; + + public IdentityService(IHttpContextAccessor context) + { + _context = context ?? throw new ArgumentNullException(nameof(context)); + } + + public string GetUserIdentity() + { + return _context.HttpContext.User.FindFirst("sub").Value; + } + + public string GetUserName() + { + return _context.HttpContext.User.FindFirst(x => x.Type == ClaimTypes.Name).Value; + } + + public async Task GetUserToken() + { + return await _context.HttpContext.GetTokenAsync("access_token"); + } + } +} diff --git a/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs b/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs index 27ee6db3e..6b730793e 100644 --- a/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs +++ b/src/ApiGateways/Web.Bff.Shopping/aggregator/Startup.cs @@ -180,6 +180,7 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator //register delegating handlers services.AddTransient(); services.AddSingleton(); + services.AddTransient(); //register http services @@ -197,7 +198,7 @@ namespace Microsoft.eShopOnContainers.Web.Shopping.HttpAggregator services.AddHttpClient() .AddHttpMessageHandler() .AddDevspacesSupport(); - + return services; } diff --git a/src/Services/Basket/Basket.API/Basket.API.csproj b/src/Services/Basket/Basket.API/Basket.API.csproj index 416adeaed..95e31375e 100644 --- a/src/Services/Basket/Basket.API/Basket.API.csproj +++ b/src/Services/Basket/Basket.API/Basket.API.csproj @@ -22,7 +22,7 @@ - + diff --git a/src/Services/Basket/Basket.API/Controllers/BasketController.cs b/src/Services/Basket/Basket.API/Controllers/BasketController.cs index 9eb81c6db..40282819a 100644 --- a/src/Services/Basket/Basket.API/Controllers/BasketController.cs +++ b/src/Services/Basket/Basket.API/Controllers/BasketController.cs @@ -50,24 +50,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Controllers [ProducesResponseType(typeof(CustomerBasket), (int)HttpStatusCode.OK)] public async Task> UpdateBasketAsync([FromBody]CustomerBasket value) { - var basket = await _repository.UpdateBasketAsync(value); - var buyerName = _identityService.GetUserName(); - - var integrationEvent = new UserAddedCatalogItemToBasketIntegrationEvent(buyerName, value.Items.Count); - try - { - _logger.LogInformation("----- Publishing integration event: {IntegrationEventId} from {AppName} - ({@IntegrationEvent})", integrationEvent.Id, Program.AppName, integrationEvent); - - _eventBus.Publish(integrationEvent); - } - catch (Exception ex) - { - _logger.LogError(ex, "ERROR Publishing integration event: {IntegrationEventId} from {AppName}", integrationEvent.Id, Program.AppName); - - throw; - } - - return Ok(basket); + return Ok(await _repository.UpdateBasketAsync(value)); } [Route("checkout")] diff --git a/src/Services/Basket/Basket.API/Grpc/BasketService.cs b/src/Services/Basket/Basket.API/Grpc/BasketService.cs index 830703b59..ec162b815 100644 --- a/src/Services/Basket/Basket.API/Grpc/BasketService.cs +++ b/src/Services/Basket/Basket.API/Grpc/BasketService.cs @@ -5,6 +5,14 @@ using Microsoft.Extensions.Logging; using System.Linq; using System.Threading.Tasks; using GrpcBasket; +using Basket.API.IntegrationEvents.Events; +using System; +using Microsoft.eShopOnContainers.Services.Basket.API.Services; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; +using Microsoft.eShopOnContainers.Services.Basket.API; +using Microsoft.AspNetCore.Http; +using Grpc.AspNetCore.Server.Internal; +using System.Security.Claims; namespace GrpcBasket { @@ -12,11 +20,17 @@ namespace GrpcBasket { private readonly IBasketRepository _repository; private readonly ILogger _logger; + private readonly IIdentityService _identityService; + private readonly IEventBus _eventBus; - public BasketService(IBasketRepository repository, ILogger logger) + public BasketService(IBasketRepository repository, ILogger logger, + IIdentityService identityService, + IEventBus eventBus) { _repository = repository; _logger = logger; + _identityService = identityService; + _eventBus = eventBus; } [AllowAnonymous] @@ -48,6 +62,21 @@ namespace GrpcBasket var response = await _repository.UpdateBasketAsync(customerBasket); + var buyerName = _identityService.GetUserName(); + var integrationEvent = new UserAddedCatalogItemToBasketIntegrationEvent(buyerName, request.Items.Count); + try + { + _logger.LogInformation("----- Publishing integration event: {IntegrationEventId} from {AppName} - ({@IntegrationEvent})", integrationEvent.Id, Program.AppName, integrationEvent); + + _eventBus.Publish(integrationEvent); + } + catch (Exception ex) + { + _logger.LogError(ex, "ERROR Publishing integration event: {IntegrationEventId} from {AppName}", integrationEvent.Id, Program.AppName); + + throw; + } + if (response != null) { return MapToCustomerBasketResponse(response); diff --git a/src/Services/Basket/Basket.API/Services/IdentityService.cs b/src/Services/Basket/Basket.API/Services/IdentityService.cs index 197cd1fce..dcc6218c8 100644 --- a/src/Services/Basket/Basket.API/Services/IdentityService.cs +++ b/src/Services/Basket/Basket.API/Services/IdentityService.cs @@ -21,7 +21,7 @@ namespace Microsoft.eShopOnContainers.Services.Basket.API.Services public string GetUserName() { - return _context.HttpContext.User.FindFirst("preferred_username").Value; + return _context.HttpContext.User.FindFirst(x => x.Type == ClaimTypes.Name).Value; } } }