diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Weather/WeatherForecast.cs b/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Weather/WeatherForecast.cs deleted file mode 100644 index 9b41fcb66..000000000 --- a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Weather/WeatherForecast.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace BlazorWebAppEntra.Client.Weather; - -public sealed class WeatherForecast(DateOnly date, int temperatureC, string summary) -{ - public DateOnly Date { get; set; } = date; - public int TemperatureC { get; set; } = temperatureC; - public string? Summary { get; set; } = summary; - public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); -} diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.sln b/10.0/BlazorWebAppEntra/BlazorWebAppEntra.sln deleted file mode 100644 index 6a8cf7700..000000000 --- a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.sln +++ /dev/null @@ -1,37 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.12.35323.107 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorWebAppEntra", "BlazorWebAppEntra\BlazorWebAppEntra.csproj", "{ABE4C0A7-8FF0-4FE1-97FD-ED4692324101}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorWebAppEntra.Client", "BlazorWebAppEntra.Client\BlazorWebAppEntra.Client.csproj", "{0E2BE51B-7C55-4CBB-B3E8-7A8EF304C8E2}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MinimalApiJwt", "MinimalApiJwt\MinimalApiJwt.csproj", "{02B2EF75-0ED3-7B54-3753-8E8DD6236369}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {ABE4C0A7-8FF0-4FE1-97FD-ED4692324101}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {ABE4C0A7-8FF0-4FE1-97FD-ED4692324101}.Debug|Any CPU.Build.0 = Debug|Any CPU - {ABE4C0A7-8FF0-4FE1-97FD-ED4692324101}.Release|Any CPU.ActiveCfg = Release|Any CPU - {ABE4C0A7-8FF0-4FE1-97FD-ED4692324101}.Release|Any CPU.Build.0 = Release|Any CPU - {0E2BE51B-7C55-4CBB-B3E8-7A8EF304C8E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0E2BE51B-7C55-4CBB-B3E8-7A8EF304C8E2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0E2BE51B-7C55-4CBB-B3E8-7A8EF304C8E2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0E2BE51B-7C55-4CBB-B3E8-7A8EF304C8E2}.Release|Any CPU.Build.0 = Release|Any CPU - {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Debug|Any CPU.Build.0 = Debug|Any CPU - {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Release|Any CPU.ActiveCfg = Release|Any CPU - {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {74FE9FED-A3AA-4190-B610-C9509637F38E} - EndGlobalSection -EndGlobal diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/LoginLogoutEndpointRouteBuilderExtensions.cs b/10.0/BlazorWebAppEntra/BlazorWebAppEntra/LoginLogoutEndpointRouteBuilderExtensions.cs deleted file mode 100644 index 7e34d6c92..000000000 --- a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/LoginLogoutEndpointRouteBuilderExtensions.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authentication.Cookies; -using Microsoft.AspNetCore.Authentication.OpenIdConnect; -using Microsoft.AspNetCore.Mvc; - -namespace Microsoft.AspNetCore.Routing; - -internal static class LoginLogoutEndpointRouteBuilderExtensions -{ - internal static IEndpointConventionBuilder MapLoginAndLogout(this IEndpointRouteBuilder endpoints) - { - var group = endpoints.MapGroup(string.Empty); - - group.MapGet("/login", (string? returnUrl) => TypedResults.Challenge(GetAuthProperties(returnUrl))) - .AllowAnonymous(); - - // Sign out with both the Cookie and OIDC authentication schemes. Users who have not signed out with the OIDC scheme will - // automatically get signed back in as the same user the next time they visit a page that requires authentication - // with no opportunity to choose another account. - group.MapPost("/logout", ([FromForm] string? returnUrl) => TypedResults.SignOut(GetAuthProperties(returnUrl), - [CookieAuthenticationDefaults.AuthenticationScheme, OpenIdConnectDefaults.AuthenticationScheme])); - - return group; - } - - // Prevent open redirects. Non-empty returnUrls are absolute URIs provided by NavigationManager.Uri. - private static AuthenticationProperties GetAuthProperties(string? returnUrl) => - new() - { - RedirectUri = returnUrl switch - { - string => new Uri(returnUrl, UriKind.Absolute).PathAndQuery, - null => "/", - } - }; -} diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/Properties/launchSettings.json b/10.0/BlazorWebAppEntra/BlazorWebAppEntra/Properties/launchSettings.json deleted file mode 100644 index 1639e4223..000000000 --- a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/Properties/launchSettings.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/launchsettings.json", - "profiles": { - "http": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", - "applicationUrl": "http://localhost:5181", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "https": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", - "applicationUrl": "https://localhost:7062;http://localhost:5181", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } - } diff --git a/10.0/BlazorWebAppEntra/README.md b/10.0/BlazorWebAppEntra/README.md deleted file mode 100644 index d3dbbe080..000000000 --- a/10.0/BlazorWebAppEntra/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# `BlazorWebAppEntra` - -Sample app to accompany [Secure an ASP.NET Core Blazor Web App with Microsoft Entra ID](https://learn.microsoft.com/aspnet/core/blazor/security/blazor-web-app-with-entra?pivots=non-bff-pattern). - -Update the `NSwag.AspNetCore` NuGet package in the `MinimalApiJwt` project to the latest version. - -## Use a production distributed token cache provider - -The sample app uses in-memory distributed token caches, but a production distributed token cache provider is recommended for production apps. For more information, see [Use a production distributed token cache provider](https://learn.microsoft.com/aspnet/core/blazor/security/blazor-web-app-with-entra?pivots=non-bff-pattern#use-a-production-distributed-token-cache-provider). diff --git a/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor b/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor index a7e9ff016..75416a4a1 100644 --- a/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor +++ b/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor @@ -25,18 +25,15 @@ protected override void OnInitialized() { - currentUrl = Navigation.ToBaseRelativePath(Navigation.Uri); + currentUrl = Navigation.Uri; Navigation.LocationChanged += OnLocationChanged; } private void OnLocationChanged(object? sender, LocationChangedEventArgs e) { - currentUrl = Navigation.ToBaseRelativePath(e.Location); + currentUrl = Navigation.Uri; StateHasChanged(); } - public void Dispose() - { - Navigation.LocationChanged -= OnLocationChanged; - } + public void Dispose() => Navigation.LocationChanged -= OnLocationChanged; } diff --git a/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor.css b/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor.css index 52048247f..0a25914e8 100644 --- a/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor.css +++ b/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor.css @@ -19,6 +19,7 @@ .nav-item { font-size: 0.9rem; padding-bottom: 0.5rem; + text-align: left; } .nav-item .nav-link { @@ -29,7 +30,7 @@ height: 3rem; display: flex; align-items: center; - line-height: 3rem; + text-align: left; width: 100%; } diff --git a/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Pages/UserClaims.razor b/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Pages/UserClaims.razor index af9efbaff..a7b94a49d 100644 --- a/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Pages/UserClaims.razor +++ b/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Pages/UserClaims.razor @@ -1,4 +1,4 @@ -@page "/user-claims" +@page "/user-claims" @using System.Security.Claims @using Microsoft.AspNetCore.Authorization @attribute [Authorize] @@ -18,7 +18,7 @@ } @code { - private IEnumerable claims = Enumerable.Empty(); + private IEnumerable claims = []; [CascadingParameter] private Task? AuthState { get; set; } diff --git a/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Pages/Weather.razor b/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Pages/Weather.razor index 0abd39421..a78eb6582 100644 --- a/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Pages/Weather.razor +++ b/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Pages/Weather.razor @@ -10,7 +10,7 @@

This component demonstrates showing data.

-@if (forecasts == null) +@if (Forecasts == null) {

Loading...

} @@ -20,13 +20,13 @@ else Date - Temp. (C) - Temp. (F) + Temp. (C) + Temp. (F) Summary - @foreach (var forecast in forecasts) + @foreach (var forecast in Forecasts) { @forecast.Date.ToShortDateString() @@ -40,10 +40,11 @@ else } @code { - private IEnumerable? forecasts; + [PersistentState] + public IEnumerable? Forecasts { get; set; } protected override async Task OnInitializedAsync() { - forecasts = await WeatherForecaster.GetWeatherForecastAsync(); + Forecasts ??= await WeatherForecaster.GetWeatherForecastAsync(); } } diff --git a/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Weather/IWeatherForecaster.cs b/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Weather/IWeatherForecaster.cs index a2e54a299..5f1b6fd73 100644 --- a/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Weather/IWeatherForecaster.cs +++ b/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Weather/IWeatherForecaster.cs @@ -1,4 +1,3 @@ - namespace BlazorWebAppEntra.Client.Weather; public interface IWeatherForecaster diff --git a/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Weather/WeatherForecast.cs b/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Weather/WeatherForecast.cs index 4ea41a45b..9b41fcb66 100644 --- a/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Weather/WeatherForecast.cs +++ b/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Weather/WeatherForecast.cs @@ -1,9 +1,9 @@ namespace BlazorWebAppEntra.Client.Weather; -public sealed class WeatherForecast +public sealed class WeatherForecast(DateOnly date, int temperatureC, string summary) { - public DateOnly Date { get; set; } - public int TemperatureC { get; set; } - public string? Summary { get; set; } + public DateOnly Date { get; set; } = date; + public int TemperatureC { get; set; } = temperatureC; + public string? Summary { get; set; } = summary; public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); } diff --git a/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.sln b/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.sln index f26e51dc9..6a8cf7700 100644 --- a/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.sln +++ b/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.sln @@ -1,93 +1,37 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 18 -VisualStudioVersion = 18.0.11201.2 d18.0 -MinimumVisualStudioVersion = 16.0.0.0 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorWebAppEntra", "BlazorWebAppEntra\BlazorWebAppEntra.csproj", "{7588C04C-A91C-46AA-A161-6441DDA6D1C8}" +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35323.107 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorWebAppEntra", "BlazorWebAppEntra\BlazorWebAppEntra.csproj", "{ABE4C0A7-8FF0-4FE1-97FD-ED4692324101}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorWebAppEntra.Client", "BlazorWebAppEntra.Client\BlazorWebAppEntra.Client.csproj", "{DCAFB651-B1C8-48F1-AC85-0221F7378DDA}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.AppHost", "Aspire\Aspire.AppHost\Aspire.AppHost.csproj", "{2F6AB681-C3FD-45F3-95C1-0FA9889CDEEA}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.ServiceDefaults", "Aspire\Aspire.ServiceDefaults\Aspire.ServiceDefaults.csproj", "{13E08A9B-6736-4342-BFE7-A951BA3F36DC}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorWebAppEntra.Client", "BlazorWebAppEntra.Client\BlazorWebAppEntra.Client.csproj", "{0E2BE51B-7C55-4CBB-B3E8-7A8EF304C8E2}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MinimalApiJwt", "MinimalApiJwt\MinimalApiJwt.csproj", "{02B2EF75-0ED3-7B54-3753-8E8DD6236369}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {7588C04C-A91C-46AA-A161-6441DDA6D1C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7588C04C-A91C-46AA-A161-6441DDA6D1C8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7588C04C-A91C-46AA-A161-6441DDA6D1C8}.Debug|x64.ActiveCfg = Debug|Any CPU - {7588C04C-A91C-46AA-A161-6441DDA6D1C8}.Debug|x64.Build.0 = Debug|Any CPU - {7588C04C-A91C-46AA-A161-6441DDA6D1C8}.Debug|x86.ActiveCfg = Debug|Any CPU - {7588C04C-A91C-46AA-A161-6441DDA6D1C8}.Debug|x86.Build.0 = Debug|Any CPU - {7588C04C-A91C-46AA-A161-6441DDA6D1C8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7588C04C-A91C-46AA-A161-6441DDA6D1C8}.Release|Any CPU.Build.0 = Release|Any CPU - {7588C04C-A91C-46AA-A161-6441DDA6D1C8}.Release|x64.ActiveCfg = Release|Any CPU - {7588C04C-A91C-46AA-A161-6441DDA6D1C8}.Release|x64.Build.0 = Release|Any CPU - {7588C04C-A91C-46AA-A161-6441DDA6D1C8}.Release|x86.ActiveCfg = Release|Any CPU - {7588C04C-A91C-46AA-A161-6441DDA6D1C8}.Release|x86.Build.0 = Release|Any CPU - {DCAFB651-B1C8-48F1-AC85-0221F7378DDA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DCAFB651-B1C8-48F1-AC85-0221F7378DDA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DCAFB651-B1C8-48F1-AC85-0221F7378DDA}.Debug|x64.ActiveCfg = Debug|Any CPU - {DCAFB651-B1C8-48F1-AC85-0221F7378DDA}.Debug|x64.Build.0 = Debug|Any CPU - {DCAFB651-B1C8-48F1-AC85-0221F7378DDA}.Debug|x86.ActiveCfg = Debug|Any CPU - {DCAFB651-B1C8-48F1-AC85-0221F7378DDA}.Debug|x86.Build.0 = Debug|Any CPU - {DCAFB651-B1C8-48F1-AC85-0221F7378DDA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DCAFB651-B1C8-48F1-AC85-0221F7378DDA}.Release|Any CPU.Build.0 = Release|Any CPU - {DCAFB651-B1C8-48F1-AC85-0221F7378DDA}.Release|x64.ActiveCfg = Release|Any CPU - {DCAFB651-B1C8-48F1-AC85-0221F7378DDA}.Release|x64.Build.0 = Release|Any CPU - {DCAFB651-B1C8-48F1-AC85-0221F7378DDA}.Release|x86.ActiveCfg = Release|Any CPU - {DCAFB651-B1C8-48F1-AC85-0221F7378DDA}.Release|x86.Build.0 = Release|Any CPU - {2F6AB681-C3FD-45F3-95C1-0FA9889CDEEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2F6AB681-C3FD-45F3-95C1-0FA9889CDEEA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2F6AB681-C3FD-45F3-95C1-0FA9889CDEEA}.Debug|x64.ActiveCfg = Debug|Any CPU - {2F6AB681-C3FD-45F3-95C1-0FA9889CDEEA}.Debug|x64.Build.0 = Debug|Any CPU - {2F6AB681-C3FD-45F3-95C1-0FA9889CDEEA}.Debug|x86.ActiveCfg = Debug|Any CPU - {2F6AB681-C3FD-45F3-95C1-0FA9889CDEEA}.Debug|x86.Build.0 = Debug|Any CPU - {2F6AB681-C3FD-45F3-95C1-0FA9889CDEEA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2F6AB681-C3FD-45F3-95C1-0FA9889CDEEA}.Release|Any CPU.Build.0 = Release|Any CPU - {2F6AB681-C3FD-45F3-95C1-0FA9889CDEEA}.Release|x64.ActiveCfg = Release|Any CPU - {2F6AB681-C3FD-45F3-95C1-0FA9889CDEEA}.Release|x64.Build.0 = Release|Any CPU - {2F6AB681-C3FD-45F3-95C1-0FA9889CDEEA}.Release|x86.ActiveCfg = Release|Any CPU - {2F6AB681-C3FD-45F3-95C1-0FA9889CDEEA}.Release|x86.Build.0 = Release|Any CPU - {13E08A9B-6736-4342-BFE7-A951BA3F36DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {13E08A9B-6736-4342-BFE7-A951BA3F36DC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {13E08A9B-6736-4342-BFE7-A951BA3F36DC}.Debug|x64.ActiveCfg = Debug|Any CPU - {13E08A9B-6736-4342-BFE7-A951BA3F36DC}.Debug|x64.Build.0 = Debug|Any CPU - {13E08A9B-6736-4342-BFE7-A951BA3F36DC}.Debug|x86.ActiveCfg = Debug|Any CPU - {13E08A9B-6736-4342-BFE7-A951BA3F36DC}.Debug|x86.Build.0 = Debug|Any CPU - {13E08A9B-6736-4342-BFE7-A951BA3F36DC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {13E08A9B-6736-4342-BFE7-A951BA3F36DC}.Release|Any CPU.Build.0 = Release|Any CPU - {13E08A9B-6736-4342-BFE7-A951BA3F36DC}.Release|x64.ActiveCfg = Release|Any CPU - {13E08A9B-6736-4342-BFE7-A951BA3F36DC}.Release|x64.Build.0 = Release|Any CPU - {13E08A9B-6736-4342-BFE7-A951BA3F36DC}.Release|x86.ActiveCfg = Release|Any CPU - {13E08A9B-6736-4342-BFE7-A951BA3F36DC}.Release|x86.Build.0 = Release|Any CPU + {ABE4C0A7-8FF0-4FE1-97FD-ED4692324101}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ABE4C0A7-8FF0-4FE1-97FD-ED4692324101}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ABE4C0A7-8FF0-4FE1-97FD-ED4692324101}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ABE4C0A7-8FF0-4FE1-97FD-ED4692324101}.Release|Any CPU.Build.0 = Release|Any CPU + {0E2BE51B-7C55-4CBB-B3E8-7A8EF304C8E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0E2BE51B-7C55-4CBB-B3E8-7A8EF304C8E2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0E2BE51B-7C55-4CBB-B3E8-7A8EF304C8E2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0E2BE51B-7C55-4CBB-B3E8-7A8EF304C8E2}.Release|Any CPU.Build.0 = Release|Any CPU {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Debug|Any CPU.Build.0 = Debug|Any CPU - {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Debug|x64.ActiveCfg = Debug|Any CPU - {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Debug|x64.Build.0 = Debug|Any CPU - {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Debug|x86.ActiveCfg = Debug|Any CPU - {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Debug|x86.Build.0 = Debug|Any CPU {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Release|Any CPU.ActiveCfg = Release|Any CPU {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Release|Any CPU.Build.0 = Release|Any CPU - {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Release|x64.ActiveCfg = Release|Any CPU - {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Release|x64.Build.0 = Release|Any CPU - {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Release|x86.ActiveCfg = Release|Any CPU - {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {A7BB58BC-6E37-4456-BCDB-80A7CE694BAD} + SolutionGuid = {74FE9FED-A3AA-4190-B610-C9509637F38E} EndGlobalSection EndGlobal diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.slnLaunch.user b/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.slnLaunch.user similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra.slnLaunch.user rename to 10.0/BlazorWebAppEntraBff/BlazorWebAppEntra.slnLaunch.user diff --git a/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra/BlazorWebAppEntra.csproj b/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra/BlazorWebAppEntra.csproj index 55c11469a..5f6ae37e7 100644 --- a/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra/BlazorWebAppEntra.csproj +++ b/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra/BlazorWebAppEntra.csproj @@ -8,7 +8,6 @@ - @@ -16,8 +15,8 @@ - + diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/BlazorWebAppEntra.http b/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra/BlazorWebAppEntra.http similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/BlazorWebAppEntra.http rename to 10.0/BlazorWebAppEntraBff/BlazorWebAppEntra/BlazorWebAppEntra.http diff --git a/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra/LoginLogoutEndpointRouteBuilderExtensions.cs b/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra/LoginLogoutEndpointRouteBuilderExtensions.cs index df9c1aa88..7e34d6c92 100644 --- a/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra/LoginLogoutEndpointRouteBuilderExtensions.cs +++ b/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra/LoginLogoutEndpointRouteBuilderExtensions.cs @@ -9,39 +9,28 @@ internal static class LoginLogoutEndpointRouteBuilderExtensions { internal static IEndpointConventionBuilder MapLoginAndLogout(this IEndpointRouteBuilder endpoints) { - var group = endpoints.MapGroup(""); + var group = endpoints.MapGroup(string.Empty); group.MapGet("/login", (string? returnUrl) => TypedResults.Challenge(GetAuthProperties(returnUrl))) .AllowAnonymous(); - // Sign out of the Cookie and OIDC handlers. If you do not sign out with the OIDC handler, - // the user will automatically be signed back in the next time they visit a page that requires authentication - // without being able to choose another account. + // Sign out with both the Cookie and OIDC authentication schemes. Users who have not signed out with the OIDC scheme will + // automatically get signed back in as the same user the next time they visit a page that requires authentication + // with no opportunity to choose another account. group.MapPost("/logout", ([FromForm] string? returnUrl) => TypedResults.SignOut(GetAuthProperties(returnUrl), [CookieAuthenticationDefaults.AuthenticationScheme, OpenIdConnectDefaults.AuthenticationScheme])); return group; } - private static AuthenticationProperties GetAuthProperties(string? returnUrl) - { - // TODO: Use HttpContext.Request.PathBase instead. - const string pathBase = "/"; - - // Prevent open redirects. - if (string.IsNullOrEmpty(returnUrl)) - { - returnUrl = pathBase; - } - else if (!Uri.IsWellFormedUriString(returnUrl, UriKind.Relative)) + // Prevent open redirects. Non-empty returnUrls are absolute URIs provided by NavigationManager.Uri. + private static AuthenticationProperties GetAuthProperties(string? returnUrl) => + new() { - returnUrl = new Uri(returnUrl, UriKind.Absolute).PathAndQuery; - } - else if (returnUrl[0] != '/') - { - returnUrl = $"{pathBase}{returnUrl}"; - } - - return new AuthenticationProperties { RedirectUri = returnUrl }; - } + RedirectUri = returnUrl switch + { + string => new Uri(returnUrl, UriKind.Absolute).PathAndQuery, + null => "/", + } + }; } diff --git a/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra/Program.cs b/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra/Program.cs index 85044536a..4752634be 100644 --- a/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra/Program.cs +++ b/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra/Program.cs @@ -1,21 +1,27 @@ +using System.Security.Claims; +using Azure.Core; using Azure.Identity; -using BlazorWebAppEntra; using BlazorWebAppEntra.Client.Weather; using BlazorWebAppEntra.Components; +using BlazorWebAppEntra.Weather; +using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authentication.OpenIdConnect; using Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Azure; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Identity.Web; using Microsoft.Identity.Web.TokenCacheProviders.Distributed; -using Microsoft.IdentityModel.Protocols.OpenIdConnect; -using Yarp.ReverseProxy.Transforms; var builder = WebApplication.CreateBuilder(args); // Add services to the container. -// Add service defaults & Aspire components. -builder.AddServiceDefaults(); +// Remove or set 'SerializeAllClaims' to 'false' if you only want to +// serialize name and role claims for CSR. +builder.Services.AddRazorComponents() + .AddInteractiveServerComponents() + .AddInteractiveWebAssemblyComponents() + .AddAuthenticationStateSerialization(options => options.SerializeAllClaims = true); // Configure authentication to use Microsoft Entra ID builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) @@ -63,14 +69,14 @@ builder.Services.AddDistributedMemoryCache(); builder.Services.Configure( - options => + options => { // Disable L1 Cache default: false //options.DisableL1Cache = false; - + // L1 Cache Size Limit default: 500 MB //options.L1CacheOptions.SizeLimit = 500 * 1024 * 1024; - + // Encrypt tokens at rest default: false options.Encrypt = true; @@ -121,25 +127,8 @@ .ProtectKeysWithAzureKeyVault( new Uri("{KEY IDENTIFIER}"), credential); */ -builder.Services.AddOptions(OpenIdConnectDefaults.AuthenticationScheme).Configure(oidcOptions => -{ - oidcOptions.Scope.Add(OpenIdConnectScope.OfflineAccess); -}); - builder.Services.AddAuthorization(); -builder.Services.AddCascadingAuthenticationState(); - -// Remove or set 'SerializeAllClaims' to 'false' if you only want to -// serialize name and role claims for CSR. -builder.Services.AddRazorComponents() - .AddInteractiveServerComponents() - .AddMicrosoftIdentityConsentHandler() - .AddInteractiveWebAssemblyComponents() - .AddAuthenticationStateSerialization(options => options.SerializeAllClaims = true); - -builder.Services.AddHttpForwarderWithServiceDiscovery(); -builder.Services.AddHttpContextAccessor(); builder.Services.AddScoped(); var app = builder.Build(); @@ -162,24 +151,17 @@ app.MapStaticAssets(); -app.MapDefaultEndpoints(); + +app.MapGet("/weather-forecast", ([FromServices] IWeatherForecaster WeatherForecaster) => +{ + return WeatherForecaster.GetWeatherForecastAsync(); +}).RequireAuthorization(); app.MapRazorComponents() .AddInteractiveServerRenderMode() .AddInteractiveWebAssemblyRenderMode() .AddAdditionalAssemblies(typeof(BlazorWebAppEntra.Client._Imports).Assembly); -app.MapForwarder("/weather-forecast", "https://weatherapi", transformBuilder => -{ - transformBuilder.AddRequestTransform(async transformContext => - { - var tokenAcquisition = transformContext.HttpContext.RequestServices.GetRequiredService(); - List scopes = ["{APP ID URI}/Weather.Get"]; - var accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(scopes); - transformContext.ProxyRequest.Headers.Authorization = new("Bearer", accessToken); - }); -}).RequireAuthorization(); - app.MapGroup("/authentication").MapLoginAndLogout(); app.Run(); diff --git a/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra/Properties/launchSettings.json b/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra/Properties/launchSettings.json index 5a5fcf3f4..1639e4223 100644 --- a/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra/Properties/launchSettings.json +++ b/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra/Properties/launchSettings.json @@ -1,15 +1,25 @@ { - "$schema": "http://json.schemastore.org/launchsettings.json", - "profiles": { - "https": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", - "applicationUrl": "https://localhost:5001;http://localhost:5000", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", + "applicationUrl": "http://localhost:5181", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", + "applicationUrl": "https://localhost:7062;http://localhost:5181", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } } } } -} diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/Weather/ServerWeatherForecaster.cs b/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra/Weather/ServerWeatherForecaster.cs similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/Weather/ServerWeatherForecaster.cs rename to 10.0/BlazorWebAppEntraBff/BlazorWebAppEntra/Weather/ServerWeatherForecaster.cs diff --git a/10.0/BlazorWebAppEntraBff/MinimalApiJwt/MinimalApiJwt.csproj b/10.0/BlazorWebAppEntraBff/MinimalApiJwt/MinimalApiJwt.csproj index b4424c9b5..8150437ba 100644 --- a/10.0/BlazorWebAppEntraBff/MinimalApiJwt/MinimalApiJwt.csproj +++ b/10.0/BlazorWebAppEntraBff/MinimalApiJwt/MinimalApiJwt.csproj @@ -8,7 +8,6 @@ - diff --git a/10.0/BlazorWebAppEntraBff/MinimalApiJwt/Program.cs b/10.0/BlazorWebAppEntraBff/MinimalApiJwt/Program.cs index 5dd55f57b..baaa2668a 100644 --- a/10.0/BlazorWebAppEntraBff/MinimalApiJwt/Program.cs +++ b/10.0/BlazorWebAppEntraBff/MinimalApiJwt/Program.cs @@ -1,12 +1,12 @@ -var builder = WebApplication.CreateBuilder(args); +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.Extensions.Options; -// Add service defaults & Aspire components. -builder.AddServiceDefaults(); +var builder = WebApplication.CreateBuilder(args); builder.Services.AddAuthentication() .AddJwtBearer("Bearer", jwtOptions => { - // {TENANT ID} in the following examples is the directory (tenant) ID. + // {TENANT ID} is the directory (tenant) ID. // // Authority format {AUTHORITY} matches the issurer (`iss`) of the JWT returned by the identity provider. // @@ -15,7 +15,6 @@ // Authority format {AUTHORITY} for B2C tenant type: https://login.microsoftonline.com/{TENANT ID}/v2.0 // jwtOptions.Authority = "{AUTHORITY}"; - // // The following should match just the path of the Application ID URI configured when adding the "Weather.Get" scope // under "Expose an API" in the Azure or Entra portal. {CLIENT ID} is the application (client) ID of this @@ -49,8 +48,6 @@ // Configure the HTTP request pipeline. app.UseHttpsRedirection(); -app.MapDefaultEndpoints(); - var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" diff --git a/10.0/BlazorWebAppEntraBff/README.md b/10.0/BlazorWebAppEntraBff/README.md index 06ebeef3c..f36038581 100644 --- a/10.0/BlazorWebAppEntraBff/README.md +++ b/10.0/BlazorWebAppEntraBff/README.md @@ -1,35 +1,9 @@ -# Blazor Web App with Entra (BFF Pattern) +# Blazor Web App with Entra (without YARP and Aspire) -This sample features: - -* A Blazor Web App with global Auto interactivity. `PersistingAuthenticationStateProvider` and `PersistentAuthenticationStateProvider` services are added to the server and client Blazor apps to capture authentication state and flow it between the server and client. -* Authentication with Microsoft Entra using Microsoft Identity Web packages. -* A minimal API backend using the `JwtBearerHandler` to validate JWT tokens saved by the Blazor app using the in-memory token store for the access token. -* The BFF pattern using Aspire service discovery and YARP for proxying the requests to `/weatherforecast` on the backend using an access token generated for the web API on behalf of the user account for the user's claims. - -## Article for this sample app - -The article for this sample app is [Secure an ASP.NET Core Blazor Web App with Microsoft Entra ID (BFF pattern)](https://learn.microsoft.com/aspnet/core/blazor/security/blazor-web-app-with-entra?pivots=bff-pattern). - -If you need to open an issue that pertains to the coding of the sample app, open [an issue on this samples repo](https://github.com/dotnet/blazor-samples/issues). Otherwise, open an issue using the **Open a documentation issue** link/feedback form at the bottom of [the article](https://learn.microsoft.com/aspnet/core/blazor/security/blazor-web-app-with-entra?pivots=bff-pattern). - -## Configure the sample - -Configure the solution following the guidance in [Secure an ASP.NET Core Blazor Web App with Microsoft Entra ID (BFF pattern)](https://learn.microsoft.com/aspnet/core/blazor/security/blazor-web-app-with-entra?pivots=bff-pattern). - -## Use a production distributed token cache provider - -The sample app uses in-memory distributed token caches, but a production distributed token cache provider is recommended for production apps. For more information, see [Use a production distributed token cache provider](https://learn.microsoft.com/aspnet/core/blazor/security/blazor-web-app-with-entra?pivots=non-bff-pattern#use-a-production-distributed-token-cache-provider). - -## Run the sample +Sample app to accompany [Secure an ASP.NET Core Blazor Web App with Microsoft Entra ID (without YARP/Aspire)](https://learn.microsoft.com/aspnet/core/blazor/security/blazor-web-app-with-entra?pivots=without-yarp-and-aspire). Update the `NSwag.AspNetCore` NuGet package in the `MinimalApiJwt` project to the latest version. -### Visual Studio - -1. Open the `BlazorWebAppEntra` solution file in Visual Studio. -1. Select the `Aspire/Aspire.AppHost` project in **Solution Explorer** and start the app with either Visual Studio's Run button or by selecting **Start Debugging** from the **Debug** menu. - -### .NET CLI +## Use a production distributed token cache provider -In a command shell, navigate to the `Aspire/Aspire.AppHost` project folder and use the `dotnet run` command to run the sample. The `BlazorWebAppEntra` and `MinimalApiJwt` projects are also started by the command. +The sample app uses in-memory distributed token caches, but a production distributed token cache provider is recommended for production apps. For more information, see [Use a production distributed token cache provider](https://learn.microsoft.com/aspnet/core/blazor/security/blazor-web-app-with-entra?pivots=without-yarp-and-aspire#use-a-production-distributed-token-cache-provider). diff --git a/10.0/BlazorWebAppEntraBff/Aspire/Aspire.AppHost/AppHost.cs b/10.0/BlazorWebAppEntraBffYarpAspire/Aspire/Aspire.AppHost/AppHost.cs similarity index 100% rename from 10.0/BlazorWebAppEntraBff/Aspire/Aspire.AppHost/AppHost.cs rename to 10.0/BlazorWebAppEntraBffYarpAspire/Aspire/Aspire.AppHost/AppHost.cs diff --git a/10.0/BlazorWebAppEntraBff/Aspire/Aspire.AppHost/Aspire.AppHost.csproj b/10.0/BlazorWebAppEntraBffYarpAspire/Aspire/Aspire.AppHost/Aspire.AppHost.csproj similarity index 100% rename from 10.0/BlazorWebAppEntraBff/Aspire/Aspire.AppHost/Aspire.AppHost.csproj rename to 10.0/BlazorWebAppEntraBffYarpAspire/Aspire/Aspire.AppHost/Aspire.AppHost.csproj diff --git a/10.0/BlazorWebAppEntraBff/Aspire/Aspire.AppHost/Properties/launchSettings.json b/10.0/BlazorWebAppEntraBffYarpAspire/Aspire/Aspire.AppHost/Properties/launchSettings.json similarity index 100% rename from 10.0/BlazorWebAppEntraBff/Aspire/Aspire.AppHost/Properties/launchSettings.json rename to 10.0/BlazorWebAppEntraBffYarpAspire/Aspire/Aspire.AppHost/Properties/launchSettings.json diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/wwwroot/appsettings.Development.json b/10.0/BlazorWebAppEntraBffYarpAspire/Aspire/Aspire.AppHost/appsettings.Development.json similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/wwwroot/appsettings.Development.json rename to 10.0/BlazorWebAppEntraBffYarpAspire/Aspire/Aspire.AppHost/appsettings.Development.json diff --git a/10.0/BlazorWebAppEntraBff/Aspire/Aspire.AppHost/appsettings.json b/10.0/BlazorWebAppEntraBffYarpAspire/Aspire/Aspire.AppHost/appsettings.json similarity index 100% rename from 10.0/BlazorWebAppEntraBff/Aspire/Aspire.AppHost/appsettings.json rename to 10.0/BlazorWebAppEntraBffYarpAspire/Aspire/Aspire.AppHost/appsettings.json diff --git a/10.0/BlazorWebAppEntraBff/Aspire/Aspire.ServiceDefaults/Aspire.ServiceDefaults.csproj b/10.0/BlazorWebAppEntraBffYarpAspire/Aspire/Aspire.ServiceDefaults/Aspire.ServiceDefaults.csproj similarity index 100% rename from 10.0/BlazorWebAppEntraBff/Aspire/Aspire.ServiceDefaults/Aspire.ServiceDefaults.csproj rename to 10.0/BlazorWebAppEntraBffYarpAspire/Aspire/Aspire.ServiceDefaults/Aspire.ServiceDefaults.csproj diff --git a/10.0/BlazorWebAppEntraBff/Aspire/Aspire.ServiceDefaults/Extensions.cs b/10.0/BlazorWebAppEntraBffYarpAspire/Aspire/Aspire.ServiceDefaults/Extensions.cs similarity index 100% rename from 10.0/BlazorWebAppEntraBff/Aspire/Aspire.ServiceDefaults/Extensions.cs rename to 10.0/BlazorWebAppEntraBffYarpAspire/Aspire/Aspire.ServiceDefaults/Extensions.cs diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/BlazorWebAppEntra.Client.csproj b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/BlazorWebAppEntra.Client.csproj similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/BlazorWebAppEntra.Client.csproj rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/BlazorWebAppEntra.Client.csproj diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor similarity index 82% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor index 75416a4a1..a7e9ff016 100644 --- a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor +++ b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor @@ -25,15 +25,18 @@ protected override void OnInitialized() { - currentUrl = Navigation.Uri; + currentUrl = Navigation.ToBaseRelativePath(Navigation.Uri); Navigation.LocationChanged += OnLocationChanged; } private void OnLocationChanged(object? sender, LocationChangedEventArgs e) { - currentUrl = Navigation.Uri; + currentUrl = Navigation.ToBaseRelativePath(e.Location); StateHasChanged(); } - public void Dispose() => Navigation.LocationChanged -= OnLocationChanged; + public void Dispose() + { + Navigation.LocationChanged -= OnLocationChanged; + } } diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor.css b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor.css similarity index 97% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor.css rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor.css index 0a25914e8..52048247f 100644 --- a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor.css +++ b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor.css @@ -19,7 +19,6 @@ .nav-item { font-size: 0.9rem; padding-bottom: 0.5rem; - text-align: left; } .nav-item .nav-link { @@ -30,7 +29,7 @@ height: 3rem; display: flex; align-items: center; - text-align: left; + line-height: 3rem; width: 100%; } diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/MainLayout.razor b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/MainLayout.razor similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/MainLayout.razor rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/MainLayout.razor diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/MainLayout.razor.css b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/MainLayout.razor.css similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/MainLayout.razor.css rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/MainLayout.razor.css diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/NavMenu.razor b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/NavMenu.razor similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/NavMenu.razor rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/NavMenu.razor diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/NavMenu.razor.css b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/NavMenu.razor.css similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/NavMenu.razor.css rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/NavMenu.razor.css diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/ReconnectModal.razor b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/ReconnectModal.razor similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/ReconnectModal.razor rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/ReconnectModal.razor diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/ReconnectModal.razor.css b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/ReconnectModal.razor.css similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/ReconnectModal.razor.css rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/ReconnectModal.razor.css diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/ReconnectModal.razor.js b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/ReconnectModal.razor.js similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/ReconnectModal.razor.js rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/ReconnectModal.razor.js diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Pages/Counter.razor b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Pages/Counter.razor similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Pages/Counter.razor rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Pages/Counter.razor diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Pages/Home.razor b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Pages/Home.razor similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Pages/Home.razor rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Pages/Home.razor diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Pages/NotFound.razor b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Pages/NotFound.razor similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Pages/NotFound.razor rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Pages/NotFound.razor diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Pages/UserClaims.razor b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Pages/UserClaims.razor similarity index 87% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Pages/UserClaims.razor rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Pages/UserClaims.razor index a7b94a49d..af9efbaff 100644 --- a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Pages/UserClaims.razor +++ b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Pages/UserClaims.razor @@ -1,4 +1,4 @@ -@page "/user-claims" +@page "/user-claims" @using System.Security.Claims @using Microsoft.AspNetCore.Authorization @attribute [Authorize] @@ -18,7 +18,7 @@ } @code { - private IEnumerable claims = []; + private IEnumerable claims = Enumerable.Empty(); [CascadingParameter] private Task? AuthState { get; set; } diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Pages/Weather.razor b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Pages/Weather.razor similarity index 69% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Pages/Weather.razor rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Pages/Weather.razor index a78eb6582..0abd39421 100644 --- a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Pages/Weather.razor +++ b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Pages/Weather.razor @@ -10,7 +10,7 @@

This component demonstrates showing data.

-@if (Forecasts == null) +@if (forecasts == null) {

Loading...

} @@ -20,13 +20,13 @@ else Date - Temp. (C) - Temp. (F) + Temp. (C) + Temp. (F) Summary - @foreach (var forecast in Forecasts) + @foreach (var forecast in forecasts) { @forecast.Date.ToShortDateString() @@ -40,11 +40,10 @@ else } @code { - [PersistentState] - public IEnumerable? Forecasts { get; set; } + private IEnumerable? forecasts; protected override async Task OnInitializedAsync() { - Forecasts ??= await WeatherForecaster.GetWeatherForecastAsync(); + forecasts = await WeatherForecaster.GetWeatherForecastAsync(); } } diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Program.cs b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Program.cs similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Program.cs rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Program.cs diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/RedirectToLogin.razor b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/RedirectToLogin.razor similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/RedirectToLogin.razor rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/RedirectToLogin.razor diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Routes.razor b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Routes.razor similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Routes.razor rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Routes.razor diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Weather/ClientWeatherForecaster.cs b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Weather/ClientWeatherForecaster.cs similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Weather/ClientWeatherForecaster.cs rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Weather/ClientWeatherForecaster.cs diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Weather/IWeatherForecaster.cs b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Weather/IWeatherForecaster.cs similarity index 99% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Weather/IWeatherForecaster.cs rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Weather/IWeatherForecaster.cs index 5f1b6fd73..a2e54a299 100644 --- a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Weather/IWeatherForecaster.cs +++ b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Weather/IWeatherForecaster.cs @@ -1,3 +1,4 @@ + namespace BlazorWebAppEntra.Client.Weather; public interface IWeatherForecaster diff --git a/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Weather/WeatherForecast.cs b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Weather/WeatherForecast.cs new file mode 100644 index 000000000..4ea41a45b --- /dev/null +++ b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Weather/WeatherForecast.cs @@ -0,0 +1,9 @@ +namespace BlazorWebAppEntra.Client.Weather; + +public sealed class WeatherForecast +{ + public DateOnly Date { get; set; } + public int TemperatureC { get; set; } + public string? Summary { get; set; } + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); +} diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/_Imports.razor b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/_Imports.razor similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/_Imports.razor rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/_Imports.razor diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/appsettings.Development.json b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/wwwroot/appsettings.Development.json similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/appsettings.Development.json rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/wwwroot/appsettings.Development.json diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/wwwroot/appsettings.json b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/wwwroot/appsettings.json similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/wwwroot/appsettings.json rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/wwwroot/appsettings.json diff --git a/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.sln b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.sln new file mode 100644 index 000000000..f26e51dc9 --- /dev/null +++ b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.sln @@ -0,0 +1,93 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 18 +VisualStudioVersion = 18.0.11201.2 d18.0 +MinimumVisualStudioVersion = 16.0.0.0 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorWebAppEntra", "BlazorWebAppEntra\BlazorWebAppEntra.csproj", "{7588C04C-A91C-46AA-A161-6441DDA6D1C8}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorWebAppEntra.Client", "BlazorWebAppEntra.Client\BlazorWebAppEntra.Client.csproj", "{DCAFB651-B1C8-48F1-AC85-0221F7378DDA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.AppHost", "Aspire\Aspire.AppHost\Aspire.AppHost.csproj", "{2F6AB681-C3FD-45F3-95C1-0FA9889CDEEA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.ServiceDefaults", "Aspire\Aspire.ServiceDefaults\Aspire.ServiceDefaults.csproj", "{13E08A9B-6736-4342-BFE7-A951BA3F36DC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MinimalApiJwt", "MinimalApiJwt\MinimalApiJwt.csproj", "{02B2EF75-0ED3-7B54-3753-8E8DD6236369}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7588C04C-A91C-46AA-A161-6441DDA6D1C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7588C04C-A91C-46AA-A161-6441DDA6D1C8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7588C04C-A91C-46AA-A161-6441DDA6D1C8}.Debug|x64.ActiveCfg = Debug|Any CPU + {7588C04C-A91C-46AA-A161-6441DDA6D1C8}.Debug|x64.Build.0 = Debug|Any CPU + {7588C04C-A91C-46AA-A161-6441DDA6D1C8}.Debug|x86.ActiveCfg = Debug|Any CPU + {7588C04C-A91C-46AA-A161-6441DDA6D1C8}.Debug|x86.Build.0 = Debug|Any CPU + {7588C04C-A91C-46AA-A161-6441DDA6D1C8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7588C04C-A91C-46AA-A161-6441DDA6D1C8}.Release|Any CPU.Build.0 = Release|Any CPU + {7588C04C-A91C-46AA-A161-6441DDA6D1C8}.Release|x64.ActiveCfg = Release|Any CPU + {7588C04C-A91C-46AA-A161-6441DDA6D1C8}.Release|x64.Build.0 = Release|Any CPU + {7588C04C-A91C-46AA-A161-6441DDA6D1C8}.Release|x86.ActiveCfg = Release|Any CPU + {7588C04C-A91C-46AA-A161-6441DDA6D1C8}.Release|x86.Build.0 = Release|Any CPU + {DCAFB651-B1C8-48F1-AC85-0221F7378DDA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DCAFB651-B1C8-48F1-AC85-0221F7378DDA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DCAFB651-B1C8-48F1-AC85-0221F7378DDA}.Debug|x64.ActiveCfg = Debug|Any CPU + {DCAFB651-B1C8-48F1-AC85-0221F7378DDA}.Debug|x64.Build.0 = Debug|Any CPU + {DCAFB651-B1C8-48F1-AC85-0221F7378DDA}.Debug|x86.ActiveCfg = Debug|Any CPU + {DCAFB651-B1C8-48F1-AC85-0221F7378DDA}.Debug|x86.Build.0 = Debug|Any CPU + {DCAFB651-B1C8-48F1-AC85-0221F7378DDA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DCAFB651-B1C8-48F1-AC85-0221F7378DDA}.Release|Any CPU.Build.0 = Release|Any CPU + {DCAFB651-B1C8-48F1-AC85-0221F7378DDA}.Release|x64.ActiveCfg = Release|Any CPU + {DCAFB651-B1C8-48F1-AC85-0221F7378DDA}.Release|x64.Build.0 = Release|Any CPU + {DCAFB651-B1C8-48F1-AC85-0221F7378DDA}.Release|x86.ActiveCfg = Release|Any CPU + {DCAFB651-B1C8-48F1-AC85-0221F7378DDA}.Release|x86.Build.0 = Release|Any CPU + {2F6AB681-C3FD-45F3-95C1-0FA9889CDEEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2F6AB681-C3FD-45F3-95C1-0FA9889CDEEA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2F6AB681-C3FD-45F3-95C1-0FA9889CDEEA}.Debug|x64.ActiveCfg = Debug|Any CPU + {2F6AB681-C3FD-45F3-95C1-0FA9889CDEEA}.Debug|x64.Build.0 = Debug|Any CPU + {2F6AB681-C3FD-45F3-95C1-0FA9889CDEEA}.Debug|x86.ActiveCfg = Debug|Any CPU + {2F6AB681-C3FD-45F3-95C1-0FA9889CDEEA}.Debug|x86.Build.0 = Debug|Any CPU + {2F6AB681-C3FD-45F3-95C1-0FA9889CDEEA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2F6AB681-C3FD-45F3-95C1-0FA9889CDEEA}.Release|Any CPU.Build.0 = Release|Any CPU + {2F6AB681-C3FD-45F3-95C1-0FA9889CDEEA}.Release|x64.ActiveCfg = Release|Any CPU + {2F6AB681-C3FD-45F3-95C1-0FA9889CDEEA}.Release|x64.Build.0 = Release|Any CPU + {2F6AB681-C3FD-45F3-95C1-0FA9889CDEEA}.Release|x86.ActiveCfg = Release|Any CPU + {2F6AB681-C3FD-45F3-95C1-0FA9889CDEEA}.Release|x86.Build.0 = Release|Any CPU + {13E08A9B-6736-4342-BFE7-A951BA3F36DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {13E08A9B-6736-4342-BFE7-A951BA3F36DC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {13E08A9B-6736-4342-BFE7-A951BA3F36DC}.Debug|x64.ActiveCfg = Debug|Any CPU + {13E08A9B-6736-4342-BFE7-A951BA3F36DC}.Debug|x64.Build.0 = Debug|Any CPU + {13E08A9B-6736-4342-BFE7-A951BA3F36DC}.Debug|x86.ActiveCfg = Debug|Any CPU + {13E08A9B-6736-4342-BFE7-A951BA3F36DC}.Debug|x86.Build.0 = Debug|Any CPU + {13E08A9B-6736-4342-BFE7-A951BA3F36DC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {13E08A9B-6736-4342-BFE7-A951BA3F36DC}.Release|Any CPU.Build.0 = Release|Any CPU + {13E08A9B-6736-4342-BFE7-A951BA3F36DC}.Release|x64.ActiveCfg = Release|Any CPU + {13E08A9B-6736-4342-BFE7-A951BA3F36DC}.Release|x64.Build.0 = Release|Any CPU + {13E08A9B-6736-4342-BFE7-A951BA3F36DC}.Release|x86.ActiveCfg = Release|Any CPU + {13E08A9B-6736-4342-BFE7-A951BA3F36DC}.Release|x86.Build.0 = Release|Any CPU + {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Debug|Any CPU.Build.0 = Debug|Any CPU + {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Debug|x64.ActiveCfg = Debug|Any CPU + {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Debug|x64.Build.0 = Debug|Any CPU + {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Debug|x86.ActiveCfg = Debug|Any CPU + {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Debug|x86.Build.0 = Debug|Any CPU + {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Release|Any CPU.ActiveCfg = Release|Any CPU + {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Release|Any CPU.Build.0 = Release|Any CPU + {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Release|x64.ActiveCfg = Release|Any CPU + {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Release|x64.Build.0 = Release|Any CPU + {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Release|x86.ActiveCfg = Release|Any CPU + {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {A7BB58BC-6E37-4456-BCDB-80A7CE694BAD} + EndGlobalSection +EndGlobal diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/BlazorWebAppEntra.csproj b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/BlazorWebAppEntra.csproj similarity index 84% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/BlazorWebAppEntra.csproj rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/BlazorWebAppEntra.csproj index 5f6ae37e7..55c11469a 100644 --- a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/BlazorWebAppEntra.csproj +++ b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/BlazorWebAppEntra.csproj @@ -8,6 +8,7 @@ + @@ -15,8 +16,8 @@ + - diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/Components/App.razor b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/Components/App.razor similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/Components/App.razor rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/Components/App.razor diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/Components/Pages/Error.razor b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/Components/Pages/Error.razor similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/Components/Pages/Error.razor rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/Components/Pages/Error.razor diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/Components/_Imports.razor b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/Components/_Imports.razor similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/Components/_Imports.razor rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/Components/_Imports.razor diff --git a/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/LoginLogoutEndpointRouteBuilderExtensions.cs b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/LoginLogoutEndpointRouteBuilderExtensions.cs new file mode 100644 index 000000000..df9c1aa88 --- /dev/null +++ b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/LoginLogoutEndpointRouteBuilderExtensions.cs @@ -0,0 +1,47 @@ +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Authentication.OpenIdConnect; +using Microsoft.AspNetCore.Mvc; + +namespace Microsoft.AspNetCore.Routing; + +internal static class LoginLogoutEndpointRouteBuilderExtensions +{ + internal static IEndpointConventionBuilder MapLoginAndLogout(this IEndpointRouteBuilder endpoints) + { + var group = endpoints.MapGroup(""); + + group.MapGet("/login", (string? returnUrl) => TypedResults.Challenge(GetAuthProperties(returnUrl))) + .AllowAnonymous(); + + // Sign out of the Cookie and OIDC handlers. If you do not sign out with the OIDC handler, + // the user will automatically be signed back in the next time they visit a page that requires authentication + // without being able to choose another account. + group.MapPost("/logout", ([FromForm] string? returnUrl) => TypedResults.SignOut(GetAuthProperties(returnUrl), + [CookieAuthenticationDefaults.AuthenticationScheme, OpenIdConnectDefaults.AuthenticationScheme])); + + return group; + } + + private static AuthenticationProperties GetAuthProperties(string? returnUrl) + { + // TODO: Use HttpContext.Request.PathBase instead. + const string pathBase = "/"; + + // Prevent open redirects. + if (string.IsNullOrEmpty(returnUrl)) + { + returnUrl = pathBase; + } + else if (!Uri.IsWellFormedUriString(returnUrl, UriKind.Relative)) + { + returnUrl = new Uri(returnUrl, UriKind.Absolute).PathAndQuery; + } + else if (returnUrl[0] != '/') + { + returnUrl = $"{pathBase}{returnUrl}"; + } + + return new AuthenticationProperties { RedirectUri = returnUrl }; + } +} diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/Program.cs b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/Program.cs similarity index 83% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/Program.cs rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/Program.cs index 4752634be..85044536a 100644 --- a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/Program.cs +++ b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/Program.cs @@ -1,27 +1,21 @@ -using System.Security.Claims; -using Azure.Core; using Azure.Identity; +using BlazorWebAppEntra; using BlazorWebAppEntra.Client.Weather; using BlazorWebAppEntra.Components; -using BlazorWebAppEntra.Weather; -using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authentication.OpenIdConnect; using Microsoft.AspNetCore.DataProtection; -using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Azure; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Identity.Web; using Microsoft.Identity.Web.TokenCacheProviders.Distributed; +using Microsoft.IdentityModel.Protocols.OpenIdConnect; +using Yarp.ReverseProxy.Transforms; var builder = WebApplication.CreateBuilder(args); // Add services to the container. -// Remove or set 'SerializeAllClaims' to 'false' if you only want to -// serialize name and role claims for CSR. -builder.Services.AddRazorComponents() - .AddInteractiveServerComponents() - .AddInteractiveWebAssemblyComponents() - .AddAuthenticationStateSerialization(options => options.SerializeAllClaims = true); +// Add service defaults & Aspire components. +builder.AddServiceDefaults(); // Configure authentication to use Microsoft Entra ID builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) @@ -69,14 +63,14 @@ builder.Services.AddDistributedMemoryCache(); builder.Services.Configure( - options => + options => { // Disable L1 Cache default: false //options.DisableL1Cache = false; - + // L1 Cache Size Limit default: 500 MB //options.L1CacheOptions.SizeLimit = 500 * 1024 * 1024; - + // Encrypt tokens at rest default: false options.Encrypt = true; @@ -127,8 +121,25 @@ .ProtectKeysWithAzureKeyVault( new Uri("{KEY IDENTIFIER}"), credential); */ +builder.Services.AddOptions(OpenIdConnectDefaults.AuthenticationScheme).Configure(oidcOptions => +{ + oidcOptions.Scope.Add(OpenIdConnectScope.OfflineAccess); +}); + builder.Services.AddAuthorization(); +builder.Services.AddCascadingAuthenticationState(); + +// Remove or set 'SerializeAllClaims' to 'false' if you only want to +// serialize name and role claims for CSR. +builder.Services.AddRazorComponents() + .AddInteractiveServerComponents() + .AddMicrosoftIdentityConsentHandler() + .AddInteractiveWebAssemblyComponents() + .AddAuthenticationStateSerialization(options => options.SerializeAllClaims = true); + +builder.Services.AddHttpForwarderWithServiceDiscovery(); +builder.Services.AddHttpContextAccessor(); builder.Services.AddScoped(); var app = builder.Build(); @@ -151,17 +162,24 @@ app.MapStaticAssets(); - -app.MapGet("/weather-forecast", ([FromServices] IWeatherForecaster WeatherForecaster) => -{ - return WeatherForecaster.GetWeatherForecastAsync(); -}).RequireAuthorization(); +app.MapDefaultEndpoints(); app.MapRazorComponents() .AddInteractiveServerRenderMode() .AddInteractiveWebAssemblyRenderMode() .AddAdditionalAssemblies(typeof(BlazorWebAppEntra.Client._Imports).Assembly); +app.MapForwarder("/weather-forecast", "https://weatherapi", transformBuilder => +{ + transformBuilder.AddRequestTransform(async transformContext => + { + var tokenAcquisition = transformContext.HttpContext.RequestServices.GetRequiredService(); + List scopes = ["{APP ID URI}/Weather.Get"]; + var accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(scopes); + transformContext.ProxyRequest.Headers.Authorization = new("Bearer", accessToken); + }); +}).RequireAuthorization(); + app.MapGroup("/authentication").MapLoginAndLogout(); app.Run(); diff --git a/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/Properties/launchSettings.json b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/Properties/launchSettings.json new file mode 100644 index 000000000..5a5fcf3f4 --- /dev/null +++ b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/Properties/launchSettings.json @@ -0,0 +1,15 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "profiles": { + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", + "applicationUrl": "https://localhost:5001;http://localhost:5000", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/10.0/BlazorWebAppEntraBff/BlazorWebAppEntra/ServerWeatherForecaster.cs b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/ServerWeatherForecaster.cs similarity index 100% rename from 10.0/BlazorWebAppEntraBff/BlazorWebAppEntra/ServerWeatherForecaster.cs rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/ServerWeatherForecaster.cs diff --git a/10.0/BlazorWebAppEntra/MinimalApiJwt/appsettings.Development.json b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/appsettings.Development.json similarity index 100% rename from 10.0/BlazorWebAppEntra/MinimalApiJwt/appsettings.Development.json rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/appsettings.Development.json diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/appsettings.json b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/appsettings.json similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/appsettings.json rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/appsettings.json diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/app.css b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/app.css similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/app.css rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/app.css diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/favicon.png b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/favicon.png similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/favicon.png rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/favicon.png diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.css b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.css similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.css rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.css diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.css.map b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.css.map similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.css.map rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.css.map diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.min.css b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.min.css similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.min.css rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.min.css diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.min.css.map b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.min.css.map similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.min.css.map rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.min.css.map diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css.map b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css.map similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css.map rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css.map diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css.map b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css.map similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css.map rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css.map diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.css b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.css similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.css rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.css diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.css.map b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.css.map similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.css.map rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.css.map diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.min.css b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.min.css similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.min.css rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.min.css diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.min.css.map b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.min.css.map similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.min.css.map rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.min.css.map diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.css b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.css similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.css rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.css diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.css.map b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.css.map similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.css.map rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.css.map diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.min.css b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.min.css similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.min.css rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.min.css diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.min.css.map b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.min.css.map similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.min.css.map rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.min.css.map diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.css b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.css similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.css rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.css diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.css b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.css similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.css rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.css diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.css.map b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.css.map similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.css.map rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.css.map diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.min.css b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.min.css similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.min.css rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.min.css diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.min.css.map b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.min.css.map similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.min.css.map rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.min.css.map diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.js b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.js similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.js rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.js diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.js.map b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.js.map similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.js.map rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.js.map diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js.map b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js.map similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js.map rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js.map diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.js b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.js similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.js rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.js diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map b/10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map similarity index 100% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map rename to 10.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map diff --git a/10.0/BlazorWebAppEntra/MinimalApiJwt/MinimalApiJwt.csproj b/10.0/BlazorWebAppEntraBffYarpAspire/MinimalApiJwt/MinimalApiJwt.csproj similarity index 84% rename from 10.0/BlazorWebAppEntra/MinimalApiJwt/MinimalApiJwt.csproj rename to 10.0/BlazorWebAppEntraBffYarpAspire/MinimalApiJwt/MinimalApiJwt.csproj index 8150437ba..b4424c9b5 100644 --- a/10.0/BlazorWebAppEntra/MinimalApiJwt/MinimalApiJwt.csproj +++ b/10.0/BlazorWebAppEntraBffYarpAspire/MinimalApiJwt/MinimalApiJwt.csproj @@ -8,6 +8,7 @@ + diff --git a/10.0/BlazorWebAppEntra/MinimalApiJwt/MinimalApiJwt.http b/10.0/BlazorWebAppEntraBffYarpAspire/MinimalApiJwt/MinimalApiJwt.http similarity index 100% rename from 10.0/BlazorWebAppEntra/MinimalApiJwt/MinimalApiJwt.http rename to 10.0/BlazorWebAppEntraBffYarpAspire/MinimalApiJwt/MinimalApiJwt.http diff --git a/10.0/BlazorWebAppEntra/MinimalApiJwt/Program.cs b/10.0/BlazorWebAppEntraBffYarpAspire/MinimalApiJwt/Program.cs similarity index 93% rename from 10.0/BlazorWebAppEntra/MinimalApiJwt/Program.cs rename to 10.0/BlazorWebAppEntraBffYarpAspire/MinimalApiJwt/Program.cs index baaa2668a..5dd55f57b 100644 --- a/10.0/BlazorWebAppEntra/MinimalApiJwt/Program.cs +++ b/10.0/BlazorWebAppEntraBffYarpAspire/MinimalApiJwt/Program.cs @@ -1,12 +1,12 @@ -using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.Extensions.Options; - var builder = WebApplication.CreateBuilder(args); +// Add service defaults & Aspire components. +builder.AddServiceDefaults(); + builder.Services.AddAuthentication() .AddJwtBearer("Bearer", jwtOptions => { - // {TENANT ID} is the directory (tenant) ID. + // {TENANT ID} in the following examples is the directory (tenant) ID. // // Authority format {AUTHORITY} matches the issurer (`iss`) of the JWT returned by the identity provider. // @@ -15,6 +15,7 @@ // Authority format {AUTHORITY} for B2C tenant type: https://login.microsoftonline.com/{TENANT ID}/v2.0 // jwtOptions.Authority = "{AUTHORITY}"; + // // The following should match just the path of the Application ID URI configured when adding the "Weather.Get" scope // under "Expose an API" in the Azure or Entra portal. {CLIENT ID} is the application (client) ID of this @@ -48,6 +49,8 @@ // Configure the HTTP request pipeline. app.UseHttpsRedirection(); +app.MapDefaultEndpoints(); + var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" diff --git a/10.0/BlazorWebAppEntra/MinimalApiJwt/Properties/launchSettings.json b/10.0/BlazorWebAppEntraBffYarpAspire/MinimalApiJwt/Properties/launchSettings.json similarity index 100% rename from 10.0/BlazorWebAppEntra/MinimalApiJwt/Properties/launchSettings.json rename to 10.0/BlazorWebAppEntraBffYarpAspire/MinimalApiJwt/Properties/launchSettings.json diff --git a/10.0/BlazorWebAppEntraBff/Aspire/Aspire.AppHost/appsettings.Development.json b/10.0/BlazorWebAppEntraBffYarpAspire/MinimalApiJwt/appsettings.Development.json similarity index 100% rename from 10.0/BlazorWebAppEntraBff/Aspire/Aspire.AppHost/appsettings.Development.json rename to 10.0/BlazorWebAppEntraBffYarpAspire/MinimalApiJwt/appsettings.Development.json diff --git a/10.0/BlazorWebAppEntra/MinimalApiJwt/appsettings.json b/10.0/BlazorWebAppEntraBffYarpAspire/MinimalApiJwt/appsettings.json similarity index 100% rename from 10.0/BlazorWebAppEntra/MinimalApiJwt/appsettings.json rename to 10.0/BlazorWebAppEntraBffYarpAspire/MinimalApiJwt/appsettings.json diff --git a/10.0/BlazorWebAppEntraBffYarpAspire/README.md b/10.0/BlazorWebAppEntraBffYarpAspire/README.md new file mode 100644 index 000000000..d7b8078f2 --- /dev/null +++ b/10.0/BlazorWebAppEntraBffYarpAspire/README.md @@ -0,0 +1,35 @@ +# Blazor Web App with Entra (with YARP and Aspire) + +This sample features: + +* A Blazor Web App with global Auto interactivity. `PersistingAuthenticationStateProvider` and `PersistentAuthenticationStateProvider` services are added to the server and client Blazor apps to capture authentication state and flow it between the server and client. +* Authentication with Microsoft Entra using Microsoft Identity Web packages. +* A minimal API backend using the `JwtBearerHandler` to validate JWT tokens saved by the Blazor app using the in-memory token store for the access token. +* The BFF pattern using Aspire service discovery and YARP for proxying the requests to `/weatherforecast` on the backend using an access token generated for the web API on behalf of the user account for the user's claims. + +## Article for this sample app + +The article for this sample app is [Secure an ASP.NET Core Blazor Web App with Microsoft Entra ID (BFF pattern)](https://learn.microsoft.com/aspnet/core/blazor/security/blazor-web-app-with-entra?pivots=with-yarp-and-aspire). + +If you need to open an issue that pertains to the coding of the sample app, open [an issue on this samples repo](https://github.com/dotnet/blazor-samples/issues). Otherwise, open an issue using the **Open a documentation issue** link/feedback form at the bottom of [the article](https://learn.microsoft.com/aspnet/core/blazor/security/blazor-web-app-with-entra?pivots=with-yarp-and-aspire). + +## Configure the sample + +Configure the solution following the guidance in [Secure an ASP.NET Core Blazor Web App with Microsoft Entra ID (BFF pattern)](https://learn.microsoft.com/aspnet/core/blazor/security/blazor-web-app-with-entra?pivots=with-yarp-and-aspire). + +## Use a production distributed token cache provider + +The sample app uses in-memory distributed token caches, but a production distributed token cache provider is recommended for production apps. For more information, see [Use a production distributed token cache provider](https://learn.microsoft.com/aspnet/core/blazor/security/blazor-web-app-with-entra?pivots=with-yarp-and-aspire#use-a-production-distributed-token-cache-provider). + +## Run the sample + +Update the `NSwag.AspNetCore` NuGet package in the `MinimalApiJwt` project to the latest version. + +### Visual Studio + +1. Open the `BlazorWebAppEntra` solution file in Visual Studio. +1. Select the `Aspire/Aspire.AppHost` project in **Solution Explorer** and start the app with either Visual Studio's Run button or by selecting **Start Debugging** from the **Debug** menu. + +### .NET CLI + +In a command shell, navigate to the `Aspire/Aspire.AppHost` project folder and use the `dotnet run` command to run the sample. The `BlazorWebAppEntra` and `MinimalApiJwt` projects are also started by the command. diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Weather/WeatherForecast.cs b/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Weather/WeatherForecast.cs deleted file mode 100644 index 9b41fcb66..000000000 --- a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Weather/WeatherForecast.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace BlazorWebAppEntra.Client.Weather; - -public sealed class WeatherForecast(DateOnly date, int temperatureC, string summary) -{ - public DateOnly Date { get; set; } = date; - public int TemperatureC { get; set; } = temperatureC; - public string? Summary { get; set; } = summary; - public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); -} diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.sln b/9.0/BlazorWebAppEntra/BlazorWebAppEntra.sln deleted file mode 100644 index 6a8cf7700..000000000 --- a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.sln +++ /dev/null @@ -1,37 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.12.35323.107 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorWebAppEntra", "BlazorWebAppEntra\BlazorWebAppEntra.csproj", "{ABE4C0A7-8FF0-4FE1-97FD-ED4692324101}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorWebAppEntra.Client", "BlazorWebAppEntra.Client\BlazorWebAppEntra.Client.csproj", "{0E2BE51B-7C55-4CBB-B3E8-7A8EF304C8E2}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MinimalApiJwt", "MinimalApiJwt\MinimalApiJwt.csproj", "{02B2EF75-0ED3-7B54-3753-8E8DD6236369}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {ABE4C0A7-8FF0-4FE1-97FD-ED4692324101}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {ABE4C0A7-8FF0-4FE1-97FD-ED4692324101}.Debug|Any CPU.Build.0 = Debug|Any CPU - {ABE4C0A7-8FF0-4FE1-97FD-ED4692324101}.Release|Any CPU.ActiveCfg = Release|Any CPU - {ABE4C0A7-8FF0-4FE1-97FD-ED4692324101}.Release|Any CPU.Build.0 = Release|Any CPU - {0E2BE51B-7C55-4CBB-B3E8-7A8EF304C8E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0E2BE51B-7C55-4CBB-B3E8-7A8EF304C8E2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0E2BE51B-7C55-4CBB-B3E8-7A8EF304C8E2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0E2BE51B-7C55-4CBB-B3E8-7A8EF304C8E2}.Release|Any CPU.Build.0 = Release|Any CPU - {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Debug|Any CPU.Build.0 = Debug|Any CPU - {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Release|Any CPU.ActiveCfg = Release|Any CPU - {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {74FE9FED-A3AA-4190-B610-C9509637F38E} - EndGlobalSection -EndGlobal diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/LoginLogoutEndpointRouteBuilderExtensions.cs b/9.0/BlazorWebAppEntra/BlazorWebAppEntra/LoginLogoutEndpointRouteBuilderExtensions.cs deleted file mode 100644 index 7e34d6c92..000000000 --- a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/LoginLogoutEndpointRouteBuilderExtensions.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authentication.Cookies; -using Microsoft.AspNetCore.Authentication.OpenIdConnect; -using Microsoft.AspNetCore.Mvc; - -namespace Microsoft.AspNetCore.Routing; - -internal static class LoginLogoutEndpointRouteBuilderExtensions -{ - internal static IEndpointConventionBuilder MapLoginAndLogout(this IEndpointRouteBuilder endpoints) - { - var group = endpoints.MapGroup(string.Empty); - - group.MapGet("/login", (string? returnUrl) => TypedResults.Challenge(GetAuthProperties(returnUrl))) - .AllowAnonymous(); - - // Sign out with both the Cookie and OIDC authentication schemes. Users who have not signed out with the OIDC scheme will - // automatically get signed back in as the same user the next time they visit a page that requires authentication - // with no opportunity to choose another account. - group.MapPost("/logout", ([FromForm] string? returnUrl) => TypedResults.SignOut(GetAuthProperties(returnUrl), - [CookieAuthenticationDefaults.AuthenticationScheme, OpenIdConnectDefaults.AuthenticationScheme])); - - return group; - } - - // Prevent open redirects. Non-empty returnUrls are absolute URIs provided by NavigationManager.Uri. - private static AuthenticationProperties GetAuthProperties(string? returnUrl) => - new() - { - RedirectUri = returnUrl switch - { - string => new Uri(returnUrl, UriKind.Absolute).PathAndQuery, - null => "/", - } - }; -} diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/Properties/launchSettings.json b/9.0/BlazorWebAppEntra/BlazorWebAppEntra/Properties/launchSettings.json deleted file mode 100644 index 1639e4223..000000000 --- a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/Properties/launchSettings.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/launchsettings.json", - "profiles": { - "http": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", - "applicationUrl": "http://localhost:5181", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "https": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", - "applicationUrl": "https://localhost:7062;http://localhost:5181", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - } - } - } diff --git a/9.0/BlazorWebAppEntra/README.md b/9.0/BlazorWebAppEntra/README.md deleted file mode 100644 index f2b2a0244..000000000 --- a/9.0/BlazorWebAppEntra/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# `BlazorWebAppEntra` - -Sample app to accompany [Secure an ASP.NET Core Blazor Web App with Microsoft Entra ID](https://learn.microsoft.com/aspnet/core/blazor/security/blazor-web-app-with-entra?pivots=non-bff-pattern). - -## Use a production distributed token cache provider - -The sample app uses in-memory distributed token caches, but a production distributed token cache provider is recommended for production apps. For more information, see [Use a production distributed token cache provider](https://learn.microsoft.com/aspnet/core/blazor/security/blazor-web-app-with-entra?pivots=non-bff-pattern#use-a-production-distributed-token-cache-provider). diff --git a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/BlazorWebAppEntra.Client.csproj b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/BlazorWebAppEntra.Client.csproj index 278b216a5..df54776f3 100644 --- a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/BlazorWebAppEntra.Client.csproj +++ b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/BlazorWebAppEntra.Client.csproj @@ -9,9 +9,9 @@ - - - + + + diff --git a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor index a7e9ff016..75416a4a1 100644 --- a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor +++ b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor @@ -25,18 +25,15 @@ protected override void OnInitialized() { - currentUrl = Navigation.ToBaseRelativePath(Navigation.Uri); + currentUrl = Navigation.Uri; Navigation.LocationChanged += OnLocationChanged; } private void OnLocationChanged(object? sender, LocationChangedEventArgs e) { - currentUrl = Navigation.ToBaseRelativePath(e.Location); + currentUrl = Navigation.Uri; StateHasChanged(); } - public void Dispose() - { - Navigation.LocationChanged -= OnLocationChanged; - } + public void Dispose() => Navigation.LocationChanged -= OnLocationChanged; } diff --git a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor.css b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor.css index 52048247f..0a25914e8 100644 --- a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor.css +++ b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor.css @@ -19,6 +19,7 @@ .nav-item { font-size: 0.9rem; padding-bottom: 0.5rem; + text-align: left; } .nav-item .nav-link { @@ -29,7 +30,7 @@ height: 3rem; display: flex; align-items: center; - line-height: 3rem; + text-align: left; width: 100%; } diff --git a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Layout/MainLayout.razor b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Layout/MainLayout.razor index 2dc69b84e..54adefe1a 100644 --- a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Layout/MainLayout.razor +++ b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Layout/MainLayout.razor @@ -21,7 +21,7 @@ -
+
An unhandled error has occurred. Reload 🗙 diff --git a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Layout/NavMenu.razor.css b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Layout/NavMenu.razor.css index 4e15395e0..a2aeace9c 100644 --- a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Layout/NavMenu.razor.css +++ b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Layout/NavMenu.razor.css @@ -16,7 +16,7 @@ } .top-row { - height: 3.5rem; + min-height: 3.5rem; background-color: rgba(0,0,0,0.4); } diff --git a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Pages/Counter.razor b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Pages/Counter.razor index 413724776..ef23cb316 100644 --- a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Pages/Counter.razor +++ b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Pages/Counter.razor @@ -11,5 +11,8 @@ @code { private int currentCount = 0; - private void IncrementCount() => currentCount++; + private void IncrementCount() + { + currentCount++; + } } diff --git a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Pages/UserClaims.razor b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Pages/UserClaims.razor index af9efbaff..a7b94a49d 100644 --- a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Pages/UserClaims.razor +++ b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Pages/UserClaims.razor @@ -1,4 +1,4 @@ -@page "/user-claims" +@page "/user-claims" @using System.Security.Claims @using Microsoft.AspNetCore.Authorization @attribute [Authorize] @@ -18,7 +18,7 @@ } @code { - private IEnumerable claims = Enumerable.Empty(); + private IEnumerable claims = []; [CascadingParameter] private Task? AuthState { get; set; } diff --git a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Pages/Weather.razor b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Pages/Weather.razor index 0abd39421..0e4c3ce1d 100644 --- a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Pages/Weather.razor +++ b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Pages/Weather.razor @@ -2,6 +2,8 @@ @using Microsoft.AspNetCore.Authorization @using BlazorWebAppEntra.Client.Weather @attribute [Authorize] +@implements IDisposable +@inject PersistentComponentState ApplicationState @inject IWeatherForecaster WeatherForecaster Weather @@ -20,8 +22,8 @@ else Date - Temp. (C) - Temp. (F) + Temp. (C) + Temp. (F) Summary @@ -41,9 +43,29 @@ else @code { private IEnumerable? forecasts; + private PersistingComponentStateSubscription persistingSubscription; protected override async Task OnInitializedAsync() { - forecasts = await WeatherForecaster.GetWeatherForecastAsync(); + if (!ApplicationState.TryTakeFromJson>(nameof(forecasts), out var restoredData)) + { + forecasts = await WeatherForecaster.GetWeatherForecastAsync(); + } + else + { + forecasts = restoredData!; + } + + // Call at the end to avoid a potential race condition at app shutdown + persistingSubscription = ApplicationState.RegisterOnPersisting(PersistData); + } + + private Task PersistData() + { + ApplicationState.PersistAsJson(nameof(forecasts), forecasts); + + return Task.CompletedTask; } + + void IDisposable.Dispose() => persistingSubscription.Dispose(); } diff --git a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Weather/IWeatherForecaster.cs b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Weather/IWeatherForecaster.cs index a2e54a299..5f1b6fd73 100644 --- a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Weather/IWeatherForecaster.cs +++ b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Weather/IWeatherForecaster.cs @@ -1,4 +1,3 @@ - namespace BlazorWebAppEntra.Client.Weather; public interface IWeatherForecaster diff --git a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Weather/WeatherForecast.cs b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Weather/WeatherForecast.cs index 4ea41a45b..9b41fcb66 100644 --- a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Weather/WeatherForecast.cs +++ b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.Client/Weather/WeatherForecast.cs @@ -1,9 +1,9 @@ namespace BlazorWebAppEntra.Client.Weather; -public sealed class WeatherForecast +public sealed class WeatherForecast(DateOnly date, int temperatureC, string summary) { - public DateOnly Date { get; set; } - public int TemperatureC { get; set; } - public string? Summary { get; set; } + public DateOnly Date { get; set; } = date; + public int TemperatureC { get; set; } = temperatureC; + public string? Summary { get; set; } = summary; public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); } diff --git a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.sln b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.sln index 0d0b6cb6c..6a8cf7700 100644 --- a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.sln +++ b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.sln @@ -1,17 +1,13 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 -VisualStudioVersion = 17.9.34407.89 +VisualStudioVersion = 17.12.35323.107 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.AppHost", "Aspire\Aspire.AppHost\Aspire.AppHost.csproj", "{82AC1A9F-595F-4F64-95AA-54EEBEACD45D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorWebAppEntra", "BlazorWebAppEntra\BlazorWebAppEntra.csproj", "{ABE4C0A7-8FF0-4FE1-97FD-ED4692324101}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorWebAppEntra", "BlazorWebAppEntra\BlazorWebAppEntra.csproj", "{FA543A49-C954-4504-8090-ABA55920B72B}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorWebAppEntra.Client", "BlazorWebAppEntra.Client\BlazorWebAppEntra.Client.csproj", "{0E2BE51B-7C55-4CBB-B3E8-7A8EF304C8E2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorWebAppEntra.Client", "BlazorWebAppEntra.Client\BlazorWebAppEntra.Client.csproj", "{7B3838A1-D145-479C-9B79-6D2CD1775B71}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MinimalApiJwt", "MinimalApiJwt\MinimalApiJwt.csproj", "{4C7F50CB-A66D-4708-8B4D-6A0018B14784}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.ServiceDefaults", "Aspire\Aspire.ServiceDefaults\Aspire.ServiceDefaults.csproj", "{4F6B20B6-25CD-45AB-A6E1-318EF3CCF854}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MinimalApiJwt", "MinimalApiJwt\MinimalApiJwt.csproj", "{02B2EF75-0ED3-7B54-3753-8E8DD6236369}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -19,31 +15,23 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {82AC1A9F-595F-4F64-95AA-54EEBEACD45D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {82AC1A9F-595F-4F64-95AA-54EEBEACD45D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {82AC1A9F-595F-4F64-95AA-54EEBEACD45D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {82AC1A9F-595F-4F64-95AA-54EEBEACD45D}.Release|Any CPU.Build.0 = Release|Any CPU - {FA543A49-C954-4504-8090-ABA55920B72B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FA543A49-C954-4504-8090-ABA55920B72B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FA543A49-C954-4504-8090-ABA55920B72B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FA543A49-C954-4504-8090-ABA55920B72B}.Release|Any CPU.Build.0 = Release|Any CPU - {7B3838A1-D145-479C-9B79-6D2CD1775B71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7B3838A1-D145-479C-9B79-6D2CD1775B71}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7B3838A1-D145-479C-9B79-6D2CD1775B71}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7B3838A1-D145-479C-9B79-6D2CD1775B71}.Release|Any CPU.Build.0 = Release|Any CPU - {4C7F50CB-A66D-4708-8B4D-6A0018B14784}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4C7F50CB-A66D-4708-8B4D-6A0018B14784}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4C7F50CB-A66D-4708-8B4D-6A0018B14784}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4C7F50CB-A66D-4708-8B4D-6A0018B14784}.Release|Any CPU.Build.0 = Release|Any CPU - {4F6B20B6-25CD-45AB-A6E1-318EF3CCF854}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4F6B20B6-25CD-45AB-A6E1-318EF3CCF854}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4F6B20B6-25CD-45AB-A6E1-318EF3CCF854}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4F6B20B6-25CD-45AB-A6E1-318EF3CCF854}.Release|Any CPU.Build.0 = Release|Any CPU + {ABE4C0A7-8FF0-4FE1-97FD-ED4692324101}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ABE4C0A7-8FF0-4FE1-97FD-ED4692324101}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ABE4C0A7-8FF0-4FE1-97FD-ED4692324101}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ABE4C0A7-8FF0-4FE1-97FD-ED4692324101}.Release|Any CPU.Build.0 = Release|Any CPU + {0E2BE51B-7C55-4CBB-B3E8-7A8EF304C8E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0E2BE51B-7C55-4CBB-B3E8-7A8EF304C8E2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0E2BE51B-7C55-4CBB-B3E8-7A8EF304C8E2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0E2BE51B-7C55-4CBB-B3E8-7A8EF304C8E2}.Release|Any CPU.Build.0 = Release|Any CPU + {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Debug|Any CPU.Build.0 = Debug|Any CPU + {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Release|Any CPU.ActiveCfg = Release|Any CPU + {02B2EF75-0ED3-7B54-3753-8E8DD6236369}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {CB9D0BF2-DFA1-4B11-8188-9B3F35FCC226} + SolutionGuid = {74FE9FED-A3AA-4190-B610-C9509637F38E} EndGlobalSection EndGlobal diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.slnLaunch.user b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.slnLaunch.user similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra.slnLaunch.user rename to 9.0/BlazorWebAppEntraBff/BlazorWebAppEntra.slnLaunch.user diff --git a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra/BlazorWebAppEntra.csproj b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra/BlazorWebAppEntra.csproj index 88aea60b8..063c8c534 100644 --- a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra/BlazorWebAppEntra.csproj +++ b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra/BlazorWebAppEntra.csproj @@ -7,15 +7,13 @@ - + - - diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/BlazorWebAppEntra.http b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra/BlazorWebAppEntra.http similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/BlazorWebAppEntra.http rename to 9.0/BlazorWebAppEntraBff/BlazorWebAppEntra/BlazorWebAppEntra.http diff --git a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra/LoginLogoutEndpointRouteBuilderExtensions.cs b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra/LoginLogoutEndpointRouteBuilderExtensions.cs index df9c1aa88..7e34d6c92 100644 --- a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra/LoginLogoutEndpointRouteBuilderExtensions.cs +++ b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra/LoginLogoutEndpointRouteBuilderExtensions.cs @@ -9,39 +9,28 @@ internal static class LoginLogoutEndpointRouteBuilderExtensions { internal static IEndpointConventionBuilder MapLoginAndLogout(this IEndpointRouteBuilder endpoints) { - var group = endpoints.MapGroup(""); + var group = endpoints.MapGroup(string.Empty); group.MapGet("/login", (string? returnUrl) => TypedResults.Challenge(GetAuthProperties(returnUrl))) .AllowAnonymous(); - // Sign out of the Cookie and OIDC handlers. If you do not sign out with the OIDC handler, - // the user will automatically be signed back in the next time they visit a page that requires authentication - // without being able to choose another account. + // Sign out with both the Cookie and OIDC authentication schemes. Users who have not signed out with the OIDC scheme will + // automatically get signed back in as the same user the next time they visit a page that requires authentication + // with no opportunity to choose another account. group.MapPost("/logout", ([FromForm] string? returnUrl) => TypedResults.SignOut(GetAuthProperties(returnUrl), [CookieAuthenticationDefaults.AuthenticationScheme, OpenIdConnectDefaults.AuthenticationScheme])); return group; } - private static AuthenticationProperties GetAuthProperties(string? returnUrl) - { - // TODO: Use HttpContext.Request.PathBase instead. - const string pathBase = "/"; - - // Prevent open redirects. - if (string.IsNullOrEmpty(returnUrl)) - { - returnUrl = pathBase; - } - else if (!Uri.IsWellFormedUriString(returnUrl, UriKind.Relative)) + // Prevent open redirects. Non-empty returnUrls are absolute URIs provided by NavigationManager.Uri. + private static AuthenticationProperties GetAuthProperties(string? returnUrl) => + new() { - returnUrl = new Uri(returnUrl, UriKind.Absolute).PathAndQuery; - } - else if (returnUrl[0] != '/') - { - returnUrl = $"{pathBase}{returnUrl}"; - } - - return new AuthenticationProperties { RedirectUri = returnUrl }; - } + RedirectUri = returnUrl switch + { + string => new Uri(returnUrl, UriKind.Absolute).PathAndQuery, + null => "/", + } + }; } diff --git a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra/Program.cs b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra/Program.cs index bd4cdca63..398ef991e 100644 --- a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra/Program.cs +++ b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra/Program.cs @@ -1,22 +1,25 @@ using Azure.Identity; -using BlazorWebAppEntra; using BlazorWebAppEntra.Client.Weather; using BlazorWebAppEntra.Components; +using BlazorWebAppEntra.Weather; using Microsoft.AspNetCore.Authentication.OpenIdConnect; using Microsoft.AspNetCore.DataProtection; +using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Azure; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Identity.Web; using Microsoft.Identity.Web.TokenCacheProviders.Distributed; -using Microsoft.IdentityModel.Protocols.OpenIdConnect; -using Yarp.ReverseProxy.Transforms; var builder = WebApplication.CreateBuilder(args); -// Add service defaults & Aspire components. -builder.AddServiceDefaults(); - // Add services to the container. +// Remove or set 'SerializeAllClaims' to 'false' if you only want to +// serialize name and role claims for CSR. +builder.Services.AddRazorComponents() + .AddInteractiveServerComponents() + .AddInteractiveWebAssemblyComponents() + .AddAuthenticationStateSerialization(options => options.SerializeAllClaims = true); + builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(msIdentityOptions => { @@ -38,7 +41,7 @@ builder.Services.AddDistributedMemoryCache(); builder.Services.Configure( - options => + options => { // Disable L1 Cache default: false //options.DisableL1Cache = false; @@ -96,25 +99,8 @@ .ProtectKeysWithAzureKeyVault( new Uri("{KEY IDENTIFIER}"), credential); */ -builder.Services.AddOptions(OpenIdConnectDefaults.AuthenticationScheme).Configure(oidcOptions => -{ - oidcOptions.Scope.Add(OpenIdConnectScope.OfflineAccess); -}); - builder.Services.AddAuthorization(); -builder.Services.AddCascadingAuthenticationState(); - -// Remove or set 'SerializeAllClaims' to 'false' if you only want to -// serialize name and role claims for CSR. -builder.Services.AddRazorComponents() - .AddInteractiveServerComponents() - .AddMicrosoftIdentityConsentHandler() - .AddInteractiveWebAssemblyComponents() - .AddAuthenticationStateSerialization(options => options.SerializeAllClaims = true); - -builder.Services.AddHttpForwarderWithServiceDiscovery(); -builder.Services.AddHttpContextAccessor(); builder.Services.AddScoped(); var app = builder.Build(); @@ -133,27 +119,20 @@ app.UseHttpsRedirection(); -app.MapStaticAssets(); app.UseAntiforgery(); -app.MapDefaultEndpoints(); +app.MapStaticAssets(); + +app.MapGet("/weather-forecast", ([FromServices] IWeatherForecaster WeatherForecaster) => +{ + return WeatherForecaster.GetWeatherForecastAsync(); +}).RequireAuthorization(); app.MapRazorComponents() .AddInteractiveServerRenderMode() .AddInteractiveWebAssemblyRenderMode() .AddAdditionalAssemblies(typeof(BlazorWebAppEntra.Client._Imports).Assembly); -app.MapForwarder("/weather-forecast", "https://weatherapi", transformBuilder => -{ - transformBuilder.AddRequestTransform(async transformContext => - { - var tokenAcquisition = transformContext.HttpContext.RequestServices.GetRequiredService(); - List scopes = [ "https://guardrexorg.onmicrosoft.com/edb4f62e-f83a-496e-9629-ed87ad546c62/Weather.Get" ]; - var accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(scopes); - transformContext.ProxyRequest.Headers.Authorization = new("Bearer", accessToken); - }); -}).RequireAuthorization(); - app.MapGroup("/authentication").MapLoginAndLogout(); app.Run(); diff --git a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra/Properties/launchSettings.json b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra/Properties/launchSettings.json index 5a5fcf3f4..1639e4223 100644 --- a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra/Properties/launchSettings.json +++ b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra/Properties/launchSettings.json @@ -1,15 +1,25 @@ { - "$schema": "http://json.schemastore.org/launchsettings.json", - "profiles": { - "https": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", - "applicationUrl": "https://localhost:5001;http://localhost:5000", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", + "applicationUrl": "http://localhost:5181", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", + "applicationUrl": "https://localhost:7062;http://localhost:5181", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } } } } -} diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/Weather/ServerWeatherForecaster.cs b/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra/Weather/ServerWeatherForecaster.cs similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/Weather/ServerWeatherForecaster.cs rename to 9.0/BlazorWebAppEntraBff/BlazorWebAppEntra/Weather/ServerWeatherForecaster.cs diff --git a/9.0/BlazorWebAppEntraBff/MinimalApiJwt/MinimalApiJwt.csproj b/9.0/BlazorWebAppEntraBff/MinimalApiJwt/MinimalApiJwt.csproj index dc607fcd5..e4005fa59 100644 --- a/9.0/BlazorWebAppEntraBff/MinimalApiJwt/MinimalApiJwt.csproj +++ b/9.0/BlazorWebAppEntraBff/MinimalApiJwt/MinimalApiJwt.csproj @@ -8,7 +8,6 @@ - diff --git a/9.0/BlazorWebAppEntraBff/MinimalApiJwt/Program.cs b/9.0/BlazorWebAppEntraBff/MinimalApiJwt/Program.cs index 3a3103672..02ef649dc 100644 --- a/9.0/BlazorWebAppEntraBff/MinimalApiJwt/Program.cs +++ b/9.0/BlazorWebAppEntraBff/MinimalApiJwt/Program.cs @@ -1,12 +1,9 @@ var builder = WebApplication.CreateBuilder(args); -// Add service defaults & Aspire components. -builder.AddServiceDefaults(); - builder.Services.AddAuthentication() .AddJwtBearer("Bearer", jwtOptions => { - // {TENANT ID} in the following examples is the directory (tenant) ID. + // {TENANT ID} is the directory (tenant) ID. // // Authority format {AUTHORITY} matches the issurer (`iss`) of the JWT returned by the identity provider. // @@ -43,8 +40,6 @@ // Configure the HTTP request pipeline. app.UseHttpsRedirection(); -app.MapDefaultEndpoints(); - var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" diff --git a/9.0/BlazorWebAppEntraBff/README.md b/9.0/BlazorWebAppEntraBff/README.md index 85466f9ea..e74f37cc7 100644 --- a/9.0/BlazorWebAppEntraBff/README.md +++ b/9.0/BlazorWebAppEntraBff/README.md @@ -1,33 +1,7 @@ -# Blazor Web App with Entra (BFF Pattern) +# Blazor Web App with Entra (without YARP and Aspire) -This sample features: - -* A Blazor Web App with global Auto interactivity. `PersistingAuthenticationStateProvider` and `PersistentAuthenticationStateProvider` services are added to the server and client Blazor apps to capture authentication state and flow it between the server and client. -* Authentication with Microsoft Entra using Microsoft Identity Web packages. -* A minimal API backend using the `JwtBearerHandler` to validate JWT tokens saved by the Blazor app using the in-memory token store for the access token. -* The BFF pattern using Aspire service discovery and YARP for proxying the requests to `/weatherforecast` on the backend using an access token generated for the web API on behalf of the user account for the user's claims. - -## Article for this sample app - -The article for this sample app is [Secure an ASP.NET Core Blazor Web App with Microsoft Entra ID (BFF pattern)](https://learn.microsoft.com/aspnet/core/blazor/security/blazor-web-app-with-entra?pivots=bff-pattern). - -If you need to open an issue that pertains to the coding of the sample app, open [an issue on this samples repo](https://github.com/dotnet/blazor-samples/issues). Otherwise, open an issue using the **Open a documentation issue** link/feedback form at the bottom of [the article](https://learn.microsoft.com/aspnet/core/blazor/security/blazor-web-app-with-entra?pivots=bff-pattern). - -## Configure the sample - -Configure the solution following the guidance in [Secure an ASP.NET Core Blazor Web App with Microsoft Entra ID (BFF pattern)](https://learn.microsoft.com/aspnet/core/blazor/security/blazor-web-app-with-entra?pivots=bff-pattern). +Sample app to accompany [Secure an ASP.NET Core Blazor Web App with Microsoft Entra ID (without YARP/Aspire)](https://learn.microsoft.com/aspnet/core/blazor/security/blazor-web-app-with-entra?pivots=without-yarp-and-aspire). ## Use a production distributed token cache provider -The sample app uses in-memory distributed token caches, but a production distributed token cache provider is recommended for production apps. For more information, see [Use a production distributed token cache provider](https://learn.microsoft.com/aspnet/core/blazor/security/blazor-web-app-with-entra?pivots=non-bff-pattern#use-a-production-distributed-token-cache-provider). - -## Run the sample - -### Visual Studio - -1. Open the `BlazorWebAppEntra` solution file in Visual Studio. -1. Select the `Aspire/Aspire.AppHost` project in **Solution Explorer** and start the app with either Visual Studio's Run button or by selecting **Start Debugging** from the **Debug** menu. - -### .NET CLI - -In a command shell, navigate to the `Aspire/Aspire.AppHost` project folder and use the `dotnet run` command to run the sample. The `BlazorWebAppEntra` and `MinimalApiJwt` projects are also started by the command. +The sample app uses in-memory distributed token caches, but a production distributed token cache provider is recommended for production apps. For more information, see [Use a production distributed token cache provider](https://learn.microsoft.com/aspnet/core/blazor/security/blazor-web-app-with-entra?pivots=without-yarp-and-aspire#use-a-production-distributed-token-cache-provider). diff --git a/9.0/BlazorWebAppEntraBff/Aspire/Aspire.AppHost/Aspire.AppHost.csproj b/9.0/BlazorWebAppEntraBffYarpAspire/Aspire/Aspire.AppHost/Aspire.AppHost.csproj similarity index 100% rename from 9.0/BlazorWebAppEntraBff/Aspire/Aspire.AppHost/Aspire.AppHost.csproj rename to 9.0/BlazorWebAppEntraBffYarpAspire/Aspire/Aspire.AppHost/Aspire.AppHost.csproj diff --git a/9.0/BlazorWebAppEntraBff/Aspire/Aspire.AppHost/Program.cs b/9.0/BlazorWebAppEntraBffYarpAspire/Aspire/Aspire.AppHost/Program.cs similarity index 100% rename from 9.0/BlazorWebAppEntraBff/Aspire/Aspire.AppHost/Program.cs rename to 9.0/BlazorWebAppEntraBffYarpAspire/Aspire/Aspire.AppHost/Program.cs diff --git a/9.0/BlazorWebAppEntraBff/Aspire/Aspire.AppHost/Properties/launchSettings.json b/9.0/BlazorWebAppEntraBffYarpAspire/Aspire/Aspire.AppHost/Properties/launchSettings.json similarity index 100% rename from 9.0/BlazorWebAppEntraBff/Aspire/Aspire.AppHost/Properties/launchSettings.json rename to 9.0/BlazorWebAppEntraBffYarpAspire/Aspire/Aspire.AppHost/Properties/launchSettings.json diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/wwwroot/appsettings.Development.json b/9.0/BlazorWebAppEntraBffYarpAspire/Aspire/Aspire.AppHost/appsettings.Development.json similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/wwwroot/appsettings.Development.json rename to 9.0/BlazorWebAppEntraBffYarpAspire/Aspire/Aspire.AppHost/appsettings.Development.json diff --git a/9.0/BlazorWebAppEntraBff/Aspire/Aspire.AppHost/appsettings.json b/9.0/BlazorWebAppEntraBffYarpAspire/Aspire/Aspire.AppHost/appsettings.json similarity index 100% rename from 9.0/BlazorWebAppEntraBff/Aspire/Aspire.AppHost/appsettings.json rename to 9.0/BlazorWebAppEntraBffYarpAspire/Aspire/Aspire.AppHost/appsettings.json diff --git a/9.0/BlazorWebAppEntraBff/Aspire/Aspire.ServiceDefaults/Aspire.ServiceDefaults.csproj b/9.0/BlazorWebAppEntraBffYarpAspire/Aspire/Aspire.ServiceDefaults/Aspire.ServiceDefaults.csproj similarity index 100% rename from 9.0/BlazorWebAppEntraBff/Aspire/Aspire.ServiceDefaults/Aspire.ServiceDefaults.csproj rename to 9.0/BlazorWebAppEntraBffYarpAspire/Aspire/Aspire.ServiceDefaults/Aspire.ServiceDefaults.csproj diff --git a/9.0/BlazorWebAppEntraBff/Aspire/Aspire.ServiceDefaults/Extensions.cs b/9.0/BlazorWebAppEntraBffYarpAspire/Aspire/Aspire.ServiceDefaults/Extensions.cs similarity index 100% rename from 9.0/BlazorWebAppEntraBff/Aspire/Aspire.ServiceDefaults/Extensions.cs rename to 9.0/BlazorWebAppEntraBffYarpAspire/Aspire/Aspire.ServiceDefaults/Extensions.cs diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/BlazorWebAppEntra.Client.csproj b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/BlazorWebAppEntra.Client.csproj similarity index 86% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/BlazorWebAppEntra.Client.csproj rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/BlazorWebAppEntra.Client.csproj index df54776f3..278b216a5 100644 --- a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/BlazorWebAppEntra.Client.csproj +++ b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/BlazorWebAppEntra.Client.csproj @@ -9,9 +9,9 @@ - - - + + + diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor similarity index 82% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor index 75416a4a1..a7e9ff016 100644 --- a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor +++ b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor @@ -25,15 +25,18 @@ protected override void OnInitialized() { - currentUrl = Navigation.Uri; + currentUrl = Navigation.ToBaseRelativePath(Navigation.Uri); Navigation.LocationChanged += OnLocationChanged; } private void OnLocationChanged(object? sender, LocationChangedEventArgs e) { - currentUrl = Navigation.Uri; + currentUrl = Navigation.ToBaseRelativePath(e.Location); StateHasChanged(); } - public void Dispose() => Navigation.LocationChanged -= OnLocationChanged; + public void Dispose() + { + Navigation.LocationChanged -= OnLocationChanged; + } } diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor.css b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor.css similarity index 97% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor.css rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor.css index 0a25914e8..52048247f 100644 --- a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor.css +++ b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/LogInOrOut.razor.css @@ -19,7 +19,6 @@ .nav-item { font-size: 0.9rem; padding-bottom: 0.5rem; - text-align: left; } .nav-item .nav-link { @@ -30,7 +29,7 @@ height: 3rem; display: flex; align-items: center; - text-align: left; + line-height: 3rem; width: 100%; } diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/MainLayout.razor b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/MainLayout.razor similarity index 93% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/MainLayout.razor rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/MainLayout.razor index 54adefe1a..2dc69b84e 100644 --- a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/MainLayout.razor +++ b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/MainLayout.razor @@ -21,7 +21,7 @@
-
+
An unhandled error has occurred. Reload 🗙 diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/MainLayout.razor.css b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/MainLayout.razor.css similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/MainLayout.razor.css rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/MainLayout.razor.css diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/NavMenu.razor b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/NavMenu.razor similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/NavMenu.razor rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/NavMenu.razor diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/NavMenu.razor.css b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/NavMenu.razor.css similarity index 99% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/NavMenu.razor.css rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/NavMenu.razor.css index a2aeace9c..4e15395e0 100644 --- a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Layout/NavMenu.razor.css +++ b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Layout/NavMenu.razor.css @@ -16,7 +16,7 @@ } .top-row { - min-height: 3.5rem; + height: 3.5rem; background-color: rgba(0,0,0,0.4); } diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Pages/Counter.razor b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Pages/Counter.razor similarity index 77% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Pages/Counter.razor rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Pages/Counter.razor index ef23cb316..413724776 100644 --- a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Pages/Counter.razor +++ b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Pages/Counter.razor @@ -11,8 +11,5 @@ @code { private int currentCount = 0; - private void IncrementCount() - { - currentCount++; - } + private void IncrementCount() => currentCount++; } diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Pages/Home.razor b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Pages/Home.razor similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Pages/Home.razor rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Pages/Home.razor diff --git a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Pages/UserClaims.razor b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Pages/UserClaims.razor similarity index 87% rename from 10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Pages/UserClaims.razor rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Pages/UserClaims.razor index a7b94a49d..af9efbaff 100644 --- a/10.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Pages/UserClaims.razor +++ b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Pages/UserClaims.razor @@ -1,4 +1,4 @@ -@page "/user-claims" +@page "/user-claims" @using System.Security.Claims @using Microsoft.AspNetCore.Authorization @attribute [Authorize] @@ -18,7 +18,7 @@ } @code { - private IEnumerable claims = []; + private IEnumerable claims = Enumerable.Empty(); [CascadingParameter] private Task? AuthState { get; set; } diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Pages/Weather.razor b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Pages/Weather.razor similarity index 51% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Pages/Weather.razor rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Pages/Weather.razor index 0e4c3ce1d..0abd39421 100644 --- a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Pages/Weather.razor +++ b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Pages/Weather.razor @@ -2,8 +2,6 @@ @using Microsoft.AspNetCore.Authorization @using BlazorWebAppEntra.Client.Weather @attribute [Authorize] -@implements IDisposable -@inject PersistentComponentState ApplicationState @inject IWeatherForecaster WeatherForecaster Weather @@ -22,8 +20,8 @@ else Date - Temp. (C) - Temp. (F) + Temp. (C) + Temp. (F) Summary @@ -43,29 +41,9 @@ else @code { private IEnumerable? forecasts; - private PersistingComponentStateSubscription persistingSubscription; protected override async Task OnInitializedAsync() { - if (!ApplicationState.TryTakeFromJson>(nameof(forecasts), out var restoredData)) - { - forecasts = await WeatherForecaster.GetWeatherForecastAsync(); - } - else - { - forecasts = restoredData!; - } - - // Call at the end to avoid a potential race condition at app shutdown - persistingSubscription = ApplicationState.RegisterOnPersisting(PersistData); - } - - private Task PersistData() - { - ApplicationState.PersistAsJson(nameof(forecasts), forecasts); - - return Task.CompletedTask; + forecasts = await WeatherForecaster.GetWeatherForecastAsync(); } - - void IDisposable.Dispose() => persistingSubscription.Dispose(); } diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Program.cs b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Program.cs similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Program.cs rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Program.cs diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/RedirectToLogin.razor b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/RedirectToLogin.razor similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/RedirectToLogin.razor rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/RedirectToLogin.razor diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Routes.razor b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Routes.razor similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Routes.razor rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Routes.razor diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Weather/ClientWeatherForecaster.cs b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Weather/ClientWeatherForecaster.cs similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Weather/ClientWeatherForecaster.cs rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Weather/ClientWeatherForecaster.cs diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Weather/IWeatherForecaster.cs b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Weather/IWeatherForecaster.cs similarity index 99% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Weather/IWeatherForecaster.cs rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Weather/IWeatherForecaster.cs index 5f1b6fd73..a2e54a299 100644 --- a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/Weather/IWeatherForecaster.cs +++ b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Weather/IWeatherForecaster.cs @@ -1,3 +1,4 @@ + namespace BlazorWebAppEntra.Client.Weather; public interface IWeatherForecaster diff --git a/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Weather/WeatherForecast.cs b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Weather/WeatherForecast.cs new file mode 100644 index 000000000..4ea41a45b --- /dev/null +++ b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/Weather/WeatherForecast.cs @@ -0,0 +1,9 @@ +namespace BlazorWebAppEntra.Client.Weather; + +public sealed class WeatherForecast +{ + public DateOnly Date { get; set; } + public int TemperatureC { get; set; } + public string? Summary { get; set; } + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); +} diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/_Imports.razor b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/_Imports.razor similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/_Imports.razor rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/_Imports.razor diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/appsettings.Development.json b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/wwwroot/appsettings.Development.json similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/appsettings.Development.json rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/wwwroot/appsettings.Development.json diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/wwwroot/appsettings.json b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/wwwroot/appsettings.json similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra.Client/wwwroot/appsettings.json rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.Client/wwwroot/appsettings.json diff --git a/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.sln b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.sln new file mode 100644 index 000000000..0d0b6cb6c --- /dev/null +++ b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra.sln @@ -0,0 +1,49 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.9.34407.89 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.AppHost", "Aspire\Aspire.AppHost\Aspire.AppHost.csproj", "{82AC1A9F-595F-4F64-95AA-54EEBEACD45D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorWebAppEntra", "BlazorWebAppEntra\BlazorWebAppEntra.csproj", "{FA543A49-C954-4504-8090-ABA55920B72B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorWebAppEntra.Client", "BlazorWebAppEntra.Client\BlazorWebAppEntra.Client.csproj", "{7B3838A1-D145-479C-9B79-6D2CD1775B71}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MinimalApiJwt", "MinimalApiJwt\MinimalApiJwt.csproj", "{4C7F50CB-A66D-4708-8B4D-6A0018B14784}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aspire.ServiceDefaults", "Aspire\Aspire.ServiceDefaults\Aspire.ServiceDefaults.csproj", "{4F6B20B6-25CD-45AB-A6E1-318EF3CCF854}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {82AC1A9F-595F-4F64-95AA-54EEBEACD45D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {82AC1A9F-595F-4F64-95AA-54EEBEACD45D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {82AC1A9F-595F-4F64-95AA-54EEBEACD45D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {82AC1A9F-595F-4F64-95AA-54EEBEACD45D}.Release|Any CPU.Build.0 = Release|Any CPU + {FA543A49-C954-4504-8090-ABA55920B72B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FA543A49-C954-4504-8090-ABA55920B72B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FA543A49-C954-4504-8090-ABA55920B72B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FA543A49-C954-4504-8090-ABA55920B72B}.Release|Any CPU.Build.0 = Release|Any CPU + {7B3838A1-D145-479C-9B79-6D2CD1775B71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7B3838A1-D145-479C-9B79-6D2CD1775B71}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7B3838A1-D145-479C-9B79-6D2CD1775B71}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7B3838A1-D145-479C-9B79-6D2CD1775B71}.Release|Any CPU.Build.0 = Release|Any CPU + {4C7F50CB-A66D-4708-8B4D-6A0018B14784}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4C7F50CB-A66D-4708-8B4D-6A0018B14784}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4C7F50CB-A66D-4708-8B4D-6A0018B14784}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4C7F50CB-A66D-4708-8B4D-6A0018B14784}.Release|Any CPU.Build.0 = Release|Any CPU + {4F6B20B6-25CD-45AB-A6E1-318EF3CCF854}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4F6B20B6-25CD-45AB-A6E1-318EF3CCF854}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4F6B20B6-25CD-45AB-A6E1-318EF3CCF854}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4F6B20B6-25CD-45AB-A6E1-318EF3CCF854}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {CB9D0BF2-DFA1-4B11-8188-9B3F35FCC226} + EndGlobalSection +EndGlobal diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/BlazorWebAppEntra.csproj b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/BlazorWebAppEntra.csproj similarity index 83% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/BlazorWebAppEntra.csproj rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/BlazorWebAppEntra.csproj index 063c8c534..88aea60b8 100644 --- a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/BlazorWebAppEntra.csproj +++ b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/BlazorWebAppEntra.csproj @@ -7,13 +7,15 @@ + - + + diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/Components/App.razor b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/Components/App.razor similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/Components/App.razor rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/Components/App.razor diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/Components/Pages/Error.razor b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/Components/Pages/Error.razor similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/Components/Pages/Error.razor rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/Components/Pages/Error.razor diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/Components/_Imports.razor b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/Components/_Imports.razor similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/Components/_Imports.razor rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/Components/_Imports.razor diff --git a/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/LoginLogoutEndpointRouteBuilderExtensions.cs b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/LoginLogoutEndpointRouteBuilderExtensions.cs new file mode 100644 index 000000000..df9c1aa88 --- /dev/null +++ b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/LoginLogoutEndpointRouteBuilderExtensions.cs @@ -0,0 +1,47 @@ +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authentication.Cookies; +using Microsoft.AspNetCore.Authentication.OpenIdConnect; +using Microsoft.AspNetCore.Mvc; + +namespace Microsoft.AspNetCore.Routing; + +internal static class LoginLogoutEndpointRouteBuilderExtensions +{ + internal static IEndpointConventionBuilder MapLoginAndLogout(this IEndpointRouteBuilder endpoints) + { + var group = endpoints.MapGroup(""); + + group.MapGet("/login", (string? returnUrl) => TypedResults.Challenge(GetAuthProperties(returnUrl))) + .AllowAnonymous(); + + // Sign out of the Cookie and OIDC handlers. If you do not sign out with the OIDC handler, + // the user will automatically be signed back in the next time they visit a page that requires authentication + // without being able to choose another account. + group.MapPost("/logout", ([FromForm] string? returnUrl) => TypedResults.SignOut(GetAuthProperties(returnUrl), + [CookieAuthenticationDefaults.AuthenticationScheme, OpenIdConnectDefaults.AuthenticationScheme])); + + return group; + } + + private static AuthenticationProperties GetAuthProperties(string? returnUrl) + { + // TODO: Use HttpContext.Request.PathBase instead. + const string pathBase = "/"; + + // Prevent open redirects. + if (string.IsNullOrEmpty(returnUrl)) + { + returnUrl = pathBase; + } + else if (!Uri.IsWellFormedUriString(returnUrl, UriKind.Relative)) + { + returnUrl = new Uri(returnUrl, UriKind.Absolute).PathAndQuery; + } + else if (returnUrl[0] != '/') + { + returnUrl = $"{pathBase}{returnUrl}"; + } + + return new AuthenticationProperties { RedirectUri = returnUrl }; + } +} diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/Program.cs b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/Program.cs similarity index 79% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/Program.cs rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/Program.cs index 398ef991e..bd4cdca63 100644 --- a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/Program.cs +++ b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/Program.cs @@ -1,25 +1,22 @@ using Azure.Identity; +using BlazorWebAppEntra; using BlazorWebAppEntra.Client.Weather; using BlazorWebAppEntra.Components; -using BlazorWebAppEntra.Weather; using Microsoft.AspNetCore.Authentication.OpenIdConnect; using Microsoft.AspNetCore.DataProtection; -using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Azure; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Identity.Web; using Microsoft.Identity.Web.TokenCacheProviders.Distributed; +using Microsoft.IdentityModel.Protocols.OpenIdConnect; +using Yarp.ReverseProxy.Transforms; var builder = WebApplication.CreateBuilder(args); -// Add services to the container. -// Remove or set 'SerializeAllClaims' to 'false' if you only want to -// serialize name and role claims for CSR. -builder.Services.AddRazorComponents() - .AddInteractiveServerComponents() - .AddInteractiveWebAssemblyComponents() - .AddAuthenticationStateSerialization(options => options.SerializeAllClaims = true); +// Add service defaults & Aspire components. +builder.AddServiceDefaults(); +// Add services to the container. builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(msIdentityOptions => { @@ -41,7 +38,7 @@ builder.Services.AddDistributedMemoryCache(); builder.Services.Configure( - options => + options => { // Disable L1 Cache default: false //options.DisableL1Cache = false; @@ -99,8 +96,25 @@ .ProtectKeysWithAzureKeyVault( new Uri("{KEY IDENTIFIER}"), credential); */ +builder.Services.AddOptions(OpenIdConnectDefaults.AuthenticationScheme).Configure(oidcOptions => +{ + oidcOptions.Scope.Add(OpenIdConnectScope.OfflineAccess); +}); + builder.Services.AddAuthorization(); +builder.Services.AddCascadingAuthenticationState(); + +// Remove or set 'SerializeAllClaims' to 'false' if you only want to +// serialize name and role claims for CSR. +builder.Services.AddRazorComponents() + .AddInteractiveServerComponents() + .AddMicrosoftIdentityConsentHandler() + .AddInteractiveWebAssemblyComponents() + .AddAuthenticationStateSerialization(options => options.SerializeAllClaims = true); + +builder.Services.AddHttpForwarderWithServiceDiscovery(); +builder.Services.AddHttpContextAccessor(); builder.Services.AddScoped(); var app = builder.Build(); @@ -119,20 +133,27 @@ app.UseHttpsRedirection(); -app.UseAntiforgery(); - app.MapStaticAssets(); +app.UseAntiforgery(); -app.MapGet("/weather-forecast", ([FromServices] IWeatherForecaster WeatherForecaster) => -{ - return WeatherForecaster.GetWeatherForecastAsync(); -}).RequireAuthorization(); +app.MapDefaultEndpoints(); app.MapRazorComponents() .AddInteractiveServerRenderMode() .AddInteractiveWebAssemblyRenderMode() .AddAdditionalAssemblies(typeof(BlazorWebAppEntra.Client._Imports).Assembly); +app.MapForwarder("/weather-forecast", "https://weatherapi", transformBuilder => +{ + transformBuilder.AddRequestTransform(async transformContext => + { + var tokenAcquisition = transformContext.HttpContext.RequestServices.GetRequiredService(); + List scopes = [ "https://guardrexorg.onmicrosoft.com/edb4f62e-f83a-496e-9629-ed87ad546c62/Weather.Get" ]; + var accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(scopes); + transformContext.ProxyRequest.Headers.Authorization = new("Bearer", accessToken); + }); +}).RequireAuthorization(); + app.MapGroup("/authentication").MapLoginAndLogout(); app.Run(); diff --git a/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/Properties/launchSettings.json b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/Properties/launchSettings.json new file mode 100644 index 000000000..5a5fcf3f4 --- /dev/null +++ b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/Properties/launchSettings.json @@ -0,0 +1,15 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "profiles": { + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", + "applicationUrl": "https://localhost:5001;http://localhost:5000", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/9.0/BlazorWebAppEntraBff/BlazorWebAppEntra/ServerWeatherForecaster.cs b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/ServerWeatherForecaster.cs similarity index 100% rename from 9.0/BlazorWebAppEntraBff/BlazorWebAppEntra/ServerWeatherForecaster.cs rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/ServerWeatherForecaster.cs diff --git a/9.0/BlazorWebAppEntra/MinimalApiJwt/appsettings.Development.json b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/appsettings.Development.json similarity index 100% rename from 9.0/BlazorWebAppEntra/MinimalApiJwt/appsettings.Development.json rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/appsettings.Development.json diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/appsettings.json b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/appsettings.json similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/appsettings.json rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/appsettings.json diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/app.css b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/app.css similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/app.css rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/app.css diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/favicon.png b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/favicon.png similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/favicon.png rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/favicon.png diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.css b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.css similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.css rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.css diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.css.map b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.css.map similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.css.map rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.css.map diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.min.css b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.min.css similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.min.css rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.min.css diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.min.css.map b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.min.css.map similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.min.css.map rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.rtl.min.css.map diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css.map b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css.map similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css.map rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css.map diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css.map b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css.map similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css.map rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css.map diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.css b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.css similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.css rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.css diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.css.map b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.css.map similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.css.map rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.css.map diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.min.css b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.min.css similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.min.css rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.min.css diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.min.css.map b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.min.css.map similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.min.css.map rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.min.css.map diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.css b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.css similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.css rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.css diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.css.map b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.css.map similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.css.map rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.css.map diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.min.css b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.min.css similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.min.css rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.min.css diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.min.css.map b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.min.css.map similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.min.css.map rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap-utilities.rtl.min.css.map diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.css b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.css similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.css rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.css diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.css b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.css similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.css rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.css diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.css.map b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.css.map similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.css.map rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.css.map diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.min.css b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.min.css similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.min.css rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.min.css diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.min.css.map b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.min.css.map similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.min.css.map rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/css/bootstrap.rtl.min.css.map diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.js b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.js similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.js rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.js diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.js.map b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.js.map similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.js.map rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.js.map diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js.map b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js.map similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js.map rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.esm.min.js.map diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.js b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.js similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.js rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.js diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js diff --git a/9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map b/9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map similarity index 100% rename from 9.0/BlazorWebAppEntra/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map rename to 9.0/BlazorWebAppEntraBffYarpAspire/BlazorWebAppEntra/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map diff --git a/9.0/BlazorWebAppEntra/MinimalApiJwt/MinimalApiJwt.csproj b/9.0/BlazorWebAppEntraBffYarpAspire/MinimalApiJwt/MinimalApiJwt.csproj similarity index 82% rename from 9.0/BlazorWebAppEntra/MinimalApiJwt/MinimalApiJwt.csproj rename to 9.0/BlazorWebAppEntraBffYarpAspire/MinimalApiJwt/MinimalApiJwt.csproj index e4005fa59..dc607fcd5 100644 --- a/9.0/BlazorWebAppEntra/MinimalApiJwt/MinimalApiJwt.csproj +++ b/9.0/BlazorWebAppEntraBffYarpAspire/MinimalApiJwt/MinimalApiJwt.csproj @@ -8,6 +8,7 @@ + diff --git a/9.0/BlazorWebAppEntra/MinimalApiJwt/MinimalApiJwt.http b/9.0/BlazorWebAppEntraBffYarpAspire/MinimalApiJwt/MinimalApiJwt.http similarity index 100% rename from 9.0/BlazorWebAppEntra/MinimalApiJwt/MinimalApiJwt.http rename to 9.0/BlazorWebAppEntraBffYarpAspire/MinimalApiJwt/MinimalApiJwt.http diff --git a/9.0/BlazorWebAppEntra/MinimalApiJwt/Program.cs b/9.0/BlazorWebAppEntraBffYarpAspire/MinimalApiJwt/Program.cs similarity index 92% rename from 9.0/BlazorWebAppEntra/MinimalApiJwt/Program.cs rename to 9.0/BlazorWebAppEntraBffYarpAspire/MinimalApiJwt/Program.cs index 02ef649dc..3a3103672 100644 --- a/9.0/BlazorWebAppEntra/MinimalApiJwt/Program.cs +++ b/9.0/BlazorWebAppEntraBffYarpAspire/MinimalApiJwt/Program.cs @@ -1,9 +1,12 @@ var builder = WebApplication.CreateBuilder(args); +// Add service defaults & Aspire components. +builder.AddServiceDefaults(); + builder.Services.AddAuthentication() .AddJwtBearer("Bearer", jwtOptions => { - // {TENANT ID} is the directory (tenant) ID. + // {TENANT ID} in the following examples is the directory (tenant) ID. // // Authority format {AUTHORITY} matches the issurer (`iss`) of the JWT returned by the identity provider. // @@ -40,6 +43,8 @@ // Configure the HTTP request pipeline. app.UseHttpsRedirection(); +app.MapDefaultEndpoints(); + var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" diff --git a/9.0/BlazorWebAppEntra/MinimalApiJwt/Properties/launchSettings.json b/9.0/BlazorWebAppEntraBffYarpAspire/MinimalApiJwt/Properties/launchSettings.json similarity index 100% rename from 9.0/BlazorWebAppEntra/MinimalApiJwt/Properties/launchSettings.json rename to 9.0/BlazorWebAppEntraBffYarpAspire/MinimalApiJwt/Properties/launchSettings.json diff --git a/9.0/BlazorWebAppEntraBff/Aspire/Aspire.AppHost/appsettings.Development.json b/9.0/BlazorWebAppEntraBffYarpAspire/MinimalApiJwt/appsettings.Development.json similarity index 100% rename from 9.0/BlazorWebAppEntraBff/Aspire/Aspire.AppHost/appsettings.Development.json rename to 9.0/BlazorWebAppEntraBffYarpAspire/MinimalApiJwt/appsettings.Development.json diff --git a/9.0/BlazorWebAppEntra/MinimalApiJwt/appsettings.json b/9.0/BlazorWebAppEntraBffYarpAspire/MinimalApiJwt/appsettings.json similarity index 100% rename from 9.0/BlazorWebAppEntra/MinimalApiJwt/appsettings.json rename to 9.0/BlazorWebAppEntraBffYarpAspire/MinimalApiJwt/appsettings.json diff --git a/9.0/BlazorWebAppEntraBffYarpAspire/README.md b/9.0/BlazorWebAppEntraBffYarpAspire/README.md new file mode 100644 index 000000000..2d620ffac --- /dev/null +++ b/9.0/BlazorWebAppEntraBffYarpAspire/README.md @@ -0,0 +1,33 @@ +# Blazor Web App with Entra (with YARP and Aspire) + +This sample features: + +* A Blazor Web App with global Auto interactivity. `PersistingAuthenticationStateProvider` and `PersistentAuthenticationStateProvider` services are added to the server and client Blazor apps to capture authentication state and flow it between the server and client. +* Authentication with Microsoft Entra using Microsoft Identity Web packages. +* A minimal API backend using the `JwtBearerHandler` to validate JWT tokens saved by the Blazor app using the in-memory token store for the access token. +* The BFF pattern using Aspire service discovery and YARP for proxying the requests to `/weatherforecast` on the backend using an access token generated for the web API on behalf of the user account for the user's claims. + +## Article for this sample app + +The article for this sample app is [Secure an ASP.NET Core Blazor Web App with Microsoft Entra ID (BFF pattern)](https://learn.microsoft.com/aspnet/core/blazor/security/blazor-web-app-with-entra?pivots=with-yarp-and-aspire). + +If you need to open an issue that pertains to the coding of the sample app, open [an issue on this samples repo](https://github.com/dotnet/blazor-samples/issues). Otherwise, open an issue using the **Open a documentation issue** link/feedback form at the bottom of [the article](https://learn.microsoft.com/aspnet/core/blazor/security/blazor-web-app-with-entra?pivots=with-yarp-and-aspire). + +## Configure the sample + +Configure the solution following the guidance in [Secure an ASP.NET Core Blazor Web App with Microsoft Entra ID (BFF pattern)](https://learn.microsoft.com/aspnet/core/blazor/security/blazor-web-app-with-entra?pivots=with-yarp-and-aspire). + +## Use a production distributed token cache provider + +The sample app uses in-memory distributed token caches, but a production distributed token cache provider is recommended for production apps. For more information, see [Use a production distributed token cache provider](https://learn.microsoft.com/aspnet/core/blazor/security/blazor-web-app-with-entra?pivots=with-yarp-and-aspire#use-a-production-distributed-token-cache-provider). + +## Run the sample + +### Visual Studio + +1. Open the `BlazorWebAppEntra` solution file in Visual Studio. +1. Select the `Aspire/Aspire.AppHost` project in **Solution Explorer** and start the app with either Visual Studio's Run button or by selecting **Start Debugging** from the **Debug** menu. + +### .NET CLI + +In a command shell, navigate to the `Aspire/Aspire.AppHost` project folder and use the `dotnet run` command to run the sample. The `BlazorWebAppEntra` and `MinimalApiJwt` projects are also started by the command. diff --git a/README.md b/README.md index 77c13ef87..b80d0748f 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ git sparse-checkout set 9.0/BlazorSample_BlazorWebApp * Blazor Web App movie database app tutorial (`BlazorWebAppMovies`)
[Build a Blazor movie database app](https://learn.microsoft.com/aspnet/core/blazor/tutorials/movie-database-app) -* Blazor Web App with Microsoft Entra ID (`BlazorWebAppEntra`/`BlazorWebAppEntraBff`)
[Secure an ASP.NET Core Blazor Web App with Microsoft Entra ID](https://learn.microsoft.com/aspnet/core/blazor/security/blazor-web-app-with-entra) +* Blazor Web App with Microsoft Entra ID (`BlazorWebAppEntraBff`/`BlazorWebAppEntraBffYarpAspire`)
[Secure an ASP.NET Core Blazor Web App with Microsoft Entra ID](https://learn.microsoft.com/aspnet/core/blazor/security/blazor-web-app-with-entra) * Blazor Web App with OIDC and Aspire (`BlazorWebAppOidcBff`/`BlazorWebAppOidc`)
[Secure an ASP.NET Core Blazor Web App with OpenID Connect (OIDC)](https://learn.microsoft.com/aspnet/core/blazor/security/blazor-web-app-with-oidc)