From 688064199d5e229865379c0553a667f23820872d Mon Sep 17 00:00:00 2001 From: Shady Nagy Date: Mon, 27 Jul 2020 15:06:18 +0200 Subject: [PATCH] Docker Fix (#431) * static added to Constants * Docker support for Blazor * GetHttp, PostHttp, ... inside AuthService, Docker working with login, Cookies Configuration temporary disabled * BaseAddress get web uri from Blazor Shared. * cookie options changed to fix docker. * Fixed returnUrl when inserting admin link and navigate without login * Functions not used removed. * AddPolicy using GetWebUrl * Login link removed from NavMenu * Change ConfigureCookieSettings, ConfigureCoreServices and ConfigureWebServices to be IServiceCollection extentions. * GetOriginWebUrl added. * Auto InDocker switch added. * Removed not used using . --- docker-compose.override.yml | 2 + src/BlazorAdmin/Constants.cs | 7 - .../Pages/CatalogItemPage/Delete.razor | 2 +- .../Pages/CatalogItemPage/Details.razor | 2 +- .../Pages/CatalogItemPage/List.razor | 3 +- src/BlazorAdmin/Services/AuthService.cs | 237 +++++++----------- .../Services/CatalogBrandServices/List.cs | 2 +- .../Services/CatalogItemServices/Create.cs | 6 +- .../Services/CatalogItemServices/Delete.cs | 2 +- .../Services/CatalogItemServices/Edit.cs | 6 +- .../Services/CatalogItemServices/GetById.cs | 2 +- .../Services/CatalogItemServices/ListPaged.cs | 2 +- .../Services/CatalogTypeServices/List.cs | 2 +- src/BlazorAdmin/Shared/NavMenu.razor | 6 - src/BlazorAdmin/Shared/RedirectToLogin.razor | 2 +- src/BlazorAdmin/_Imports.razor | 3 +- src/BlazorShared/Authorization/ClaimValue.cs | 6 +- src/BlazorShared/Authorization/Constants.cs | 23 +- src/BlazorShared/Authorization/UserInfo.cs | 5 +- src/PublicApi/Startup.cs | 8 +- .../Identity/Pages/Account/Login.cshtml.cs | 5 +- .../Configuration/ConfigureCookieSettings.cs | 6 +- .../Configuration/ConfigureCoreServices.cs | 4 +- src/Web/Configuration/ConfigureWebServices.cs | 4 +- src/Web/Startup.cs | 40 +-- 25 files changed, 172 insertions(+), 215 deletions(-) delete mode 100644 src/BlazorAdmin/Constants.cs diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 182e085..32b0faa 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -4,6 +4,7 @@ services: environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://+:80 + - DOTNET_RUNNING_IN_CONTAINER=true ports: - "5106:80" volumes: @@ -13,6 +14,7 @@ services: environment: - ASPNETCORE_ENVIRONMENT=Development - ASPNETCORE_URLS=http://+:80 + - DOTNET_RUNNING_IN_CONTAINER=true ports: - "5200:80" volumes: diff --git a/src/BlazorAdmin/Constants.cs b/src/BlazorAdmin/Constants.cs deleted file mode 100644 index 0ff40f7..0000000 --- a/src/BlazorAdmin/Constants.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace BlazorAdmin -{ - public class Constants - { - public const string API_URL = "https://localhost:5099/api/"; - } -} diff --git a/src/BlazorAdmin/Pages/CatalogItemPage/Delete.razor b/src/BlazorAdmin/Pages/CatalogItemPage/Delete.razor index d643167..7104ef6 100644 --- a/src/BlazorAdmin/Pages/CatalogItemPage/Delete.razor +++ b/src/BlazorAdmin/Pages/CatalogItemPage/Delete.razor @@ -23,7 +23,7 @@ {
- +
diff --git a/src/BlazorAdmin/Pages/CatalogItemPage/Details.razor b/src/BlazorAdmin/Pages/CatalogItemPage/Details.razor index 1539ee6..217b0f2 100644 --- a/src/BlazorAdmin/Pages/CatalogItemPage/Details.razor +++ b/src/BlazorAdmin/Pages/CatalogItemPage/Details.razor @@ -26,7 +26,7 @@ {
- +
diff --git a/src/BlazorAdmin/Pages/CatalogItemPage/List.razor b/src/BlazorAdmin/Pages/CatalogItemPage/List.razor index d0de450..f3d7c74 100644 --- a/src/BlazorAdmin/Pages/CatalogItemPage/List.razor +++ b/src/BlazorAdmin/Pages/CatalogItemPage/List.razor @@ -1,7 +1,6 @@ @page "/admin" @attribute [Authorize(Roles = BlazorShared.Authorization.Constants.Roles.ADMINISTRATORS)] @inject AuthService Auth -@using global::BlazorShared.Authorization @inherits BlazorAdmin.Helpers.BlazorComponent @namespace BlazorAdmin.Pages.CatalogItemPage @@ -38,7 +37,7 @@ else { - + @Services.CatalogTypeServices.List.GetTypeName(catalogTypes, item.CatalogTypeId) @Services.CatalogBrandServices.List.GetBrandName(catalogBrands, item.CatalogBrandId) diff --git a/src/BlazorAdmin/Services/AuthService.cs b/src/BlazorAdmin/Services/AuthService.cs index 714ef31..989a9a1 100644 --- a/src/BlazorAdmin/Services/AuthService.cs +++ b/src/BlazorAdmin/Services/AuthService.cs @@ -1,10 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; +using System.Net.Http; using System.Net.Http.Headers; using System.Net.Http.Json; -using System.Security.Claims; using System.Text; using System.Threading.Tasks; using BlazorAdmin.JavaScript; @@ -20,6 +16,12 @@ namespace BlazorAdmin.Services private readonly HttpClient _httpClient; private readonly ILocalStorageService _localStorage; private readonly IJSRuntime _jSRuntime; + + public string ApiUrl => Constants.GetApiUrl(InDocker); + public string WebUrl => Constants.GetWebUrl(InDocker); + + private static bool InDocker { get; set; } + public bool IsLoggedIn { get; set; } public string UserName { get; set; } @@ -30,51 +32,33 @@ namespace BlazorAdmin.Services _jSRuntime = jSRuntime; } - public HttpClient GetHttpClient() + public async Task HttpGet(string uri) { - return _httpClient; + return await _httpClient.GetAsync($"{ApiUrl}{uri}"); } - public async Task LoginWithoutSaveToLocalStorage(AuthRequest user) + public async Task HttpDelete(string uri, int id) { - var jsonContent = new StringContent(JsonConvert.SerializeObject(user), Encoding.UTF8, "application/json"); - var response = await _httpClient.PostAsync($"{Constants.API_URL}authenticate", jsonContent); - var authResponse = new AuthResponse(); - - if (response.IsSuccessStatusCode) - { - authResponse = await DeserializeToAuthResponse(response); - - IsLoggedIn = true; - } - - return authResponse; + return await _httpClient.DeleteAsync($"{ApiUrl}{uri}/{id}"); } - public async Task Login(AuthRequest user) + public async Task HttpPost(string uri, object dataToSend) { - var jsonContent = new StringContent(JsonConvert.SerializeObject(user), Encoding.UTF8, "application/json"); - var response = await _httpClient.PostAsync($"{Constants.API_URL}authenticate", jsonContent); - var authResponse = new AuthResponse(); + var content = ToJson(dataToSend); - if (response.IsSuccessStatusCode) - { - authResponse = await DeserializeToAuthResponse(response); - await SaveTokenInLocalStorage(authResponse); - await SaveUsernameInLocalStorage(authResponse); - await SetAuthorizationHeader(); + return await _httpClient.PostAsync($"{ApiUrl}{uri}", content); + } - UserName = await GetUsername(); - IsLoggedIn = true; - } + public async Task HttpPut(string uri, object dataToSend) + { + var content = ToJson(dataToSend); - return authResponse; + return await _httpClient.PutAsync($"{ApiUrl}{uri}", content); } public async Task Logout() { - await _localStorage.RemoveItemAsync("authToken"); - await _localStorage.RemoveItemAsync("username"); + await DeleteLocalStorage(); await DeleteCookies(); RemoveAuthorizationHeader(); UserName = null; @@ -95,67 +79,11 @@ namespace BlazorAdmin.Services var username = await new Cookies(_jSRuntime).GetCookie("username"); await SaveUsernameInLocalStorage(username); + var inDocker = await new Cookies(_jSRuntime).GetCookie("inDocker"); + await SaveInDockerInLocalStorage(inDocker); + await RefreshLoginInfo(); } - private async Task LogoutIdentityManager() - { - await _httpClient.PostAsync("Identity/Account/Logout", null); - } - - private async Task DeleteCookies() - { - await new Cookies(_jSRuntime).DeleteCookie("token"); - await new Cookies(_jSRuntime).DeleteCookie("username"); - } - - private async Task SetLoginData() - { - IsLoggedIn = !string.IsNullOrEmpty(await GetToken()); - UserName = await GetUsername(); - await SetAuthorizationHeader(); - } - - private async Task DeserializeToAuthResponse(HttpResponseMessage response) - { - var responseContent = await response.Content.ReadAsStringAsync(); - return JsonConvert.DeserializeObject(responseContent); - } - - private async Task SaveTokenInLocalStorage(AuthResponse authResponse) - { - await _localStorage.SetItemAsync("authToken", SaveTokenInLocalStorage(authResponse.Token)); - } - - private async Task SaveTokenInLocalStorage(string token) - { - if (string.IsNullOrEmpty(token)) - { - return; - } - await _localStorage.SetItemAsync("authToken", token); - } - - private void RemoveAuthorizationHeader() - { - if (_httpClient.DefaultRequestHeaders.Contains("Authorization")) - { - _httpClient.DefaultRequestHeaders.Remove("Authorization"); - } - } - - private async Task SaveUsernameInLocalStorage(AuthResponse authResponse) - { - await _localStorage.SetItemAsync("username", SaveUsernameInLocalStorage(authResponse.Username)); - } - - private async Task SaveUsernameInLocalStorage(string username) - { - if (string.IsNullOrEmpty(username)) - { - return; - } - await _localStorage.SetItemAsync("username", username); - } public async Task GetToken() { @@ -175,58 +103,83 @@ namespace BlazorAdmin.Services return username; } + public async Task GetInDocker() + { + return (await _localStorage.GetItemAsync("inDocker")).ToLower() == "true"; + } + + private StringContent ToJson(object obj) + { + return new StringContent(JsonConvert.SerializeObject(obj), Encoding.UTF8, "application/json"); + } + + private async Task LogoutIdentityManager() + { + await _httpClient.PostAsync("Identity/Account/Logout", null); + } + + private async Task DeleteLocalStorage() + { + await _localStorage.RemoveItemAsync("authToken"); + await _localStorage.RemoveItemAsync("username"); + await _localStorage.RemoveItemAsync("inDocker"); + } + + private async Task DeleteCookies() + { + await new Cookies(_jSRuntime).DeleteCookie("token"); + await new Cookies(_jSRuntime).DeleteCookie("username"); + await new Cookies(_jSRuntime).DeleteCookie("inDocker"); + } + + private async Task SetLoginData() + { + IsLoggedIn = !string.IsNullOrEmpty(await GetToken()); + UserName = await GetUsername(); + InDocker = await GetInDocker(); + await SetAuthorizationHeader(); + } + + private void RemoveAuthorizationHeader() + { + if (_httpClient.DefaultRequestHeaders.Contains("Authorization")) + { + _httpClient.DefaultRequestHeaders.Remove("Authorization"); + } + } + + private async Task SaveTokenInLocalStorage(string token) + { + if (string.IsNullOrEmpty(token)) + { + return; + } + await _localStorage.SetItemAsync("authToken", token); + } + + private async Task SaveUsernameInLocalStorage(string username) + { + if (string.IsNullOrEmpty(username)) + { + return; + } + await _localStorage.SetItemAsync("username", username); + } + + private async Task SaveInDockerInLocalStorage(string inDocker) + { + if (string.IsNullOrEmpty(inDocker)) + { + return; + } + await _localStorage.SetItemAsync("inDocker", inDocker); + } + private async Task SetAuthorizationHeader() { var token = await GetToken(); _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); } - public IEnumerable ParseClaimsFromJwt(string jwt) - { - var claims = new List(); - if (string.IsNullOrEmpty(jwt)) - { - return claims; - } - - var payload = jwt.Split('.')[1]; - var jsonBytes = ParseBase64WithoutPadding(payload); - var keyValuePairs = JsonConvert.DeserializeObject>(Encoding.UTF8.GetString(jsonBytes)); - - keyValuePairs.TryGetValue(ClaimTypes.Role, out object roles); - - if (roles != null) - { - if (roles.ToString().Trim().StartsWith("[")) - { - var parsedRoles = JsonConvert.DeserializeObject(roles.ToString()); - - foreach (var parsedRole in parsedRoles) - { - claims.Add(new Claim(ClaimTypes.Role, parsedRole)); - } - } - else - { - claims.Add(new Claim(ClaimTypes.Role, roles.ToString())); - } - - keyValuePairs.Remove(ClaimTypes.Role); - } - - claims.AddRange(keyValuePairs.Select(kvp => new Claim(kvp.Key, kvp.Value.ToString()))); - - return claims; - } - - private byte[] ParseBase64WithoutPadding(string base64) - { - switch (base64.Length % 4) - { - case 2: base64 += "=="; break; - case 3: base64 += "="; break; - } - return Convert.FromBase64String(base64); - } } } diff --git a/src/BlazorAdmin/Services/CatalogBrandServices/List.cs b/src/BlazorAdmin/Services/CatalogBrandServices/List.cs index fc7b7ee..2cc2dec 100644 --- a/src/BlazorAdmin/Services/CatalogBrandServices/List.cs +++ b/src/BlazorAdmin/Services/CatalogBrandServices/List.cs @@ -26,7 +26,7 @@ namespace BlazorAdmin.Services.CatalogBrandServices try { - var result = (await _authService.GetHttpClient().GetAsync($"{Constants.API_URL}catalog-brands")); + var result = await _authService.HttpGet("catalog-brands"); if (result.StatusCode != HttpStatusCode.OK) { return brands; diff --git a/src/BlazorAdmin/Services/CatalogItemServices/Create.cs b/src/BlazorAdmin/Services/CatalogItemServices/Create.cs index c9fe760..67e4abe 100644 --- a/src/BlazorAdmin/Services/CatalogItemServices/Create.cs +++ b/src/BlazorAdmin/Services/CatalogItemServices/Create.cs @@ -1,6 +1,4 @@ using System.Net; -using System.Net.Http; -using System.Text; using System.Threading.Tasks; using Newtonsoft.Json; @@ -19,9 +17,7 @@ namespace BlazorAdmin.Services.CatalogItemServices { var catalogItemResult = new CatalogItem(); - var content = new StringContent(JsonConvert.SerializeObject(catalogItem), Encoding.UTF8, "application/json"); - - var result = await _authService.GetHttpClient().PostAsync($"{Constants.API_URL}catalog-items", content); + var result = await _authService.HttpPost("catalog-items", catalogItem); if (result.StatusCode != HttpStatusCode.OK) { return catalogItemResult; diff --git a/src/BlazorAdmin/Services/CatalogItemServices/Delete.cs b/src/BlazorAdmin/Services/CatalogItemServices/Delete.cs index 4b36204..eb20182 100644 --- a/src/BlazorAdmin/Services/CatalogItemServices/Delete.cs +++ b/src/BlazorAdmin/Services/CatalogItemServices/Delete.cs @@ -17,7 +17,7 @@ namespace BlazorAdmin.Services.CatalogItemServices { var catalogItemResult = string.Empty; - var result = await _authService.GetHttpClient().DeleteAsync($"{Constants.API_URL}catalog-items/{catalogItemId}"); + var result = await _authService.HttpDelete("catalog-items", catalogItemId); if (result.StatusCode != HttpStatusCode.OK) { return catalogItemResult; diff --git a/src/BlazorAdmin/Services/CatalogItemServices/Edit.cs b/src/BlazorAdmin/Services/CatalogItemServices/Edit.cs index 7bf917a..98484f2 100644 --- a/src/BlazorAdmin/Services/CatalogItemServices/Edit.cs +++ b/src/BlazorAdmin/Services/CatalogItemServices/Edit.cs @@ -1,6 +1,4 @@ using System.Net; -using System.Net.Http; -using System.Text; using System.Threading.Tasks; using Newtonsoft.Json; @@ -19,9 +17,7 @@ namespace BlazorAdmin.Services.CatalogItemServices { var catalogItemResult = new CatalogItem(); - var content = new StringContent(JsonConvert.SerializeObject(catalogItem), Encoding.UTF8, "application/json"); - - var result = await _authService.GetHttpClient().PutAsync($"{Constants.API_URL}catalog-items", content); + var result = await _authService.HttpPut("catalog-items", catalogItem); if (result.StatusCode != HttpStatusCode.OK) { return catalogItemResult; diff --git a/src/BlazorAdmin/Services/CatalogItemServices/GetById.cs b/src/BlazorAdmin/Services/CatalogItemServices/GetById.cs index aaf70c8..ee1907a 100644 --- a/src/BlazorAdmin/Services/CatalogItemServices/GetById.cs +++ b/src/BlazorAdmin/Services/CatalogItemServices/GetById.cs @@ -17,7 +17,7 @@ namespace BlazorAdmin.Services.CatalogItemServices { var catalogItemResult = new CatalogItem(); - var result = await _authService.GetHttpClient().GetAsync($"{Constants.API_URL}catalog-items/{catalogItemId}"); + var result = await _authService.HttpGet($"catalog-items/{catalogItemId}"); if (result.StatusCode != HttpStatusCode.OK) { return catalogItemResult; diff --git a/src/BlazorAdmin/Services/CatalogItemServices/ListPaged.cs b/src/BlazorAdmin/Services/CatalogItemServices/ListPaged.cs index 9663168..3db843d 100644 --- a/src/BlazorAdmin/Services/CatalogItemServices/ListPaged.cs +++ b/src/BlazorAdmin/Services/CatalogItemServices/ListPaged.cs @@ -18,7 +18,7 @@ namespace BlazorAdmin.Services.CatalogItemServices { var catalogItems = new List(); - var result = (await _authService.GetHttpClient().GetAsync($"{Constants.API_URL}catalog-items?PageSize={pageSize}")); + var result = await _authService.HttpGet($"catalog-items?PageSize={pageSize}"); if (result.StatusCode != HttpStatusCode.OK) { return catalogItems; diff --git a/src/BlazorAdmin/Services/CatalogTypeServices/List.cs b/src/BlazorAdmin/Services/CatalogTypeServices/List.cs index c5ab999..7512a66 100644 --- a/src/BlazorAdmin/Services/CatalogTypeServices/List.cs +++ b/src/BlazorAdmin/Services/CatalogTypeServices/List.cs @@ -27,7 +27,7 @@ namespace BlazorAdmin.Services.CatalogTypeServices try { - var result = (await _authService.GetHttpClient().GetAsync($"{Constants.API_URL}catalog-types")); + var result = await _authService.HttpGet("catalog-types"); if (result.StatusCode != HttpStatusCode.OK) { return types; diff --git a/src/BlazorAdmin/Shared/NavMenu.razor b/src/BlazorAdmin/Shared/NavMenu.razor index 0688581..129eb57 100644 --- a/src/BlazorAdmin/Shared/NavMenu.razor +++ b/src/BlazorAdmin/Shared/NavMenu.razor @@ -27,12 +27,6 @@ Logout } - else - { - - Login - - } diff --git a/src/BlazorAdmin/Shared/RedirectToLogin.razor b/src/BlazorAdmin/Shared/RedirectToLogin.razor index 8a2ba84..810a66e 100644 --- a/src/BlazorAdmin/Shared/RedirectToLogin.razor +++ b/src/BlazorAdmin/Shared/RedirectToLogin.razor @@ -4,6 +4,6 @@ protected override void OnInitialized() { Navigation.NavigateTo($"Identity/Account/Login?returnUrl=" + - Uri.EscapeDataString(Navigation.Uri)); + $"/{Uri.EscapeDataString(Navigation.ToBaseRelativePath(Navigation.Uri))}"); } } \ No newline at end of file diff --git a/src/BlazorAdmin/_Imports.razor b/src/BlazorAdmin/_Imports.razor index ecad015..cd87be6 100644 --- a/src/BlazorAdmin/_Imports.razor +++ b/src/BlazorAdmin/_Imports.razor @@ -7,11 +7,12 @@ @using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.Components.WebAssembly.Http @using Microsoft.JSInterop +@using Microsoft.Extensions.Logging @using BlazorAdmin @using BlazorAdmin.Shared @using BlazorAdmin.Services @using BlazorAdmin.Services.CatalogBrandServices @using BlazorAdmin.Services.CatalogItemServices @using BlazorAdmin.Services.CatalogTypeServices -@using Microsoft.Extensions.Logging @using BlazorAdmin.JavaScript +@using BlazorShared.Authorization diff --git a/src/BlazorShared/Authorization/ClaimValue.cs b/src/BlazorShared/Authorization/ClaimValue.cs index f2749cf..963da22 100644 --- a/src/BlazorShared/Authorization/ClaimValue.cs +++ b/src/BlazorShared/Authorization/ClaimValue.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace BlazorShared.Authorization +namespace BlazorShared.Authorization { public class ClaimValue { diff --git a/src/BlazorShared/Authorization/Constants.cs b/src/BlazorShared/Authorization/Constants.cs index 59dceb6..b7120fd 100644 --- a/src/BlazorShared/Authorization/Constants.cs +++ b/src/BlazorShared/Authorization/Constants.cs @@ -1,14 +1,25 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace BlazorShared.Authorization +namespace BlazorShared.Authorization { - public class Constants + public static class Constants { public static class Roles { public const string ADMINISTRATORS = "Administrators"; } + public static string GetApiUrl(bool inDocker) => + inDocker ? DOCKER_API_URL : API_URL; + + public static string GetWebUrl(bool inDocker) => + inDocker ? DOCKER_WEB_URL : WEB_URL; + + public static string GetOriginWebUrl(bool inDocker) => + GetWebUrl(inDocker).TrimEnd('/'); + + private const string API_URL = "https://localhost:5099/api/"; + private const string DOCKER_API_URL = "http://localhost:5200/api/"; + + private const string WEB_URL = "https://localhost:44315/"; + private const string DOCKER_WEB_URL = "http://localhost:5106/"; + } } diff --git a/src/BlazorShared/Authorization/UserInfo.cs b/src/BlazorShared/Authorization/UserInfo.cs index d5ea56a..19cbd11 100644 --- a/src/BlazorShared/Authorization/UserInfo.cs +++ b/src/BlazorShared/Authorization/UserInfo.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Security.Claims; -using System.Text; +using System.Collections.Generic; namespace BlazorShared.Authorization { diff --git a/src/PublicApi/Startup.cs b/src/PublicApi/Startup.cs index 7818499..fa47fb0 100644 --- a/src/PublicApi/Startup.cs +++ b/src/PublicApi/Startup.cs @@ -2,9 +2,8 @@ using System; using System.Collections.Generic; using System.Text; using AutoMapper; +using BlazorShared.Authorization; using MediatR; - -using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; @@ -28,6 +27,8 @@ namespace Microsoft.eShopWeb.PublicApi public class Startup { private const string CORS_POLICY = "CorsPolicy"; + public static bool InDocker => Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER") == "true"; + public Startup(IConfiguration configuration) { Configuration = configuration; @@ -128,8 +129,7 @@ namespace Microsoft.eShopWeb.PublicApi { builder.WithOrigins("http://localhost:44319", "https://localhost:44319", - "http://localhost:44315", - "https://localhost:44315"); + Constants.GetOriginWebUrl(InDocker)); builder.AllowAnyMethod(); builder.AllowAnyHeader(); }); diff --git a/src/Web/Areas/Identity/Pages/Account/Login.cshtml.cs b/src/Web/Areas/Identity/Pages/Account/Login.cshtml.cs index 4a357b0..4c775f6 100644 --- a/src/Web/Areas/Identity/Pages/Account/Login.cshtml.cs +++ b/src/Web/Areas/Identity/Pages/Account/Login.cshtml.cs @@ -89,7 +89,7 @@ namespace Microsoft.eShopWeb.Web.Areas.Identity.Pages.Account if (result.Succeeded) { var token = await _tokenClaimsService.GetTokenAsync(Input.Email); - CreateAuthCookie(Input.Email, token); + CreateAuthCookie(Input.Email, token, Startup.InDocker); _logger.LogInformation("User logged in."); await TransferAnonymousBasketToUserAsync(Input.Email); return LocalRedirect(returnUrl); @@ -114,12 +114,13 @@ namespace Microsoft.eShopWeb.Web.Areas.Identity.Pages.Account return Page(); } - private void CreateAuthCookie(string username, string token) + private void CreateAuthCookie(string username, string token, bool inDocker) { var cookieOptions = new CookieOptions(); cookieOptions.Expires = DateTime.Today.AddYears(10); Response.Cookies.Append("token", token, cookieOptions); Response.Cookies.Append("username", username, cookieOptions); + Response.Cookies.Append("inDocker", inDocker.ToString(), cookieOptions); } private async Task TransferAnonymousBasketToUserAsync(string userName) diff --git a/src/Web/Configuration/ConfigureCookieSettings.cs b/src/Web/Configuration/ConfigureCookieSettings.cs index d17f2c5..69515b4 100644 --- a/src/Web/Configuration/ConfigureCookieSettings.cs +++ b/src/Web/Configuration/ConfigureCookieSettings.cs @@ -7,14 +7,14 @@ namespace Microsoft.eShopWeb.Web.Configuration { public static class ConfigureCookieSettings { - public static void Configure(IServiceCollection services) + public static IServiceCollection AddCookieSettings(this IServiceCollection services) { services.Configure(options => { // This lambda determines whether user consent for non-essential cookies is needed for a given request. //TODO need to check that. //options.CheckConsentNeeded = context => true; - options.MinimumSameSitePolicy = SameSiteMode.None; + options.MinimumSameSitePolicy = SameSiteMode.Strict; }); services.ConfigureApplicationCookie(options => { @@ -27,6 +27,8 @@ namespace Microsoft.eShopWeb.Web.Configuration IsEssential = true // required for auth to work without explicit user consent; adjust to suit your privacy policy }; }); + + return services; } } } diff --git a/src/Web/Configuration/ConfigureCoreServices.cs b/src/Web/Configuration/ConfigureCoreServices.cs index 8284297..039e13a 100644 --- a/src/Web/Configuration/ConfigureCoreServices.cs +++ b/src/Web/Configuration/ConfigureCoreServices.cs @@ -10,7 +10,7 @@ namespace Microsoft.eShopWeb.Web.Configuration { public static class ConfigureCoreServices { - public static void Configure(IServiceCollection services, IConfiguration configuration) + public static IServiceCollection AddCoreServices(this IServiceCollection services, IConfiguration configuration) { services.AddScoped(typeof(IAsyncRepository<>), typeof(EfRepository<>)); services.AddScoped(); @@ -19,6 +19,8 @@ namespace Microsoft.eShopWeb.Web.Configuration services.AddSingleton(new UriComposer(configuration.Get())); services.AddScoped(typeof(IAppLogger<>), typeof(LoggerAdapter<>)); services.AddTransient(); + + return services; } } } diff --git a/src/Web/Configuration/ConfigureWebServices.cs b/src/Web/Configuration/ConfigureWebServices.cs index 92da237..87030d5 100644 --- a/src/Web/Configuration/ConfigureWebServices.cs +++ b/src/Web/Configuration/ConfigureWebServices.cs @@ -8,7 +8,7 @@ namespace Microsoft.eShopWeb.Web.Configuration { public static class ConfigureWebServices { - public static void Configure(IServiceCollection services, IConfiguration configuration) + public static IServiceCollection AddWebServices(this IServiceCollection services, IConfiguration configuration) { services.AddMediatR(typeof(BasketViewModelService).Assembly); services.AddScoped(); @@ -16,6 +16,8 @@ namespace Microsoft.eShopWeb.Web.Configuration services.AddScoped(); services.Configure(configuration); services.AddScoped(); + + return services; } } } diff --git a/src/Web/Startup.cs b/src/Web/Startup.cs index 83e9231..f543879 100644 --- a/src/Web/Startup.cs +++ b/src/Web/Startup.cs @@ -15,14 +15,14 @@ using Microsoft.Extensions.Diagnostics.HealthChecks; using Microsoft.Extensions.Hosting; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Net.Http; using System.Net.Mime; using BlazorAdmin.Services; using Blazored.LocalStorage; -using Microsoft.AspNetCore.Components; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.DataProtection; using Microsoft.eShopWeb.ApplicationCore.Interfaces; namespace Microsoft.eShopWeb.Web @@ -30,6 +30,8 @@ namespace Microsoft.eShopWeb.Web public class Startup { private IServiceCollection _services; + public static bool InDocker => Environment.GetEnvironmentVariable("DOTNET_RUNNING_IN_CONTAINER") == "true"; + public Startup(IConfiguration configuration) { Configuration = configuration; @@ -83,7 +85,22 @@ namespace Microsoft.eShopWeb.Web // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { - ConfigureCookieSettings.Configure(services); + services.AddCookieSettings(); + + if (InDocker) + { + services.AddDataProtection() + .SetApplicationName("eshopwebmvc") + .PersistKeysToFileSystem(new DirectoryInfo(@"./")); + } + + services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) + .AddCookie(options => + { + options.Cookie.HttpOnly = true; + options.Cookie.SecurePolicy = CookieSecurePolicy.Always; + options.Cookie.SameSite = SameSiteMode.Lax; + }); services.AddIdentity() .AddDefaultUI() @@ -92,8 +109,8 @@ namespace Microsoft.eShopWeb.Web services.AddScoped(); - ConfigureCoreServices.Configure(services, Configuration); - ConfigureWebServices.Configure(services, Configuration); + services.AddCoreServices(Configuration); + services.AddWebServices(Configuration); // Add memory cache services services.AddMemoryCache(); @@ -124,15 +141,9 @@ namespace Microsoft.eShopWeb.Web }); // Blazor Admin Required Services for Prerendering - services.AddScoped(s => + services.AddScoped(s => new HttpClient { - var navigationManager = s.GetRequiredService(); - return new HttpClient - { - //TODO need to do it well - BaseAddress = new Uri("https://localhost:44315/") - //BaseAddress = new Uri(navigationManager.BaseUri) - }; + BaseAddress = new Uri(BlazorShared.Authorization.Constants.GetWebUrl(InDocker)) }); services.AddBlazoredLocalStorage(); @@ -197,6 +208,7 @@ namespace Microsoft.eShopWeb.Web endpoints.MapFallbackToFile("index.html"); }); } + } } \ No newline at end of file