From fb30189a4ac813344786e907f81469ccbbb44615 Mon Sep 17 00:00:00 2001 From: Rick Anderson <3605364+Rick-Anderson@users.noreply.github.com> Date: Thu, 23 Jul 2020 17:28:20 -1000 Subject: [PATCH] Doc global require authenticated users (#18825) * Doc global require authenticated usesrs * Doc global require authenticated usesrs * Doc global require authenticated usesrs * Doc global require authenticated usesrs * Doc global require authenticated usesrs * work * react to tratcher feedback * react to feedback * Update aspnetcore/security/authorization/secure-data.md Co-authored-by: Chris Ross Co-authored-by: Chris Ross --- aspnetcore/includes/requireAuth.md | 1 + .../authentication/identity-configuration.md | 4 + .../security/authentication/identity.md | 2 + aspnetcore/security/authentication/index.md | 1 + aspnetcore/security/authorization/policies.md | 5 +- .../security/authorization/secure-data.md | 42 +++++--- .../secure-data/samples/final3/Startup.cs | 32 +++--- .../secure-data/samples/final3/Startup2.cs | 98 +++++++++++++++++++ aspnetcore/security/authorization/simple.md | 2 + 9 files changed, 150 insertions(+), 37 deletions(-) create mode 100644 aspnetcore/includes/requireAuth.md create mode 100644 aspnetcore/security/authorization/secure-data/samples/final3/Startup2.cs diff --git a/aspnetcore/includes/requireAuth.md b/aspnetcore/includes/requireAuth.md new file mode 100644 index 0000000000..b2f81fee70 --- /dev/null +++ b/aspnetcore/includes/requireAuth.md @@ -0,0 +1 @@ +For information on how to globally require all users to be authenticated, see [Require authenticated users](xref:security/authorization/secure-data#rau). \ No newline at end of file diff --git a/aspnetcore/security/authentication/identity-configuration.md b/aspnetcore/security/authentication/identity-configuration.md index 439a376d4f..6d7fe94f89 100644 --- a/aspnetcore/security/authentication/identity-configuration.md +++ b/aspnetcore/security/authentication/identity-configuration.md @@ -139,3 +139,7 @@ services.Configure(option => option.IterationCount = 12000; }); ``` + +## Globally require all users to be authenticated + +[!INCLUDE[](~/includes/requireAuth.md)] \ No newline at end of file diff --git a/aspnetcore/security/authentication/identity.md b/aspnetcore/security/authentication/identity.md index dda1804b08..35842c3a0c 100644 --- a/aspnetcore/security/authentication/identity.md +++ b/aspnetcore/security/authentication/identity.md @@ -20,6 +20,8 @@ ASP.NET Core Identity: Users can create an account with the login information stored in Identity or they can use an external login provider. Supported external login providers include [Facebook, Google, Microsoft Account, and Twitter](xref:security/authentication/social/index). +[!INCLUDE[](~/includes/requireAuth.md)] + The [Identity source code](https://github.com/dotnet/AspNetCore/tree/master/src/Identity) is available on GitHub. [Scaffold Identity](xref:security/authentication/scaffold-identity) and view the generated files to review the template interaction with Identity. Identity is typically configured using a SQL Server database to store user names, passwords, and profile data. Alternatively, another persistent store can be used, for example, Azure Table Storage. diff --git a/aspnetcore/security/authentication/index.md b/aspnetcore/security/authentication/index.md index d3c95b8cb4..045c03e391 100644 --- a/aspnetcore/security/authentication/index.md +++ b/aspnetcore/security/authentication/index.md @@ -123,3 +123,4 @@ See the [Orchard Core](https://github.com/OrchardCMS/OrchardCore) source for an * * * +* [Globally require authenticated users](xref:security/authorization/secure-data#rau) \ No newline at end of file diff --git a/aspnetcore/security/authorization/policies.md b/aspnetcore/security/authorization/policies.md index b3fb7c3d61..070bd99558 100644 --- a/aspnetcore/security/authorization/policies.md +++ b/aspnetcore/security/authorization/policies.md @@ -239,8 +239,11 @@ if (context.Resource is AuthorizationFilterContext mvcContext) } ``` -::: moniker-end +## Globally require all users to be authenticated +[!INCLUDE[](~/includes/requireAuth.md)] + +::: moniker-end ::: moniker range="< aspnetcore-3.0" diff --git a/aspnetcore/security/authorization/secure-data.md b/aspnetcore/security/authorization/secure-data.md index 510527a82d..73724bf82d 100644 --- a/aspnetcore/security/authorization/secure-data.md +++ b/aspnetcore/security/authorization/secure-data.md @@ -1,24 +1,18 @@ --- title: Create an ASP.NET Core app with user data protected by authorization author: rick-anderson -description: Learn how to create a Razor Pages app with user data protected by authorization. Includes HTTPS, authentication, security, ASP.NET Core Identity. +description: Learn how to create an ASP.NET Core web app with user data protected by authorization. Includes HTTPS, authentication, security, ASP.NET Core Identity. ms.author: riande -ms.date: 12/18/2018 +ms.date: 7/18/2020 ms.custom: "mvc, seodec18" no-loc: [Blazor, "Blazor Server", "Blazor WebAssembly", "Identity", "Let's Encrypt", Razor, SignalR] uid: security/authorization/secure-data --- -# Create an ASP.NET Core app with user data protected by authorization +# Create an ASP.NET Core web app with user data protected by authorization By [Rick Anderson](https://twitter.com/RickAndMSFT) and [Joe Audette](https://twitter.com/joeaudette) -::: moniker range="<= aspnetcore-1.1" - -See [this PDF](https://webpifeed.blob.core.windows.net/webpifeed/Partners/asp.net_repo_pdf_1-16-18.pdf) for the ASP.NET Core MVC version. The ASP.NET Core 1.1 version of this tutorial is in [this](https://github.com/dotnet/AspNetCore.Docs/tree/master/aspnetcore/security/authorization/secure-data) folder. The 1.1 ASP.NET Core sample is in the [samples](https://github.com/dotnet/AspNetCore.Docs/tree/master/aspnetcore/security/authorization/secure-data/samples/final2). - -::: moniker-end - ::: moniker range="= aspnetcore-2.0" See [this pdf](https://webpifeed.blob.core.windows.net/webpifeed/Partners/asp.net_repo_pdf_July16_18.pdf) @@ -110,15 +104,33 @@ Append [AddRoles](/dotnet/api/microsoft.aspnetcore.identity.identitybuilder.addr [!code-csharp[](secure-data/samples/final3/Startup.cs?name=snippet2&highlight=9)] + + ### Require authenticated users -Set the default authentication policy to require users to be authenticated: +Set the fallback authentication policy to require users to be authenticated: -[!code-csharp[](secure-data/samples/final3/Startup.cs?name=snippet&highlight=15-99)] +[!code-csharp[](secure-data/samples/final3/Startup.cs?name=snippet&highlight=13-99)] - You can opt out of authentication at the Razor Page, controller, or action method level with the `[AllowAnonymous]` attribute. Setting the default authentication policy to require users to be authenticated protects newly added Razor Pages and controllers. Having authentication required by default is more secure than relying on new controllers and Razor Pages to include the `[Authorize]` attribute. +The preceding highlighted code sets the [fallback authentication policy](xref:Microsoft.AspNetCore.Authorization.AuthorizationOptions.FallbackPolicy). The fallback authentication policy requires ***all*** users to be authenticated, except for Razor Pages, controllers, or action methods with an authentication attribute. For example, Razor Pages, controllers, or action methods with `[AllowAnonymous]` or `[Authorize(PolicyName="MyPolicy")]` use the applied authentication attribute rather than the fallback authentication policy. -Add [AllowAnonymous](/dotnet/api/microsoft.aspnetcore.authorization.allowanonymousattribute) to the Index and Privacy pages so anonymous users can get information about the site before they register. +The fallback authentication policy: + +* Is applied to all requests that do not explicitly specify an authentication policy. For requests served by endpoint routing, this would include any endpoint that does not specify an authorization attribute. For requests served by other middleware after the authorization middleware, such as [static files](xref:fundamentals/static-files), this would apply the policy to all requests. + +Setting the fallback authentication policy to require users to be authenticated protects newly added Razor Pages and controllers. Having authentication required by default is more secure than relying on new controllers and Razor Pages to include the `[Authorize]` attribute. + +The class also contains . The `DefaultPolicy` is the policy used with the `[Authorize]` attribute when no policy is specified. `[Authorize]` doesn't contain a named policy, unlike `[Authorize(PolicyName="MyPolicy")]`. + +For more information on policies, see . + +An alternative way for MVC controllers and Razor Pages to require all users be authenticated is adding an authorization filter: + +[!code-csharp[](secure-data/samples/final3/Startup2.cs?name=snippet&highlight=14-99)] + +The preceding code uses an authorization filter, setting the fallback policy uses endpoint routing. Setting the fallback policy is the preferred way to require all users be authenticated. + +Add [AllowAnonymous](/dotnet/api/microsoft.aspnetcore.authorization.allowanonymousattribute) to the `Index` and `Privacy` pages so anonymous users can get information about the site before they register: [!code-csharp[](secure-data/samples/final3/Pages/Index.cshtml.cs?highlight=1,7)] @@ -272,7 +284,7 @@ See [this issue](https://github.com/dotnet/AspNetCore.Docs/issues/8502) for info ## Differences between Challenge and Forbid -This app sets the default policy to [require authenticated users](#require-authenticated-users). The following code allows anonymous users. Anonymous users are allowed to show the differences between Challenge vs Forbid. +This app sets the default policy to [require authenticated users](#rau). The following code allows anonymous users. Anonymous users are allowed to show the differences between Challenge vs Forbid. [!code-csharp[](secure-data/samples/final3/Pages/Contacts/Details2.cshtml.cs?name=snippet)] @@ -444,7 +456,7 @@ dotnet ef database update Append [AddRoles](/dotnet/api/microsoft.aspnetcore.identity.identitybuilder.addroles#Microsoft_AspNetCore_Identity_IdentityBuilder_AddRoles__1) to add Role services: -[!code-csharp[](secure-data/samples/final2.1/Startup.cs?name=snippet2&highlight=12)] +[!code-csharp[](secure-data/samples/final2.1/Startup.cs?name=snippet2&highlight=11)] ### Require authenticated users diff --git a/aspnetcore/security/authorization/secure-data/samples/final3/Startup.cs b/aspnetcore/security/authorization/secure-data/samples/final3/Startup.cs index 4701eba139..3be681031e 100644 --- a/aspnetcore/security/authorization/secure-data/samples/final3/Startup.cs +++ b/aspnetcore/security/authorization/secure-data/samples/final3/Startup.cs @@ -1,20 +1,13 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Identity.UI; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.HttpsPolicy; -using Microsoft.EntityFrameworkCore; +using ContactManager.Authorization; using ContactManager.Data; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Identity; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc.Authorization; -using ContactManager.Authorization; namespace ContactManager { @@ -32,7 +25,6 @@ namespace ContactManager #region snippet2 public void ConfigureServices(IServiceCollection services) { - services.AddDbContext(options => options.UseSqlServer( Configuration.GetConnectionString("DefaultConnection"))); @@ -44,16 +36,14 @@ namespace ContactManager services.AddRazorPages(); - services.AddControllers(config => + services.AddAuthorization(options => { - // using Microsoft.AspNetCore.Mvc.Authorization; - // using Microsoft.AspNetCore.Authorization; - var policy = new AuthorizationPolicyBuilder() - .RequireAuthenticatedUser() - .Build(); - config.Filters.Add(new AuthorizeFilter(policy)); + options.FallbackPolicy = new AuthorizationPolicyBuilder() + .RequireAuthenticatedUser() + .Build(); }); #endregion + // Authorization handlers. services.AddScoped(); diff --git a/aspnetcore/security/authorization/secure-data/samples/final3/Startup2.cs b/aspnetcore/security/authorization/secure-data/samples/final3/Startup2.cs new file mode 100644 index 0000000000..41f259ab6a --- /dev/null +++ b/aspnetcore/security/authorization/secure-data/samples/final3/Startup2.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Identity.UI; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.HttpsPolicy; +using Microsoft.EntityFrameworkCore; +using ContactManager.Data; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc.Authorization; +using ContactManager.Authorization; + +namespace ContactManager +{ + public class Startup2 + { + public Startup2(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + #region snippet_defaultPolicy + #region snippet + #region snippet2 + public void ConfigureServices(IServiceCollection services) + { + + services.AddDbContext(options => + options.UseSqlServer( + Configuration.GetConnectionString("DefaultConnection"))); + services.AddDefaultIdentity( + options => options.SignIn.RequireConfirmedAccount = true) + .AddRoles() + .AddEntityFrameworkStores(); + #endregion + + services.AddRazorPages(); + + services.AddControllers(config => + { + // using Microsoft.AspNetCore.Mvc.Authorization; + // using Microsoft.AspNetCore.Authorization; + var policy = new AuthorizationPolicyBuilder() + .RequireAuthenticatedUser() + .Build(); + config.Filters.Add(new AuthorizeFilter(policy)); + }); + #endregion + // Authorization handlers. + services.AddScoped(); + + services.AddSingleton(); + + services.AddSingleton(); + } + #endregion + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + app.UseDatabaseErrorPage(); + } + else + { + app.UseExceptionHandler("/Error"); + // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. + app.UseHsts(); + } + + app.UseHttpsRedirection(); + app.UseStaticFiles(); + + app.UseRouting(); + + app.UseAuthentication(); + app.UseAuthorization(); + + app.UseEndpoints(endpoints => + { + endpoints.MapRazorPages(); + }); + } + } +} diff --git a/aspnetcore/security/authorization/simple.md b/aspnetcore/security/authorization/simple.md index f45afbecf0..1cdb0ddc52 100644 --- a/aspnetcore/security/authorization/simple.md +++ b/aspnetcore/security/authorization/simple.md @@ -69,6 +69,8 @@ This would allow only authenticated users to the `AccountController`, except for > [!WARNING] > `[AllowAnonymous]` bypasses all authorization statements. If you combine `[AllowAnonymous]` and any `[Authorize]` attribute, the `[Authorize]` attributes are ignored. For example if you apply `[AllowAnonymous]` at the controller level, any `[Authorize]` attributes on the same controller (or on any action within it) is ignored. +[!INCLUDE[](~/includes/requireAuth.md)] + ## Authorize attribute and Razor Pages