diff --git a/NRZMyk.Components/App.razor b/NRZMyk.Components/App.razor index 72d5ca3..6052977 100644 --- a/NRZMyk.Components/App.razor +++ b/NRZMyk.Components/App.razor @@ -3,22 +3,12 @@ - @**@ - -

Sorry, there's nothing at this address.

-
-
-
- -@* - - - - +

Sorry, there's nothing at this address.

-
-
*@ \ No newline at end of file + + + \ No newline at end of file diff --git a/NRZMyk.Components/Pages/Counter.razor b/NRZMyk.Components/Pages/Counter.razor index 9c37bac..fcb3342 100644 --- a/NRZMyk.Components/Pages/Counter.razor +++ b/NRZMyk.Components/Pages/Counter.razor @@ -3,4 +3,6 @@

Counter

Current count: @CurrentCount

+

Groups: @Groups

+

Roles: @Roles

diff --git a/NRZMyk.Components/Pages/CounterBase.cs b/NRZMyk.Components/Pages/CounterBase.cs index 3b2544e..d96c640 100644 --- a/NRZMyk.Components/Pages/CounterBase.cs +++ b/NRZMyk.Components/Pages/CounterBase.cs @@ -1,12 +1,32 @@ -using Microsoft.AspNetCore.Components; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Authorization; namespace NRZMyk.Components.Pages { public class CounterBase : ComponentBase { + [Inject] + public AuthenticationStateProvider AuthenticationStateProvider { get; set; } + public int CurrentCount { get; set; } - public void IncrementCount() + public string Groups { get; set; } + + public string Roles { get; set; } + + protected override async Task OnInitializedAsync() + { + var state = await AuthenticationStateProvider.GetAuthenticationStateAsync(); + var user = state.User; + var claims = user.Claims; + Groups = string.Join(",", claims.Where(c => c.Type == "groups").Select(c => c.Value)); + Roles = string.Join(",", claims.Where(c => c.Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/role").Select(c => c.Value)); + await base.OnInitializedAsync(); + } + + public async Task IncrementCount() { CurrentCount++; } diff --git a/NRZMyk.Components/Pages/Writer.razor b/NRZMyk.Components/Pages/Writer.razor new file mode 100644 index 0000000..feb833a --- /dev/null +++ b/NRZMyk.Components/Pages/Writer.razor @@ -0,0 +1,5 @@ +@page "/writer" +@attribute [Authorize(Roles = "Writer")] + +

Writer

+

Access allowed for writer role only

\ No newline at end of file diff --git a/NRZMyk.Components/Shared/LoginDisplay.razor b/NRZMyk.Components/Shared/LoginDisplay.razor index fc4422a..b4a00b9 100644 --- a/NRZMyk.Components/Shared/LoginDisplay.razor +++ b/NRZMyk.Components/Shared/LoginDisplay.razor @@ -1,9 +1,9 @@  Hello, @context.User.Identity.Name! - Log out + Log out - Log in + Log in - + \ No newline at end of file diff --git a/NRZMyk.Components/Shared/NavMenu.razor b/NRZMyk.Components/Shared/NavMenu.razor index d01df03..4696604 100644 --- a/NRZMyk.Components/Shared/NavMenu.razor +++ b/NRZMyk.Components/Shared/NavMenu.razor @@ -24,5 +24,17 @@ Fetch data + + + + + + diff --git a/NRZMyk.Server/Areas/AzureAD/Pages/Account/SignedOut.cshtml b/NRZMyk.Server/Areas/AzureAD/Pages/Account/SignedOut.cshtml deleted file mode 100644 index 3af2f4f..0000000 --- a/NRZMyk.Server/Areas/AzureAD/Pages/Account/SignedOut.cshtml +++ /dev/null @@ -1,7 +0,0 @@ -@page -@functions { - public async Task OnGet() - { - return Redirect("~/"); - } -} \ No newline at end of file diff --git a/NRZMyk.Server/Areas/MicrosoftIdentity/Pages/Account/SignedOut.cshtml b/NRZMyk.Server/Areas/MicrosoftIdentity/Pages/Account/SignedOut.cshtml new file mode 100644 index 0000000..e9fcf3d --- /dev/null +++ b/NRZMyk.Server/Areas/MicrosoftIdentity/Pages/Account/SignedOut.cshtml @@ -0,0 +1,7 @@ +@page +@functions { + public async Task OnGet() + { + return Redirect("~/"); + } +} \ No newline at end of file diff --git a/NRZMyk.Server/Areas/MicrosoftIdentity/Pages/Account/SignedOut.cshtml.cs b/NRZMyk.Server/Areas/MicrosoftIdentity/Pages/Account/SignedOut.cshtml.cs new file mode 100644 index 0000000..e870190 --- /dev/null +++ b/NRZMyk.Server/Areas/MicrosoftIdentity/Pages/Account/SignedOut.cshtml.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace NRZMyk.Server.Areas.MicrosoftIdentity.Account +{ + public class SignedOutModel : PageModel + { + public void OnGet() + { + } + } +} diff --git a/NRZMyk.Server/Connected Services/Application Insights/ConnectedService.json b/NRZMyk.Server/Connected Services/Application Insights/ConnectedService.json new file mode 100644 index 0000000..01dfb96 --- /dev/null +++ b/NRZMyk.Server/Connected Services/Application Insights/ConnectedService.json @@ -0,0 +1,4 @@ +{ + "ProviderId": "Microsoft.ApplicationInsights.ConnectedService.ConnectedServiceProvider", + "Version": "16.0.0.0" +} \ No newline at end of file diff --git a/NRZMyk.Server/NRZMyk.Server.csproj b/NRZMyk.Server/NRZMyk.Server.csproj index 76b6d2a..9870e22 100644 --- a/NRZMyk.Server/NRZMyk.Server.csproj +++ b/NRZMyk.Server/NRZMyk.Server.csproj @@ -1,4 +1,4 @@ - + netcoreapp3.1 @@ -7,10 +7,12 @@ - + + + @@ -19,4 +21,8 @@ + + + + diff --git a/NRZMyk.Server/Properties/serviceDependencies.json b/NRZMyk.Server/Properties/serviceDependencies.json new file mode 100644 index 0000000..66741d6 --- /dev/null +++ b/NRZMyk.Server/Properties/serviceDependencies.json @@ -0,0 +1,8 @@ +{ + "dependencies": { + "appInsights1": { + "type": "appInsights", + "connectionId": null + } + } +} \ No newline at end of file diff --git a/NRZMyk.Server/Properties/serviceDependencies.local.json b/NRZMyk.Server/Properties/serviceDependencies.local.json new file mode 100644 index 0000000..8350d04 --- /dev/null +++ b/NRZMyk.Server/Properties/serviceDependencies.local.json @@ -0,0 +1,8 @@ +{ + "dependencies": { + "appInsights1": { + "type": "appInsights.sdk", + "connectionId": null + } + } +} \ No newline at end of file diff --git a/NRZMyk.Server/Startup.cs b/NRZMyk.Server/Startup.cs index 789eb01..a28d77b 100644 --- a/NRZMyk.Server/Startup.cs +++ b/NRZMyk.Server/Startup.cs @@ -1,5 +1,5 @@ using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authentication.AzureAD.UI; +using Microsoft.AspNetCore.Authentication.OpenIdConnect; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Components.Authorization; @@ -11,6 +11,8 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using Microsoft.Identity.Web; +using Microsoft.Identity.Web.UI; using NRZMyk.Services.Data; using NRZMyk.Services.Service; @@ -29,8 +31,7 @@ public Startup(IConfiguration configuration) // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { - services.AddAuthentication(AzureADDefaults.AuthenticationScheme) - .AddAzureAD(options => Configuration.Bind("AzureAd", options)); + services.AddSignIn(Configuration); services.AddControllersWithViews(options => { @@ -40,16 +41,18 @@ public void ConfigureServices(IServiceCollection services) options.Filters.Add(new AuthorizeFilter(policy)); }); - services.AddMvc().AddRazorPagesOptions(options => { options.RootDirectory = "/"; }); services.AddDbContext(options => options.UseSqlServer( Configuration.GetConnectionString("DefaultConnection"))); - services.AddRazorPages(); + services.AddRazorPages().AddMicrosoftIdentityUI(); services.AddServerSideBlazor(); services.AddSingleton(); + + services.AddApplicationInsightsTelemetry(); } + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { diff --git a/NRZMyk.Server/appsettings.json b/NRZMyk.Server/appsettings.json index c47d53f..6b9567a 100644 --- a/NRZMyk.Server/appsettings.json +++ b/NRZMyk.Server/appsettings.json @@ -11,10 +11,11 @@ }, "AzureAd": { "Instance": "https://login.microsoftonline.com/", - "Domain": "", - "TenantId": "", - "ClientId": "", - "CallbackPath": "/signin-oidc" + "Domain": "[Enter the domain of your tenant, e.g. contoso.onmicrosoft.com]", + "TenantId": "[Enter 'common', or 'organizations' or the Tenant Id (Obtained from the Azure portal. Select 'Endpoints' from the 'App registrations' blade and use the GUID in any of the URLs), e.g. da41245a5-11b3-996c-00a8-4d99re19f292]", + "ClientId": "[Enter the Client Id (Application ID obtained from the Azure portal), e.g. ba74781c2-53c2-442a-97c2-3d60re42f403]", + "CallbackPath": "/signin-oidc", + "SignedOutCallbackPath ": "/signout-callback-oidc" }, "AllowedHosts": "*" } diff --git a/README.md b/README.md index ba41920..151623c 100644 --- a/README.md +++ b/README.md @@ -27,4 +27,15 @@ This app authenticates with Azure AD. In order to run it locally you need to con - `AzureAd__Domain`: Your domain - `AzureAd__TenantId`: Your tenant ID -- `AzureAd__ClientId`: Your apps client ID \ No newline at end of file +- `AzureAd__ClientId`: Your apps client ID + +## Deployment setup + +### Fix Azure AD redirect issues + +There are cases where RedirectUri is needed, for instance when you use a reverse proxy that transforms HTTPS +URLs (external world) to HTTP URLs (inside the protected area). This can also be useful for Web apps running +in containers (for the same reasons). I.e. in case that AAD tries to redirect to +you would need to override the following config value: + +- `AzureAd__RedirectUri`: `` \ No newline at end of file