From 8c6bb075e59cb1a41ca6670a7be68954e60b93fb Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Tue, 10 Oct 2017 13:34:19 -0500 Subject: [PATCH 01/34] 2.0 update of Limiting identity by scheme doc --- .../authorization/limitingidentitybyscheme.md | 95 ++++++++++++++----- 1 file changed, 73 insertions(+), 22 deletions(-) diff --git a/aspnetcore/security/authorization/limitingidentitybyscheme.md b/aspnetcore/security/authorization/limitingidentitybyscheme.md index 53d034bcaf..8ffa427e9c 100644 --- a/aspnetcore/security/authorization/limitingidentitybyscheme.md +++ b/aspnetcore/security/authorization/limitingidentitybyscheme.md @@ -2,10 +2,10 @@ title: Limiting identity by scheme author: rick-anderson description: -keywords: ASP.NET Core, +keywords: ASP.NET Core,identity,authentication scheme ms.author: riande manager: wpickett -ms.date: 10/14/2016 +ms.date: 10/10/2017 ms.topic: article ms.assetid: d3d6ca1b-b4b5-4bf7-898e-dcd90ec1bf8c ms.technology: aspnet @@ -16,51 +16,102 @@ uid: security/authorization/limitingidentitybyscheme -In some scenarios, such as Single Page Applications it is possible to end up with multiple authentication methods. For example, your application may use cookie-based authentication to log in and bearer authentication for JavaScript requests. In some cases you may have multiple instances of an authentication middleware. For example, two cookie middlewares where one contains a basic identity and one is created when a multi-factor authentication has triggered because the user requested an operation that requires extra security. +In some scenarios, such as Single Page Applications, it's common to use multiple authentication methods. For example, your application may use cookie-based authentication to log in and JWT bearer authentication for JavaScript requests. In some cases, you may have multiple instances of an authentication middleware. For example, two cookie middlewares where one contains a basic identity and one is created when a multi-factor authentication has triggered (because the user requested an operation that requires extra security). -Authentication schemes are named when authentication middleware is configured during authentication, for example +Authentication schemes are named when authentication middleware is configured during authentication. For example: + +# [ASP.NET Core 2.x](#tab/aspnetcore2x) ```csharp -app.UseCookieAuthentication(new CookieAuthenticationOptions() +public void ConfigureServices(IServiceCollection services) { - AuthenticationScheme = "Cookie", - LoginPath = new PathString("/Account/Unauthorized/"), - AccessDeniedPath = new PathString("/Account/Forbidden/"), - AutomaticAuthenticate = false -}); + // Code omitted for brevity -app.UseBearerAuthentication(options => -{ - options.AuthenticationScheme = "Bearer"; - options.AutomaticAuthenticate = false; -}); + services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) + .AddCookie(options => { + options.LoginPath = "/Account/Unauthorized/"; + options.AccessDeniedPath = "/Account/Forbidden/"; + }); + + services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddJwtBearer(); ``` -In this configuration two authentication middlewares have been added, one for cookies and one for bearer. +In the preceding code, two authentication services have been added: one for cookies and one for bearer. >[!NOTE] ->When adding multiple authentication middleware you should ensure that no middleware is configured to run automatically. You do this by setting the `AutomaticAuthenticate` options property to false. If you fail to do this filtering by scheme will not work. +>When adding multiple authentication middlewares, ensure that no middleware is configured to run automatically. You do this by setting the `AutomaticAuthenticate` options property to false. If you fail to do this, filtering by scheme will not work. + +# [ASP.NET Core 1.x](#tab/aspnetcore1x) + +```csharp +public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) +{ + // Code omitted for brevity + + app.UseCookieAuthentication(new CookieAuthenticationOptions() + { + AuthenticationScheme = "Cookie", + LoginPath = "/Account/Unauthorized/", + AccessDeniedPath = "/Account/Forbidden/", + AutomaticAuthenticate = false + }); + + app.UseJwtBearerAuthentication(new JwtBearerOptions() + { + AuthenticationScheme = "Bearer", + AutomaticAuthenticate = false + }); +``` + +In the preceding code, two authentication middlewares have been added: one for cookies and one for bearer. + +>[!NOTE] +>When adding multiple authentication middlewares, ensure that no middleware is configured to run automatically. You do this by setting the `AutomaticAuthenticate` options property to false. If you fail to do this, filtering by scheme will not work. + +--- ## Selecting the scheme with the Authorize attribute -As no authentication middleware is configured to automatically run and create an identity you must, at the point of authorization choose which middleware will be used. The simplest way to select the middleware you wish to authorize with is to use the `ActiveAuthenticationSchemes` property. This property accepts a comma delimited list of Authentication Schemes to use. For example; +No authentication middleware is configured to automatically run and create an identity. At the point of authorization, you choose which middleware will be used. The simplest way to select the middleware with which you wish to authorize is to use the `ActiveAuthenticationSchemes` property. This property accepts a comma-delimited list of authentication schemes to use. For example: + +# [ASP.NET Core 2.x](#tab/aspnetcore2x) + +```csharp +[Authorize(AuthenticationSchemes = "Cookie,Bearer")] +public class MixedController : Controller +``` + +# [ASP.NET Core 1.x](#tab/aspnetcore1x) ```csharp [Authorize(ActiveAuthenticationSchemes = "Cookie,Bearer")] public class MixedController : Controller ``` -In the example above both the cookie and bearer middlewares will run and have a chance to create and append an identity for the current user. By specifying a single scheme only the specified middleware will run; +--- + +In the example above, both the cookie and bearer middlewares run and have a chance to create and append an identity for the current user. By specifying a single scheme only, the specified middleware runs. + +# [ASP.NET Core 2.x](#tab/aspnetcore2x) + +```csharp +[Authorize(AuthenticationSchemes = "Bearer")] +``` + +# [ASP.NET Core 1.x](#tab/aspnetcore1x) ```csharp [Authorize(ActiveAuthenticationSchemes = "Bearer")] ``` -In this case only the middleware with the Bearer scheme would run, and any cookie based identities would be ignored. +--- + +In this case, only the middleware with the "Bearer" scheme runs. Any cookie-based identities are ignored. ## Selecting the scheme with policies -If you prefer to specify the desired schemes in [policy](policies.md#security-authorization-policies-based) you can set the `AuthenticationSchemes` collection when adding your policy. +If you prefer to specify the desired schemes in [policy](policies.md#security-authorization-policies-based), you can set the `AuthenticationSchemes` collection when adding your policy: ```csharp options.AddPolicy("Over18", policy => @@ -71,4 +122,4 @@ options.AddPolicy("Over18", policy => }); ``` -In this example the Over18 policy will only run against the identity created by the `Bearer` middleware. +In this example, the "Over18" policy only runs against the identity created by the "Bearer" middleware. From 1d087dc6e71e972d75ee46a41a39514104434327 Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Tue, 10 Oct 2017 14:47:05 -0500 Subject: [PATCH 02/34] Update 2.0 code snippet --- .../security/authorization/limitingidentitybyscheme.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/aspnetcore/security/authorization/limitingidentitybyscheme.md b/aspnetcore/security/authorization/limitingidentitybyscheme.md index 8ffa427e9c..cc1c2eb3e9 100644 --- a/aspnetcore/security/authorization/limitingidentitybyscheme.md +++ b/aspnetcore/security/authorization/limitingidentitybyscheme.md @@ -18,7 +18,7 @@ uid: security/authorization/limitingidentitybyscheme In some scenarios, such as Single Page Applications, it's common to use multiple authentication methods. For example, your application may use cookie-based authentication to log in and JWT bearer authentication for JavaScript requests. In some cases, you may have multiple instances of an authentication middleware. For example, two cookie middlewares where one contains a basic identity and one is created when a multi-factor authentication has triggered (because the user requested an operation that requires extra security). -Authentication schemes are named when authentication middleware is configured during authentication. For example: +Authentication schemes are named when authentication middlewares or services are configured during authentication. For example: # [ASP.NET Core 2.x](#tab/aspnetcore2x) @@ -31,16 +31,14 @@ public void ConfigureServices(IServiceCollection services) .AddCookie(options => { options.LoginPath = "/Account/Unauthorized/"; options.AccessDeniedPath = "/Account/Forbidden/"; - }); - - services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + }) .AddJwtBearer(); ``` In the preceding code, two authentication services have been added: one for cookies and one for bearer. >[!NOTE] ->When adding multiple authentication middlewares, ensure that no middleware is configured to run automatically. You do this by setting the `AutomaticAuthenticate` options property to false. If you fail to do this, filtering by scheme will not work. +>When adding multiple authentication middlewares, ensure that no middleware is configured to run automatically. You do this by setting the `AuthenticationOptions.AutomaticAuthenticate` property to false. If you fail to do this, filtering by scheme will not work. # [ASP.NET Core 1.x](#tab/aspnetcore1x) @@ -67,7 +65,7 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerF In the preceding code, two authentication middlewares have been added: one for cookies and one for bearer. >[!NOTE] ->When adding multiple authentication middlewares, ensure that no middleware is configured to run automatically. You do this by setting the `AutomaticAuthenticate` options property to false. If you fail to do this, filtering by scheme will not work. +>When adding multiple authentication middlewares, ensure that no middleware is configured to run automatically. You do this by setting the `AuthenticationOptions.AutomaticAuthenticate` property to false. If you fail to do this, filtering by scheme will not work. --- From 1074ebd07beb5dec0a2111a8f6a5de269e258e44 Mon Sep 17 00:00:00 2001 From: Michael DePouw Date: Wed, 11 Oct 2017 09:29:14 -0400 Subject: [PATCH 03/34] add link to what css auto-sync is --- aspnetcore/client-side/using-browserlink.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/client-side/using-browserlink.md b/aspnetcore/client-side/using-browserlink.md index cb63291678..08a9c0d1fd 100644 --- a/aspnetcore/client-side/using-browserlink.md +++ b/aspnetcore/client-side/using-browserlink.md @@ -76,7 +76,7 @@ From the Browser Link toolbar control, you can: * Refresh the web application in several browsers at once. * Open the **Browser Link Dashboard**. * Enable or disable **Browser Link**. Note: Browser Link is disabled by default in Visual Studio 2017 (15.3). -* Enable or disable CSS Auto-Sync. +* Enable or disable [CSS Auto-Sync](#enable-or-disable-css-auto-sync). > [!NOTE] > Some Visual Studio plug-ins, most notably *Web Extension Pack 2015* and *Web Extension Pack 2017*, offer extended functionality for Browser Link, but some of the additional features don't work with ASP.NET Core projects. From cc85485f9adc5c5e0d792418b97d52f0f3fd50bb Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Wed, 11 Oct 2017 10:44:16 -0500 Subject: [PATCH 04/34] Remove unnecessary anchor --- aspnetcore/security/authentication/cookie.md | 2 +- aspnetcore/security/authorization/limitingidentitybyscheme.md | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/aspnetcore/security/authentication/cookie.md b/aspnetcore/security/authentication/cookie.md index 6175057918..eaa25b6080 100644 --- a/aspnetcore/security/authentication/cookie.md +++ b/aspnetcore/security/authentication/cookie.md @@ -71,7 +71,7 @@ The code snippets above configure some or all of the following options: * `AccessDeniedPath` - This is the relative path to which requests redirect when a user attempts to access a resource but does not pass any [authorization policies](xref:security/authorization/policies#security-authorization-policies-based) for that resource. -* `AuthenticationScheme` - This is a value by which a particular cookie authentication scheme is known. This is useful when there are multiple instances of cookie authentication and you want to [limit authorization to one instance](xref:security/authorization/limitingidentitybyscheme#security-authorization-limiting-by-scheme). +* `AuthenticationScheme` - This is a value by which a particular cookie authentication scheme is known. This is useful when there are multiple instances of cookie authentication and you want to [limit authorization to one instance](xref:security/authorization/limitingidentitybyscheme). * `AutomaticAuthenticate` - This flag is relevant only for ASP.NET Core 1.x. It indicates that the cookie authentication should run on every request and attempt to validate and reconstruct any serialized principal it created. diff --git a/aspnetcore/security/authorization/limitingidentitybyscheme.md b/aspnetcore/security/authorization/limitingidentitybyscheme.md index cc1c2eb3e9..c6b7d96baf 100644 --- a/aspnetcore/security/authorization/limitingidentitybyscheme.md +++ b/aspnetcore/security/authorization/limitingidentitybyscheme.md @@ -14,8 +14,6 @@ uid: security/authorization/limitingidentitybyscheme --- # Limiting identity by scheme - - In some scenarios, such as Single Page Applications, it's common to use multiple authentication methods. For example, your application may use cookie-based authentication to log in and JWT bearer authentication for JavaScript requests. In some cases, you may have multiple instances of an authentication middleware. For example, two cookie middlewares where one contains a basic identity and one is created when a multi-factor authentication has triggered (because the user requested an operation that requires extra security). Authentication schemes are named when authentication middlewares or services are configured during authentication. For example: From 6d03b6651b2356dcdcdf7895070928db162878d0 Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Wed, 11 Oct 2017 11:47:11 -0500 Subject: [PATCH 05/34] Update note for 2.0 --- .../security/authorization/limitingidentitybyscheme.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aspnetcore/security/authorization/limitingidentitybyscheme.md b/aspnetcore/security/authorization/limitingidentitybyscheme.md index c6b7d96baf..646e500beb 100644 --- a/aspnetcore/security/authorization/limitingidentitybyscheme.md +++ b/aspnetcore/security/authorization/limitingidentitybyscheme.md @@ -1,7 +1,7 @@ --- -title: Limiting identity by scheme +title: Limiting identity by scheme - ASP.NET Core author: rick-anderson -description: +description: This article explains how to limit identity to a specific schema when working with multiple authentication methods. keywords: ASP.NET Core,identity,authentication scheme ms.author: riande manager: wpickett @@ -36,7 +36,7 @@ public void ConfigureServices(IServiceCollection services) In the preceding code, two authentication services have been added: one for cookies and one for bearer. >[!NOTE] ->When adding multiple authentication middlewares, ensure that no middleware is configured to run automatically. You do this by setting the `AuthenticationOptions.AutomaticAuthenticate` property to false. If you fail to do this, filtering by scheme will not work. +>When adding multiple authentication middlewares, ensure that no middleware is configured to run automatically. You do this by supplying an argument, such as `CookieAuthenticationDefaults.AuthenticationScheme`, to the `AddAuthentication` method. If you fail to do this, filtering by scheme will not work. # [ASP.NET Core 1.x](#tab/aspnetcore1x) From 9c27fa0f0c57ad611aa43f63afb9b9c9571d4a94 Mon Sep 17 00:00:00 2001 From: Eilon Lipton Date: Wed, 11 Oct 2017 10:24:18 -0700 Subject: [PATCH 06/34] Update doc to state that CookieTempData is the default (#4350) * Update doc to state that CookieTempData is the default In ASP.NET Core 2.0 the Cookie TempData provider is the default, not session state. * Feedback + restructuring the text * Add more explanation of choosing a TempData provider Also fixed formatting and headings * Update app-state.md * Update app-state.md (#4525) * Update app-state.md * Update app-state.md * Update app-state.md * Update app-state.md --- aspnetcore/fundamentals/app-state.md | 63 +++++++++++++++++++--------- 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/aspnetcore/fundamentals/app-state.md b/aspnetcore/fundamentals/app-state.md index 1579407711..3f383ee903 100644 --- a/aspnetcore/fundamentals/app-state.md +++ b/aspnetcore/fundamentals/app-state.md @@ -5,7 +5,7 @@ description: Approaches to preserving application and user (session) state betwe keywords: ASP.NET Core,Application state,session state,querystring,post ms.author: riande manager: wpickett -ms.date: 06/08/2017 +ms.date: 10/08/2017 ms.topic: article ms.assetid: 18cda488-0769-4cb9-82f6-4c6685f2045d ms.technology: aspnet @@ -18,7 +18,7 @@ ms.custom: H1Hack27Feb2017 By [Rick Anderson](https://twitter.com/RickAndMSFT), [Steve Smith](https://ardalis.com/), and [Diana LaRose](https://github.com/DianaLaRose) -HTTP is a stateless protocol. A web server treats each HTTP request as an independent request and does not retain user values from previous requests. This article discusses different ways to preserve application and session state between requests. +HTTP is a stateless protocol. A web server treats each HTTP request as an independent request and does not retain user values from previous requests. This article discusses different ways to preserve application and session state between requests. ## Session state @@ -33,38 +33,60 @@ The server retains a session for a limited time after the last request. You can The in-memory session provider stores session data on the local server. If you plan to run your web app on a server farm, you must use sticky sessions to tie each session to a specific server. The Windows Azure Web Sites platform defaults to sticky sessions (Application Request Routing or ARR). However, sticky sessions can affect scalability and complicate web app updates. A better option is to use the Redis or SQL Server distributed caches, which don't require sticky sessions. For more information, see [Working with a Distributed Cache](xref:performance/caching/distributed). For details on setting up service providers, see [Configuring Session](#configuring-session) later in this article. -The remainder of this section describes the options for storing user data. -### TempData +## TempData -ASP.NET Core MVC exposes the [TempData](https://docs.microsoft.com/aspnet/core/api/microsoft.aspnetcore.mvc.controller#Microsoft_AspNetCore_Mvc_Controller_TempData) property on a [controller](https://docs.microsoft.com/aspnet/core/api/microsoft.aspnetcore.mvc.controller). This property stores data until it is read. The `Keep` and `Peek` methods can be used to examine the data without deletion. `TempData` is particularly useful for redirection, when data is needed for more than a single request. `TempData` is built on top of session state. +ASP.NET Core MVC exposes the [TempData](https://docs.microsoft.com/dotnet/api/microsoft.aspnetcore.mvc.controller.tempdata?view=aspnetcore-2.0#Microsoft_AspNetCore_Mvc_Controller_TempData) property on a [controller](https://docs.microsoft.com/dotnet/api/microsoft.aspnetcore.mvc.controller?view=aspnetcore-2.0). This property stores data until it is read. The `Keep` and `Peek` methods can be used to examine the data without deletion. `TempData` is particularly useful for redirection, when data is needed for more than a single request. `TempData` is implemented by TempData providers, for example, using either cookies or session state. -## Cookie-based TempData provider +### TempData providers -In ASP.NET Core 1.1 and higher, you can use the cookie-based TempData provider to store a user's TempData in a cookie. To enable the cookie-based TempData provider, register the `CookieTempDataProvider` service in `ConfigureServices`: +# [ASP.NET Core 2.x](#tab/aspnetcore2x) + +In ASP.NET Core 2.0 and later, the cookie-based TempData provider is used by default to store TempData in cookies. + +The cookie data is encoded with the [Base64UrlTextEncoder](https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.webutilities.base64urltextencoder?view=aspnetcore-2.0). Because the cookie is encrypted and chunked, the single cookie size limit found in ASP.NET Core 1.x does not apply. The cookie data is not compressed because compressing encryped data can lead to security problems such as the [CRIME](https://wikipedia.org/wiki/CRIME_(security_exploit)) and [BREACH](https://wikipedia.org/wiki/BREACH_(security_exploit)) attacks. For more information on the cookie-based TempData provider, see [CookieTempDataProvider](https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewFeatures/CookieTempDataProvider.cs). + +# [ASP.NET Core 1.x](#tab/aspnetcore1x) + +In ASP.NET Core 1.0 and 1.1, the session state TempData provider is the default. + +-------------- + +### Choosing a TempData provider + +Choosing a TempData provider involves several considerations, such as: + +1. Does the application already use session state for other purposes? If so, using the session state TempData provider has no additional cost to the application (aside from the size of the data). +2. Does the application use TempData only sparingly, for relatively small amounts of data (up to 500 bytes)? If so, the cookie TempData provider will add a small cost to each request that carries TempData. If not, the session state TempData provider can be beneficial to avoid round-tripping a large amount of data in each request until the TempData is consumed. +3. Does the application run in a web farm (multiple servers)? If so, there is no additional configuration needed to use the cookie TempData provider. + +> [!NOTE] +> Most web clients (such as web browsers) enforce limits on the maximum size of each cookie, the total number of cookies, or both. Therefore, when using the cookie TempData provider, verify the app won't exceed these limits. Consider the total size of the data, accounting for the overheads of encryption and chunking. + +To configure the TempData provider for an application, register a TempData provider implementation in `ConfigureServices`: ```csharp public void ConfigureServices(IServiceCollection services) { - services.AddMvc(); - // Add CookieTempDataProvider after AddMvc and include ViewFeatures. - // using Microsoft.AspNetCore.Mvc.ViewFeatures; - services.AddSingleton(); + services + .AddMvc() + .AddSessionStateTempDataProvider(); + + // The Session State TempData Provider requires adding the session state service + services.AddSession(); } ``` -The cookie data is encoded with the [Base64UrlTextEncoder](https://docs.microsoft.com/aspnet/core/api/microsoft.aspnetcore.authentication.base64urltextencoder). Because the cookie is encrypted and chunked, the single cookie size limit does not apply. The cookie data is not compressed, because compressing encryped data can lead to security problems such as the [CRIME](https://wikipedia.org/wiki/CRIME_(security_exploit)) and [BREACH](https://wikipedia.org/wiki/BREACH_(security_exploit)) attacks. For more information on the cookie-based TempData provider, see [CookieTempDataProvider](https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewFeatures/CookieTempDataProvider.cs). - -### Query strings +## Query strings You can pass a limited amount of data from one request to another by adding it to the new request’s query string. This is useful for capturing state in a persistent manner that allows links with embedded state to be shared through email or social networks. However, for this reason, you should never use query strings for sensitive data. In addition to being easily shared, including data in query strings can create opportunities for [Cross-Site Request Forgery (CSRF)](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)) attacks, which can trick users into visiting malicious sites while authenticated. Attackers can then steal user data from your app or take malicious actions on behalf of the user. Any preserved application or session state must protect against CSRF attacks. For more information on CSRF attacks, see [Preventing Cross-Site Request Forgery (XSRF/CSRF) Attacks in ASP.NET Core](../security/anti-request-forgery.md). -### Post data and hidden fields +## Post data and hidden fields Data can be saved in hidden form fields and posted back on the next request. This is common in multipage forms. However, because the client can potentially tamper with the data, the server must always revalidate it. -### Cookies +## Cookies Cookies provide a way to store user-specific data in web applications. Because cookies are sent with every request, their size should be kept to a minimum. Ideally, only an identifier should be stored in a cookie with the actual data stored on the server. Most browsers restrict cookies to 4096 bytes. In addition, only a limited number of cookies are available for each domain. @@ -72,17 +94,18 @@ Because cookies are subject to tampering, they must be validated on the server. Cookies are often used for personalization, where content is customized for a known user. Because the user is only identified and not authenticated in most cases, you can typically secure a cookie by storing the user name, account name, or a unique user ID (such as a GUID) in the cookie. You can then use the cookie to access the user personalization infrastructure of a site. -### HttpContext.Items +## HttpContext.Items The `Items` collection is a good location to store data that is needed only while processing one particular request. The collection's contents are discarded after each request. The `Items` collection is best used as a way for components or middleware to communicate when they operate at different points in time during a request and have no direct way to pass parameters. For more information, see [Working with HttpContext.Items](#working-with-httpcontextitems), later in this article. -### Cache +## Cache Caching is an efficient way to store and retrieve data. You can control the lifetime of cached items based on time and other considerations. Learn more about [Caching](../performance/caching/index.md). +## Working with Session State -## Configuring Session +### Configuring Session The `Microsoft.AspNetCore.Session` package provides middleware for managing session state. To enable the session middleware, `Startup`must contain: @@ -134,7 +157,7 @@ The server uses the `IdleTimeout` property to determine how long a session can b Because `Session` is *non-locking*, if two requests both attempt to modify the contents of session, the last one overrides the first. `Session` is implemented as a *coherent session*, which means that all the contents are stored together. Two requests that are modifying different parts of the session (different keys) might still impact each other. -## Setting and getting Session values +### Setting and getting Session values Session is accessed through the `Session` property on `HttpContext`. This property is an [ISession](https://docs.microsoft.com/aspnet/core/api/microsoft.aspnetcore.http.isession) implementation. From 304a6352fe6dd4d2e048dbde0ea37343794b6e75 Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Wed, 11 Oct 2017 13:37:31 -0500 Subject: [PATCH 07/34] Minor edits --- .../authorization/limitingidentitybyscheme.md | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/aspnetcore/security/authorization/limitingidentitybyscheme.md b/aspnetcore/security/authorization/limitingidentitybyscheme.md index 646e500beb..ccb53a2647 100644 --- a/aspnetcore/security/authorization/limitingidentitybyscheme.md +++ b/aspnetcore/security/authorization/limitingidentitybyscheme.md @@ -16,10 +16,10 @@ uid: security/authorization/limitingidentitybyscheme In some scenarios, such as Single Page Applications, it's common to use multiple authentication methods. For example, your application may use cookie-based authentication to log in and JWT bearer authentication for JavaScript requests. In some cases, you may have multiple instances of an authentication middleware. For example, two cookie middlewares where one contains a basic identity and one is created when a multi-factor authentication has triggered (because the user requested an operation that requires extra security). -Authentication schemes are named when authentication middlewares or services are configured during authentication. For example: - # [ASP.NET Core 2.x](#tab/aspnetcore2x) +An authentication scheme is named when the authentication service is configured during authentication. For example: + ```csharp public void ConfigureServices(IServiceCollection services) { @@ -40,25 +40,27 @@ In the preceding code, two authentication services have been added: one for cook # [ASP.NET Core 1.x](#tab/aspnetcore1x) -```csharp -public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) -{ - // Code omitted for brevity +Authentication schemes are named when authentication middlewares are configured during authentication. For example: - app.UseCookieAuthentication(new CookieAuthenticationOptions() + ```csharp + public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { - AuthenticationScheme = "Cookie", - LoginPath = "/Account/Unauthorized/", - AccessDeniedPath = "/Account/Forbidden/", - AutomaticAuthenticate = false - }); + // Code omitted for brevity - app.UseJwtBearerAuthentication(new JwtBearerOptions() - { - AuthenticationScheme = "Bearer", - AutomaticAuthenticate = false - }); -``` + app.UseCookieAuthentication(new CookieAuthenticationOptions() + { + AuthenticationScheme = "Cookie", + LoginPath = "/Account/Unauthorized/", + AccessDeniedPath = "/Account/Forbidden/", + AutomaticAuthenticate = false + }); + + app.UseJwtBearerAuthentication(new JwtBearerOptions() + { + AuthenticationScheme = "Bearer", + AutomaticAuthenticate = false + }); + ``` In the preceding code, two authentication middlewares have been added: one for cookies and one for bearer. @@ -93,12 +95,14 @@ In the example above, both the cookie and bearer middlewares run and have a chan ```csharp [Authorize(AuthenticationSchemes = "Bearer")] +public class MixedController : Controller ``` # [ASP.NET Core 1.x](#tab/aspnetcore1x) ```csharp [Authorize(ActiveAuthenticationSchemes = "Bearer")] +public class MixedController : Controller ``` --- From 87c6f7ecce35944813de14d71a4bc005d77c1dfa Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Wed, 11 Oct 2017 13:41:28 -0500 Subject: [PATCH 08/34] Provide more context in last code snippet --- .../authorization/limitingidentitybyscheme.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/aspnetcore/security/authorization/limitingidentitybyscheme.md b/aspnetcore/security/authorization/limitingidentitybyscheme.md index ccb53a2647..10f7574582 100644 --- a/aspnetcore/security/authorization/limitingidentitybyscheme.md +++ b/aspnetcore/security/authorization/limitingidentitybyscheme.md @@ -114,11 +114,14 @@ In this case, only the middleware with the "Bearer" scheme runs. Any cookie-base If you prefer to specify the desired schemes in [policy](policies.md#security-authorization-policies-based), you can set the `AuthenticationSchemes` collection when adding your policy: ```csharp -options.AddPolicy("Over18", policy => +services.AddAuthorization(options => { - policy.AuthenticationSchemes.Add("Bearer"); - policy.RequireAuthenticatedUser(); - policy.Requirements.Add(new Over18Requirement()); + options.AddPolicy("Over18", policy => + { + policy.AuthenticationSchemes.Add("Bearer"); + policy.RequireAuthenticatedUser(); + policy.Requirements.Add(new Over18Requirement()); + }); }); ``` From e0bf5eb48befdb490c5c623a683bf922a5b0bbd2 Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Wed, 11 Oct 2017 13:48:28 -0500 Subject: [PATCH 09/34] Dedent code snippet --- .../authorization/limitingidentitybyscheme.md | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/aspnetcore/security/authorization/limitingidentitybyscheme.md b/aspnetcore/security/authorization/limitingidentitybyscheme.md index 10f7574582..96459091d2 100644 --- a/aspnetcore/security/authorization/limitingidentitybyscheme.md +++ b/aspnetcore/security/authorization/limitingidentitybyscheme.md @@ -42,25 +42,25 @@ In the preceding code, two authentication services have been added: one for cook Authentication schemes are named when authentication middlewares are configured during authentication. For example: - ```csharp - public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) +```csharp +public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) +{ + // Code omitted for brevity + + app.UseCookieAuthentication(new CookieAuthenticationOptions() { - // Code omitted for brevity + AuthenticationScheme = "Cookie", + LoginPath = "/Account/Unauthorized/", + AccessDeniedPath = "/Account/Forbidden/", + AutomaticAuthenticate = false + }); - app.UseCookieAuthentication(new CookieAuthenticationOptions() - { - AuthenticationScheme = "Cookie", - LoginPath = "/Account/Unauthorized/", - AccessDeniedPath = "/Account/Forbidden/", - AutomaticAuthenticate = false - }); - - app.UseJwtBearerAuthentication(new JwtBearerOptions() - { - AuthenticationScheme = "Bearer", - AutomaticAuthenticate = false - }); - ``` + app.UseJwtBearerAuthentication(new JwtBearerOptions() + { + AuthenticationScheme = "Bearer", + AutomaticAuthenticate = false + }); +``` In the preceding code, two authentication middlewares have been added: one for cookies and one for bearer. From 6625b36affc0615d3ad47ea2417595d71ba2fed6 Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Wed, 11 Oct 2017 14:04:07 -0500 Subject: [PATCH 10/34] Convert link to xref style --- aspnetcore/security/authorization/limitingidentitybyscheme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/security/authorization/limitingidentitybyscheme.md b/aspnetcore/security/authorization/limitingidentitybyscheme.md index 96459091d2..d920721153 100644 --- a/aspnetcore/security/authorization/limitingidentitybyscheme.md +++ b/aspnetcore/security/authorization/limitingidentitybyscheme.md @@ -111,7 +111,7 @@ In this case, only the middleware with the "Bearer" scheme runs. Any cookie-base ## Selecting the scheme with policies -If you prefer to specify the desired schemes in [policy](policies.md#security-authorization-policies-based), you can set the `AuthenticationSchemes` collection when adding your policy: +If you prefer to specify the desired schemes in [policy](xref:security/authorization/policies#security-authorization-policies-based), you can set the `AuthenticationSchemes` collection when adding your policy: ```csharp services.AddAuthorization(options => From 134813bf5968589a0199614d084e64b76f2d8eca Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Wed, 11 Oct 2017 15:13:20 -0500 Subject: [PATCH 11/34] React to feedback --- .../authorization/limitingidentitybyscheme.md | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/aspnetcore/security/authorization/limitingidentitybyscheme.md b/aspnetcore/security/authorization/limitingidentitybyscheme.md index d920721153..46fd0a0c85 100644 --- a/aspnetcore/security/authorization/limitingidentitybyscheme.md +++ b/aspnetcore/security/authorization/limitingidentitybyscheme.md @@ -25,18 +25,21 @@ public void ConfigureServices(IServiceCollection services) { // Code omitted for brevity - services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) + services.AddAuthentication() .AddCookie(options => { options.LoginPath = "/Account/Unauthorized/"; options.AccessDeniedPath = "/Account/Forbidden/"; }) - .AddJwtBearer(); + .AddJwtBearer(options => { + options.Audience = "http://localhost:5001/"; + options.Authority = "http://localhost:5000/"; + }); ``` In the preceding code, two authentication services have been added: one for cookies and one for bearer. >[!NOTE] ->When adding multiple authentication middlewares, ensure that no middleware is configured to run automatically. You do this by supplying an argument, such as `CookieAuthenticationDefaults.AuthenticationScheme`, to the `AddAuthentication` method. If you fail to do this, filtering by scheme will not work. +>When adding multiple authentication middlewares, ensure that no middleware is configured to run automatically. You do this by invoking `AddAuthentication` with no arguments. If you fail to do this, filtering by scheme doesn't work. For example, `AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)` makes cookies run automatically. # [ASP.NET Core 1.x](#tab/aspnetcore1x) @@ -58,20 +61,22 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerF app.UseJwtBearerAuthentication(new JwtBearerOptions() { AuthenticationScheme = "Bearer", - AutomaticAuthenticate = false + AutomaticAuthenticate = false, + Audience = "http://localhost:5001/", + Authority = "http://localhost:5000/" }); ``` In the preceding code, two authentication middlewares have been added: one for cookies and one for bearer. >[!NOTE] ->When adding multiple authentication middlewares, ensure that no middleware is configured to run automatically. You do this by setting the `AuthenticationOptions.AutomaticAuthenticate` property to false. If you fail to do this, filtering by scheme will not work. +>When adding multiple authentication middlewares, ensure that no middleware is configured to run automatically. You do this by setting the `AuthenticationOptions.AutomaticAuthenticate` property to false. If you fail to do this, filtering by scheme doesn't work. --- ## Selecting the scheme with the Authorize attribute -No authentication middleware is configured to automatically run and create an identity. At the point of authorization, you choose which middleware will be used. The simplest way to select the middleware with which you wish to authorize is to use the `ActiveAuthenticationSchemes` property. This property accepts a comma-delimited list of authentication schemes to use. For example: +At the point of authorization, you indicate the middleware to be used. The simplest way to select the middleware with which you wish to authorize is to pass a comma-delimited list of authentication schemes to the `[Authorize]` attribute. The `[Authorize]` attribute specifies the authentication scheme or schemes to use regardless of whether a default is configured. For example: # [ASP.NET Core 2.x](#tab/aspnetcore2x) From 5dda7cb14f23969815fa5d949ef5a02804273ef0 Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Wed, 11 Oct 2017 15:56:08 -0500 Subject: [PATCH 12/34] Remove unnecessary anchors from social auth docs --- aspnetcore/security/authentication/social/facebook-logins.md | 2 -- aspnetcore/security/authentication/social/google-logins.md | 2 -- aspnetcore/security/authentication/social/microsoft-logins.md | 2 -- aspnetcore/security/authentication/social/twitter-logins.md | 2 -- 4 files changed, 8 deletions(-) diff --git a/aspnetcore/security/authentication/social/facebook-logins.md b/aspnetcore/security/authentication/social/facebook-logins.md index 779b6628e0..14c916945f 100644 --- a/aspnetcore/security/authentication/social/facebook-logins.md +++ b/aspnetcore/security/authentication/social/facebook-logins.md @@ -14,8 +14,6 @@ uid: security/authentication/facebook-logins --- # Configuring Facebook authentication - - By [Valeriy Novytskyy](https://github.com/01binary) and [Rick Anderson](https://twitter.com/RickAndMSFT) This tutorial shows you how to enable your users to sign in with their Facebook account using a sample ASP.NET Core 2.0 project created on the [previous page](index.md). We start by creating a Facebook App ID by following the [official steps](https://www.facebook.com/unsupportedbrowser). diff --git a/aspnetcore/security/authentication/social/google-logins.md b/aspnetcore/security/authentication/social/google-logins.md index 1de874e793..d43cc439aa 100644 --- a/aspnetcore/security/authentication/social/google-logins.md +++ b/aspnetcore/security/authentication/social/google-logins.md @@ -13,8 +13,6 @@ uid: security/authentication/google-logins --- # Configuring Google authentication in ASP.NET Core - - By [Valeriy Novytskyy](https://github.com/01binary) and [Rick Anderson](https://twitter.com/RickAndMSFT) This tutorial shows you how to enable your users to sign in with their Google+ account using a sample ASP.NET Core 2.0 project created on the [previous page](index.md). We start by following the [official steps](https://developers.google.com/identity/sign-in/web/devconsole-project) to create a new app in Google API Console. diff --git a/aspnetcore/security/authentication/social/microsoft-logins.md b/aspnetcore/security/authentication/social/microsoft-logins.md index 411564a82d..e6bcf9a99a 100644 --- a/aspnetcore/security/authentication/social/microsoft-logins.md +++ b/aspnetcore/security/authentication/social/microsoft-logins.md @@ -14,8 +14,6 @@ uid: security/authentication/microsoft-logins --- # Configuring Microsoft Account authentication - - By [Valeriy Novytskyy](https://github.com/01binary) and [Rick Anderson](https://twitter.com/RickAndMSFT) This tutorial shows you how to enable your users to sign in with their Microsoft account using a sample ASP.NET Core 2.0 project created on the [previous page](index.md). diff --git a/aspnetcore/security/authentication/social/twitter-logins.md b/aspnetcore/security/authentication/social/twitter-logins.md index c070beb0ab..ffc7dc918a 100644 --- a/aspnetcore/security/authentication/social/twitter-logins.md +++ b/aspnetcore/security/authentication/social/twitter-logins.md @@ -14,8 +14,6 @@ uid: security/authentication/twitter-logins --- # Configuring Twitter authentication - - By [Valeriy Novytskyy](https://github.com/01binary) and [Rick Anderson](https://twitter.com/RickAndMSFT) This tutorial shows you how to enable your users to [sign in with their Twitter account](https://dev.twitter.com/web/sign-in/desktop-browser) using a sample ASP.NET Core 2.0 project created on the [previous page](index.md). From e452a5516bf449c137b8261bc20b6c270b753f57 Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Wed, 11 Oct 2017 21:15:41 -0500 Subject: [PATCH 13/34] MVC Core --> Core MVC --- aspnetcore/includes/mvc-intro/controller-methods-views.md | 2 +- aspnetcore/tutorials/first-mvc-app-mac/adding-model.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aspnetcore/includes/mvc-intro/controller-methods-views.md b/aspnetcore/includes/mvc-intro/controller-methods-views.md index fc3509fb97..b872e8a931 100644 --- a/aspnetcore/includes/mvc-intro/controller-methods-views.md +++ b/aspnetcore/includes/mvc-intro/controller-methods-views.md @@ -5,7 +5,7 @@ Browse to the `Movies` controller and hold the mouse pointer over an **Edit** li ![Browser window with mouse over the Edit link and a link Url of http://localhost:1234/Movies/Edit/5 is shown](../../tutorials/first-mvc-app/controller-methods-views/_static/edit7.png) -The **Edit**, **Details**, and **Delete** links are generated by the MVC Core Anchor Tag Helper in the *Views/Movies/Index.cshtml* file. +The **Edit**, **Details**, and **Delete** links are generated by the Core MVC Anchor Tag Helper in the *Views/Movies/Index.cshtml* file. [!code-HTML[Main](../../tutorials/first-mvc-app/start-mvc/sample/MvcMovie/Views/Movies/IndexOriginal.cshtml?highlight=1-3&range=46-50)] diff --git a/aspnetcore/tutorials/first-mvc-app-mac/adding-model.md b/aspnetcore/tutorials/first-mvc-app-mac/adding-model.md index fd9bfb4e75..945e8ca623 100644 --- a/aspnetcore/tutorials/first-mvc-app-mac/adding-model.md +++ b/aspnetcore/tutorials/first-mvc-app-mac/adding-model.md @@ -1,5 +1,5 @@ --- -title: Add a model to an ASP.NET MVC Core app +title: Add a model to an ASP.NET Core MVC app author: rick-anderson description: Add a model to a simple ASP.NET Core app. keywords: ASP.NET Core,MVC,scaffold,scaffolding From a06e47425ea19a2e1d1d977ca7fda9aedfb9e7de Mon Sep 17 00:00:00 2001 From: Rick Anderson Date: Wed, 11 Oct 2017 16:32:14 -1000 Subject: [PATCH 14/34] Update limitingidentitybyscheme.md --- .../authorization/limitingidentitybyscheme.md | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/aspnetcore/security/authorization/limitingidentitybyscheme.md b/aspnetcore/security/authorization/limitingidentitybyscheme.md index 46fd0a0c85..a76e30712b 100644 --- a/aspnetcore/security/authorization/limitingidentitybyscheme.md +++ b/aspnetcore/security/authorization/limitingidentitybyscheme.md @@ -14,7 +14,7 @@ uid: security/authorization/limitingidentitybyscheme --- # Limiting identity by scheme -In some scenarios, such as Single Page Applications, it's common to use multiple authentication methods. For example, your application may use cookie-based authentication to log in and JWT bearer authentication for JavaScript requests. In some cases, you may have multiple instances of an authentication middleware. For example, two cookie middlewares where one contains a basic identity and one is created when a multi-factor authentication has triggered (because the user requested an operation that requires extra security). +In some scenarios, such as Single Page Applications (SPAs), it's common to use multiple authentication methods. For example, the application may use cookie-based authentication to log in and JWT bearer authentication for JavaScript requests. In some cases, the app may have multiple instances of an authentication middleware. For example, two cookie middlewares where one contains a basic identity and one is created when a multi-factor authentication (MFA) has been triggered. MFA may be triggered because the user requested an operation that requires extra security. # [ASP.NET Core 2.x](#tab/aspnetcore2x) @@ -39,7 +39,9 @@ public void ConfigureServices(IServiceCollection services) In the preceding code, two authentication services have been added: one for cookies and one for bearer. >[!NOTE] ->When adding multiple authentication middlewares, ensure that no middleware is configured to run automatically. You do this by invoking `AddAuthentication` with no arguments. If you fail to do this, filtering by scheme doesn't work. For example, `AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)` makes cookies run automatically. +>When adding multiple authentication middlewares, ensure that no middleware is configured to run automatically. Invoking `AddAuthentication` with no arguments ensures that no middleware is configured to run automatically. If the app does **not** + invoke `AddAuthentication` with no arguments, filtering by scheme doesn't work. For example, calling + `AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)` makes cookies run automatically. # [ASP.NET Core 1.x](#tab/aspnetcore1x) @@ -70,13 +72,17 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerF In the preceding code, two authentication middlewares have been added: one for cookies and one for bearer. >[!NOTE] ->When adding multiple authentication middlewares, ensure that no middleware is configured to run automatically. You do this by setting the `AuthenticationOptions.AutomaticAuthenticate` property to false. If you fail to do this, filtering by scheme doesn't work. +>When adding multiple authentication middlewares, ensure that no middleware is configured to run automatically. An app ensures that no middleware is configured to run automatically by setting the `AuthenticationOptions.AutomaticAuthenticate` property to false. If the app fails to set`AuthenticationOptions.AutomaticAuthenticate` to false, filtering by scheme doesn't work. --- ## Selecting the scheme with the Authorize attribute -At the point of authorization, you indicate the middleware to be used. The simplest way to select the middleware with which you wish to authorize is to pass a comma-delimited list of authentication schemes to the `[Authorize]` attribute. The `[Authorize]` attribute specifies the authentication scheme or schemes to use regardless of whether a default is configured. For example: +At the point of authorization, the app indicates the middleware to be used. The simplest way to select the middleware with which the app will authorize: + +* Pass a comma-delimited list of authentication schemes to the `[Authorize]` attribute. + +The `[Authorize]` attribute specifies the authentication scheme or schemes to use regardless of whether a default is configured. For example: # [ASP.NET Core 2.x](#tab/aspnetcore2x) @@ -94,7 +100,7 @@ public class MixedController : Controller --- -In the example above, both the cookie and bearer middlewares run and have a chance to create and append an identity for the current user. By specifying a single scheme only, the specified middleware runs. +In the preceding example, both the cookie and bearer middlewares run and have a chance to create and append an identity for the current user. By specifying a single scheme only, the specified middleware runs. # [ASP.NET Core 2.x](#tab/aspnetcore2x) @@ -112,7 +118,8 @@ public class MixedController : Controller --- -In this case, only the middleware with the "Bearer" scheme runs. Any cookie-based identities are ignored. + +In the preceding code , only the middleware with the "Bearer" scheme runs. Any cookie-based identities are ignored. ## Selecting the scheme with policies @@ -130,4 +137,4 @@ services.AddAuthorization(options => }); ``` -In this example, the "Over18" policy only runs against the identity created by the "Bearer" middleware. +In the preceding example, the "Over18" policy only runs against the identity created by the "Bearer" middleware. From a73fb5161fbdbee1d2e8474205e9840a134ee2ad Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Wed, 11 Oct 2017 21:33:55 -0500 Subject: [PATCH 15/34] Fix incorrect file name in QR Code doc --- aspnetcore/security/authentication/identity-enable-qrcodes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/security/authentication/identity-enable-qrcodes.md b/aspnetcore/security/authentication/identity-enable-qrcodes.md index ebaeb02d5a..60378798cc 100644 --- a/aspnetcore/security/authentication/identity-enable-qrcodes.md +++ b/aspnetcore/security/authentication/identity-enable-qrcodes.md @@ -58,7 +58,7 @@ Run your app and ensure that you can scan the QR code and validate the code the ## Change the site name in the QR Code -The site name in the QR Code is taken from the project name you choose when initially creating your project. You can change it by looking for the `GenerateQrCodeUri(string email, string unformattedKey)` method in the *Pages\Account\Manage\EnableAuthenticator.cshtml.cs* (Razor Pages) file or the *Controllers\AccountController.cs* (MVC) file. +The site name in the QR Code is taken from the project name you choose when initially creating your project. You can change it by looking for the `GenerateQrCodeUri(string email, string unformattedKey)` method in the *Pages\Account\Manage\EnableAuthenticator.cshtml.cs* (Razor Pages) file or the *Controllers\ManageController.cs* (MVC) file. The default code from the template looks as follows: From 9d6cafcdc85644bbcc3a217a8f7bfcdddcc5bad6 Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Thu, 12 Oct 2017 09:27:46 -0500 Subject: [PATCH 16/34] Minor tweaks --- .../authorization/limitingidentitybyscheme.md | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/aspnetcore/security/authorization/limitingidentitybyscheme.md b/aspnetcore/security/authorization/limitingidentitybyscheme.md index a76e30712b..6271855789 100644 --- a/aspnetcore/security/authorization/limitingidentitybyscheme.md +++ b/aspnetcore/security/authorization/limitingidentitybyscheme.md @@ -39,9 +39,7 @@ public void ConfigureServices(IServiceCollection services) In the preceding code, two authentication services have been added: one for cookies and one for bearer. >[!NOTE] ->When adding multiple authentication middlewares, ensure that no middleware is configured to run automatically. Invoking `AddAuthentication` with no arguments ensures that no middleware is configured to run automatically. If the app does **not** - invoke `AddAuthentication` with no arguments, filtering by scheme doesn't work. For example, calling - `AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)` makes cookies run automatically. +>When adding multiple authentication middlewares, ensure that no middleware is configured to run automatically. Invoking `AddAuthentication` with no arguments ensures that no middleware is configured to run automatically. If the app invokes `AddAuthentication` with arguments, filtering by scheme doesn't work. For example, calling `AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)` makes cookies run automatically. # [ASP.NET Core 1.x](#tab/aspnetcore1x) @@ -72,17 +70,13 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerF In the preceding code, two authentication middlewares have been added: one for cookies and one for bearer. >[!NOTE] ->When adding multiple authentication middlewares, ensure that no middleware is configured to run automatically. An app ensures that no middleware is configured to run automatically by setting the `AuthenticationOptions.AutomaticAuthenticate` property to false. If the app fails to set`AuthenticationOptions.AutomaticAuthenticate` to false, filtering by scheme doesn't work. +>When adding multiple authentication middlewares, ensure that no middleware is configured to run automatically. An app ensures that no middleware is configured to run automatically by setting the `AuthenticationOptions.AutomaticAuthenticate` property to false. If the app fails to set `AuthenticationOptions.AutomaticAuthenticate` to false, filtering by scheme doesn't work. --- ## Selecting the scheme with the Authorize attribute -At the point of authorization, the app indicates the middleware to be used. The simplest way to select the middleware with which the app will authorize: - -* Pass a comma-delimited list of authentication schemes to the `[Authorize]` attribute. - -The `[Authorize]` attribute specifies the authentication scheme or schemes to use regardless of whether a default is configured. For example: +At the point of authorization, the app indicates the middleware to be used. Select the middleware with which the app will authorize by passing a comma-delimited list of authentication schemes to `[Authorize]`. The `[Authorize]` attribute specifies the authentication scheme or schemes to use regardless of whether a default is configured. For example: # [ASP.NET Core 2.x](#tab/aspnetcore2x) @@ -118,8 +112,7 @@ public class MixedController : Controller --- - -In the preceding code , only the middleware with the "Bearer" scheme runs. Any cookie-based identities are ignored. +In the preceding code, only the middleware with the "Bearer" scheme runs. Any cookie-based identities are ignored. ## Selecting the scheme with policies @@ -137,4 +130,4 @@ services.AddAuthorization(options => }); ``` -In the preceding example, the "Over18" policy only runs against the identity created by the "Bearer" middleware. +In the preceding example, the "Over18" policy only runs against the identity created by the "Bearer" middleware. From c857c8f187187dcf2abfe88dfd67859bd92a5f8f Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Thu, 12 Oct 2017 09:35:20 -0500 Subject: [PATCH 17/34] application --> app --- aspnetcore/security/authorization/limitingidentitybyscheme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/security/authorization/limitingidentitybyscheme.md b/aspnetcore/security/authorization/limitingidentitybyscheme.md index 6271855789..087fe51c68 100644 --- a/aspnetcore/security/authorization/limitingidentitybyscheme.md +++ b/aspnetcore/security/authorization/limitingidentitybyscheme.md @@ -14,7 +14,7 @@ uid: security/authorization/limitingidentitybyscheme --- # Limiting identity by scheme -In some scenarios, such as Single Page Applications (SPAs), it's common to use multiple authentication methods. For example, the application may use cookie-based authentication to log in and JWT bearer authentication for JavaScript requests. In some cases, the app may have multiple instances of an authentication middleware. For example, two cookie middlewares where one contains a basic identity and one is created when a multi-factor authentication (MFA) has been triggered. MFA may be triggered because the user requested an operation that requires extra security. +In some scenarios, such as Single Page Applications (SPAs), it's common to use multiple authentication methods. For example, the app may use cookie-based authentication to log in and JWT bearer authentication for JavaScript requests. In some cases, the app may have multiple instances of an authentication middleware. For example, two cookie middlewares where one contains a basic identity and one is created when a multi-factor authentication (MFA) has been triggered. MFA may be triggered because the user requested an operation that requires extra security. # [ASP.NET Core 2.x](#tab/aspnetcore2x) From fb8d79c28ef6529999f404e7d867fa31372391e6 Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Thu, 12 Oct 2017 12:20:58 -0500 Subject: [PATCH 18/34] Implement Rick's suggestion in cookie doc --- aspnetcore/security/authentication/cookie.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/security/authentication/cookie.md b/aspnetcore/security/authentication/cookie.md index eaa25b6080..4c0ff2e2a6 100644 --- a/aspnetcore/security/authentication/cookie.md +++ b/aspnetcore/security/authentication/cookie.md @@ -71,7 +71,7 @@ The code snippets above configure some or all of the following options: * `AccessDeniedPath` - This is the relative path to which requests redirect when a user attempts to access a resource but does not pass any [authorization policies](xref:security/authorization/policies#security-authorization-policies-based) for that resource. -* `AuthenticationScheme` - This is a value by which a particular cookie authentication scheme is known. This is useful when there are multiple instances of cookie authentication and you want to [limit authorization to one instance](xref:security/authorization/limitingidentitybyscheme). +* `AuthenticationScheme` - This is a value by which a particular cookie authentication scheme is known. This is useful when there are multiple instances of cookie authentication and the app needs to [limit authorization to one instance](xref:security/authorization/limitingidentitybyscheme). * `AutomaticAuthenticate` - This flag is relevant only for ASP.NET Core 1.x. It indicates that the cookie authentication should run on every request and attempt to validate and reconstruct any serialized principal it created. From 9acd1a1db1c48765ef1d34ea3b85270a6488f4bc Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Thu, 12 Oct 2017 12:22:13 -0500 Subject: [PATCH 19/34] Implement Rick's suggestion in cookie doc --- aspnetcore/security/authentication/cookie.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/security/authentication/cookie.md b/aspnetcore/security/authentication/cookie.md index eaa25b6080..4c0ff2e2a6 100644 --- a/aspnetcore/security/authentication/cookie.md +++ b/aspnetcore/security/authentication/cookie.md @@ -71,7 +71,7 @@ The code snippets above configure some or all of the following options: * `AccessDeniedPath` - This is the relative path to which requests redirect when a user attempts to access a resource but does not pass any [authorization policies](xref:security/authorization/policies#security-authorization-policies-based) for that resource. -* `AuthenticationScheme` - This is a value by which a particular cookie authentication scheme is known. This is useful when there are multiple instances of cookie authentication and you want to [limit authorization to one instance](xref:security/authorization/limitingidentitybyscheme). +* `AuthenticationScheme` - This is a value by which a particular cookie authentication scheme is known. This is useful when there are multiple instances of cookie authentication and the app needs to [limit authorization to one instance](xref:security/authorization/limitingidentitybyscheme). * `AutomaticAuthenticate` - This flag is relevant only for ASP.NET Core 1.x. It indicates that the cookie authentication should run on every request and attempt to validate and reconstruct any serialized principal it created. From 8f820a653f5586dd610e364dde78ed3fc286dd3d Mon Sep 17 00:00:00 2001 From: Luke Latham <1622880+guardrex@users.noreply.github.com> Date: Thu, 12 Oct 2017 12:35:34 -0500 Subject: [PATCH 20/34] Remove link to "Quick Guide" --- .../overview/getting-started/recommended-resources-for-mvc.md | 1 - 1 file changed, 1 deletion(-) diff --git a/aspnet/mvc/overview/getting-started/recommended-resources-for-mvc.md b/aspnet/mvc/overview/getting-started/recommended-resources-for-mvc.md index eb88599d9e..a572d44a3a 100644 --- a/aspnet/mvc/overview/getting-started/recommended-resources-for-mvc.md +++ b/aspnet/mvc/overview/getting-started/recommended-resources-for-mvc.md @@ -27,7 +27,6 @@ by [Rick Anderson](https://github.com/Rick-Anderson) - [Intro to ASP.NET MVC 5](introduction/getting-started.md) - [Introduction to ASP.NET MVC](https://pluralsight.com/training/Player?author=scott-allen&name=mvc4-building-m1-intro&mode=live&clip=0&course=mvc4-building) (video by Pluralsight) - [Understanding Model View Controller in Asp.Net MVC](http://www.dotnet-tricks.com/Tutorial/mvc/DIYG060113-Understanding-Model-View-Controller-in-Asp.Net-MVC.html) (short blog intro). -- [ASP.NET MVC Quick Guide](http://qkview.com/techbrij/aspnet-mvc-4) - [ASP.NET MVC Overview](../older-versions-1/overview/asp-net-mvc-overview.md) - [Free 6 hour online course - Developing ASP.NET MVC 4 Web Applications Jump Start](https://weblogs.asp.net/jgalloway/archive/2013/10/09/free-6-hour-online-course-developing-asp-net-mvc-4-web-applications-jump-start.aspx) - [Learning MVC - Part 1: Introduction to MVC Architecture and Separation of Concerns](http://www.codeproject.com/Articles/620195/Learning-MVC-Part-1-Introduction-to-MVC-Architectu) From 1570038c174a56509d425a1a5bbf55125de2716b Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Thu, 12 Oct 2017 13:03:03 -0500 Subject: [PATCH 21/34] Change html code snippet types to cshtml --- aspnetcore/data/ef-mvc/intro.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aspnetcore/data/ef-mvc/intro.md b/aspnetcore/data/ef-mvc/intro.md index 9bb77461e5..9782b46dfb 100644 --- a/aspnetcore/data/ef-mvc/intro.md +++ b/aspnetcore/data/ef-mvc/intro.md @@ -89,11 +89,11 @@ Open *Views/Shared/_Layout.cshtml* and make the following changes: The changes are highlighted. -[!code-html[](intro/samples/cu/Views/Shared/_Layout.cshtml?highlight=6,30,36-39,48)] +[!code-cshtml[](intro/samples/cu/Views/Shared/_Layout.cshtml?highlight=6,30,36-39,48)] In *Views/Home/Index.cshtml*, replace the contents of the file with the following code to replace the text about ASP.NET and MVC with text about this application: -[!code-html[](intro/samples/cu/Views/Home/Index.cshtml)] +[!code-cshtml[](intro/samples/cu/Views/Home/Index.cshtml)] Press CTRL+F5 to run the project or choose **Debug > Start Without Debugging** from the menu. You see the home page with tabs for the pages you'll create in these tutorials. @@ -283,7 +283,7 @@ You'll learn about the asynchronous programming elements in this code later in t The *Views/Students/Index.cshtml* view displays this list in a table: -[!code-html[](intro/samples/cu/Views/Students/Index1.cshtml)] +[!code-cshtml[](intro/samples/cu/Views/Students/Index1.cshtml)] Press CTRL+F5 to run the project or choose **Debug > Start Without Debugging** from the menu. From 4a4a2306217584a4d71a02f9b5f8726fb8412f15 Mon Sep 17 00:00:00 2001 From: Rick Anderson Date: Thu, 12 Oct 2017 08:26:32 -1000 Subject: [PATCH 22/34] Update sql.md --- aspnetcore/tutorials/razor-pages/sql.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/tutorials/razor-pages/sql.md b/aspnetcore/tutorials/razor-pages/sql.md index 7f29a5b4e9..12bc665f4b 100644 --- a/aspnetcore/tutorials/razor-pages/sql.md +++ b/aspnetcore/tutorials/razor-pages/sql.md @@ -65,7 +65,7 @@ if (context.Movie.Any()) Add the seed initializer to the end of the `Main` method in the *Program.cs* file: -[!code-csharp[Main](razor-pages-start/sample/RazorPagesMovie/Program.cs?highlight=6,17-32)] +[!code-csharp[Main](razor-pages-start/sample/RazorPagesMovie/Program.cs)] Test the app From cb9fa97a7b8aec218fcf9a69cd38a6855f5ebe97 Mon Sep 17 00:00:00 2001 From: Marek Karbarz Date: Thu, 12 Oct 2017 12:12:24 -0700 Subject: [PATCH 23/34] Remove unnecessary markup from top of the document --- aspnetcore/security/app-secrets.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/aspnetcore/security/app-secrets.md b/aspnetcore/security/app-secrets.md index 88060ebf5d..3d33ccbcfc 100644 --- a/aspnetcore/security/app-secrets.md +++ b/aspnetcore/security/app-secrets.md @@ -13,8 +13,6 @@ uid: security/app-secrets --- # Safe storage of app secrets during development in ASP.NET Core - - By [Rick Anderson](https://twitter.com/RickAndMSFT), [Daniel Roth](https://github.com/danroth27), and [Scott Addie](https://scottaddie.com) This document shows how you can use the Secret Manager tool in development to keep secrets out of your code. The most important point is you should never store passwords or other sensitive data in source code, and you shouldn't use production secrets in development and test mode. You can instead use the [configuration](../fundamentals/configuration.md) system to read these values from environment variables or from values stored using the Secret Manager tool. The Secret Manager tool helps prevent sensitive data from being checked into source control. The [configuration](../fundamentals/configuration.md) system can read secrets stored with the Secret Manager tool described in this article. From 9332fc59406e4d855853e8e78d11f8bbdda1f174 Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Thu, 12 Oct 2017 15:14:00 -0500 Subject: [PATCH 24/34] React to feedback --- .../authorization/limitingidentitybyscheme.md | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/aspnetcore/security/authorization/limitingidentitybyscheme.md b/aspnetcore/security/authorization/limitingidentitybyscheme.md index 087fe51c68..598f323c75 100644 --- a/aspnetcore/security/authorization/limitingidentitybyscheme.md +++ b/aspnetcore/security/authorization/limitingidentitybyscheme.md @@ -1,20 +1,20 @@ --- -title: Limiting identity by scheme - ASP.NET Core +title: Authorize with a specific scheme - ASP.NET Core author: rick-anderson -description: This article explains how to limit identity to a specific schema when working with multiple authentication methods. +description: This article explains how to limit identity to a specific scheme when working with multiple authentication methods. keywords: ASP.NET Core,identity,authentication scheme ms.author: riande manager: wpickett -ms.date: 10/10/2017 +ms.date: 10/12/2017 ms.topic: article ms.assetid: d3d6ca1b-b4b5-4bf7-898e-dcd90ec1bf8c ms.technology: aspnet ms.prod: asp.net-core uid: security/authorization/limitingidentitybyscheme --- -# Limiting identity by scheme +# Authorize with a specific scheme -In some scenarios, such as Single Page Applications (SPAs), it's common to use multiple authentication methods. For example, the app may use cookie-based authentication to log in and JWT bearer authentication for JavaScript requests. In some cases, the app may have multiple instances of an authentication middleware. For example, two cookie middlewares where one contains a basic identity and one is created when a multi-factor authentication (MFA) has been triggered. MFA may be triggered because the user requested an operation that requires extra security. +In some scenarios, such as Single Page Applications (SPAs), it's common to use multiple authentication methods. For example, the app may use cookie-based authentication to log in and JWT bearer authentication for JavaScript requests. In some cases, the app may have multiple instances of an authentication handler. For example, two cookie handlers where one contains a basic identity and one is created when a multi-factor authentication (MFA) has been triggered. MFA may be triggered because the user requested an operation that requires extra security. # [ASP.NET Core 2.x](#tab/aspnetcore2x) @@ -36,10 +36,10 @@ public void ConfigureServices(IServiceCollection services) }); ``` -In the preceding code, two authentication services have been added: one for cookies and one for bearer. +In the preceding code, two authentication handlers have been added: one for cookies and one for bearer. >[!NOTE] ->When adding multiple authentication middlewares, ensure that no middleware is configured to run automatically. Invoking `AddAuthentication` with no arguments ensures that no middleware is configured to run automatically. If the app invokes `AddAuthentication` with arguments, filtering by scheme doesn't work. For example, calling `AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)` makes cookies run automatically. +>Specifying the default scheme results in the `HttpContext.User` property being set to that identity. If that behavior isn't desired, disable it by invoking the parameterless form of `AddAuthentication`. # [ASP.NET Core 1.x](#tab/aspnetcore1x) @@ -63,20 +63,21 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerF AuthenticationScheme = "Bearer", AutomaticAuthenticate = false, Audience = "http://localhost:5001/", - Authority = "http://localhost:5000/" + Authority = "http://localhost:5000/", + RequireHttpsMetadata = false }); ``` In the preceding code, two authentication middlewares have been added: one for cookies and one for bearer. >[!NOTE] ->When adding multiple authentication middlewares, ensure that no middleware is configured to run automatically. An app ensures that no middleware is configured to run automatically by setting the `AuthenticationOptions.AutomaticAuthenticate` property to false. If the app fails to set `AuthenticationOptions.AutomaticAuthenticate` to false, filtering by scheme doesn't work. +>Specifying the default scheme results in the `HttpContext.User` property being set to that identity. If that behavior isn't desired, disable it by setting the `AuthenticationOptions.AutomaticAuthenticate` property to `false`. --- ## Selecting the scheme with the Authorize attribute -At the point of authorization, the app indicates the middleware to be used. Select the middleware with which the app will authorize by passing a comma-delimited list of authentication schemes to `[Authorize]`. The `[Authorize]` attribute specifies the authentication scheme or schemes to use regardless of whether a default is configured. For example: +At the point of authorization, the app indicates the handler to be used. Select the handler with which the app will authorize by passing a comma-delimited list of authentication schemes to `[Authorize]`. The `[Authorize]` attribute specifies the authentication scheme or schemes to use regardless of whether a default is configured. For example: # [ASP.NET Core 2.x](#tab/aspnetcore2x) @@ -94,7 +95,7 @@ public class MixedController : Controller --- -In the preceding example, both the cookie and bearer middlewares run and have a chance to create and append an identity for the current user. By specifying a single scheme only, the specified middleware runs. +In the preceding example, both the cookie and bearer handlers run and have a chance to create and append an identity for the current user. By specifying a single scheme only, the corresponding handler runs. # [ASP.NET Core 2.x](#tab/aspnetcore2x) @@ -112,7 +113,7 @@ public class MixedController : Controller --- -In the preceding code, only the middleware with the "Bearer" scheme runs. Any cookie-based identities are ignored. +In the preceding code, only the handler with the "Bearer" scheme runs. Any cookie-based identities are ignored. ## Selecting the scheme with policies @@ -125,9 +126,14 @@ services.AddAuthorization(options => { policy.AuthenticationSchemes.Add("Bearer"); policy.RequireAuthenticatedUser(); - policy.Requirements.Add(new Over18Requirement()); + policy.Requirements.Add(new MinimumAgeRequirement()); }); }); ``` -In the preceding example, the "Over18" policy only runs against the identity created by the "Bearer" middleware. +In the preceding example, the "Over18" policy only runs against the identity created by the "Bearer" handler. Use the policy by setting the `[Authorize]` attribute's `Policy` property: + +```csharp +[Authorize(Policy = "Over18")] +public class RegistrationController : Controller +``` From 8831b607626a3f1e49ca17ba384924e0bb24a32f Mon Sep 17 00:00:00 2001 From: Luke Latham <1622880+guardrex@users.noreply.github.com> Date: Thu, 12 Oct 2017 15:19:21 -0500 Subject: [PATCH 25/34] Escape underscores --- .../consumer-apis/purpose-strings-multitenancy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/security/data-protection/consumer-apis/purpose-strings-multitenancy.md b/aspnetcore/security/data-protection/consumer-apis/purpose-strings-multitenancy.md index bb05f9ebed..d6953a1456 100644 --- a/aspnetcore/security/data-protection/consumer-apis/purpose-strings-multitenancy.md +++ b/aspnetcore/security/data-protection/consumer-apis/purpose-strings-multitenancy.md @@ -16,7 +16,7 @@ uid: security/data-protection/consumer-apis/purpose-strings-multitenancy Since an IDataProtector is also implicitly an IDataProtectionProvider, purposes can be chained together. In this sense provider.CreateProtector([ "purpose1", "purpose2" ]) is equivalent to provider.CreateProtector("purpose1").CreateProtector("purpose2"). -This allows for some interesting hierarchical relationships through the data protection system. In the earlier example of [Contoso.Messaging.SecureMessage](purpose-strings.md#data-protection-contoso-purpose), the SecureMessage component can call provider.CreateProtector("Contoso.Messaging.SecureMessage") once upfront and cache the result into a private _myProvider field. Future protectors can then be created via calls to _myProvider.CreateProtector("User: username"), and these protectors would be used for securing the individual messages. +This allows for some interesting hierarchical relationships through the data protection system. In the earlier example of [Contoso.Messaging.SecureMessage](purpose-strings.md#data-protection-contoso-purpose), the SecureMessage component can call provider.CreateProtector("Contoso.Messaging.SecureMessage") once upfront and cache the result into a private \_myProvider field. Future protectors can then be created via calls to \_myProvider.CreateProtector("User: username"), and these protectors would be used for securing the individual messages. This can also be flipped. Consider a single logical application which hosts multiple tenants (a CMS seems reasonable), and each tenant can be configured with its own authentication and state management system. The umbrella application has a single master provider, and it calls provider.CreateProtector("Tenant 1") and provider.CreateProtector("Tenant 2") to give each tenant its own isolated slice of the data protection system. The tenants could then derive their own individual protectors based on their own needs, but no matter how hard they try they cannot create protectors which collide with any other tenant in the system. Graphically this is represented as below. From b5a516462eb7c2081a4ef7c3e60bc045a9ed07cc Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Thu, 12 Oct 2017 15:25:57 -0500 Subject: [PATCH 26/34] Change snippet types to cshtml --- aspnetcore/security/authorization/views.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aspnetcore/security/authorization/views.md b/aspnetcore/security/authorization/views.md index 2e128801cd..2d4d557edb 100644 --- a/aspnetcore/security/authorization/views.md +++ b/aspnetcore/security/authorization/views.md @@ -20,7 +20,7 @@ Often a developer will want to show, hide or otherwise modify a UI based on the Once you have injected the authorization service you use it by calling the `AuthorizeAsync` method in exactly the same way as you would check during [resource based authorization](resourcebased.md#security-authorization-resource-based-imperative). -```csharp +```cshtml @if (await AuthorizationService.AuthorizeAsync(User, "PolicyName")) {

This paragraph is displayed because you fulfilled PolicyName.

@@ -31,7 +31,7 @@ In some cases the resource will be your view model, and you can call `AuthorizeA # [ASP.NET Core 2.x](#tab/aspnetcore2x) -```csharp +```cshtml @if ((await AuthorizationService.AuthorizeAsync(User, Model, Operations.Edit)).Succeeded) {

Date: Thu, 12 Oct 2017 15:29:48 -0500 Subject: [PATCH 27/34] Fence it! --- .../consumer-apis/purpose-strings-multitenancy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/security/data-protection/consumer-apis/purpose-strings-multitenancy.md b/aspnetcore/security/data-protection/consumer-apis/purpose-strings-multitenancy.md index d6953a1456..e0c2ccf279 100644 --- a/aspnetcore/security/data-protection/consumer-apis/purpose-strings-multitenancy.md +++ b/aspnetcore/security/data-protection/consumer-apis/purpose-strings-multitenancy.md @@ -16,7 +16,7 @@ uid: security/data-protection/consumer-apis/purpose-strings-multitenancy Since an IDataProtector is also implicitly an IDataProtectionProvider, purposes can be chained together. In this sense provider.CreateProtector([ "purpose1", "purpose2" ]) is equivalent to provider.CreateProtector("purpose1").CreateProtector("purpose2"). -This allows for some interesting hierarchical relationships through the data protection system. In the earlier example of [Contoso.Messaging.SecureMessage](purpose-strings.md#data-protection-contoso-purpose), the SecureMessage component can call provider.CreateProtector("Contoso.Messaging.SecureMessage") once upfront and cache the result into a private \_myProvider field. Future protectors can then be created via calls to \_myProvider.CreateProtector("User: username"), and these protectors would be used for securing the individual messages. +This allows for some interesting hierarchical relationships through the data protection system. In the earlier example of [Contoso.Messaging.SecureMessage](purpose-strings.md#data-protection-contoso-purpose), the SecureMessage component can call provider.CreateProtector("Contoso.Messaging.SecureMessage") once upfront and cache the result into a private `_myProvide` field. Future protectors can then be created via calls to `_myProvider.CreateProtector("User: username")`, and these protectors would be used for securing the individual messages. This can also be flipped. Consider a single logical application which hosts multiple tenants (a CMS seems reasonable), and each tenant can be configured with its own authentication and state management system. The umbrella application has a single master provider, and it calls provider.CreateProtector("Tenant 1") and provider.CreateProtector("Tenant 2") to give each tenant its own isolated slice of the data protection system. The tenants could then derive their own individual protectors based on their own needs, but no matter how hard they try they cannot create protectors which collide with any other tenant in the system. Graphically this is represented as below. From 8e163af0e5df8373e97e123993eb5f42f8dfbd84 Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Thu, 12 Oct 2017 15:47:54 -0500 Subject: [PATCH 28/34] Convert to xref link --- aspnetcore/fundamentals/environments.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/fundamentals/environments.md b/aspnetcore/fundamentals/environments.md index 6bd8d96da7..2a08910c77 100644 --- a/aspnetcore/fundamentals/environments.md +++ b/aspnetcore/fundamentals/environments.md @@ -45,7 +45,7 @@ Here is a `launchSettings.json` file that includes profiles for `Development` an Changes made to project profiles may not take effect until the web server used is restarted (in particular, Kestrel must be restarted before it will detect changes made to its environment). >[!WARNING] -> Environment variables stored in *launchSettings.json* are not secured in any way and will be part of the source code repository for your project, if you use one. **Never store credentials or other secret data in this file.** If you need a place to store such data, use the *Secret Manager* tool described in [Safe storage of app secrets during development](../security/app-secrets.md#security-app-secrets). +> Environment variables stored in *launchSettings.json* are not secured in any way and will be part of the source code repository for your project, if you use one. **Never store credentials or other secret data in this file.** If you need a place to store such data, use the *Secret Manager* tool described in [Safe storage of app secrets during development](xref:security/app-secrets). ### Staging From 5bb923bbccda501dabdf69524dbfc8bc14112a21 Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Thu, 12 Oct 2017 20:30:16 -0500 Subject: [PATCH 29/34] HTML --> cshtml --- aspnetcore/fundamentals/localization.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/aspnetcore/fundamentals/localization.md b/aspnetcore/fundamentals/localization.md index 2dd72be85f..a406b1fcf6 100644 --- a/aspnetcore/fundamentals/localization.md +++ b/aspnetcore/fundamentals/localization.md @@ -63,7 +63,7 @@ Some developers use the `Startup` class to contain global or shared strings. In The `IViewLocalizer` service provides localized strings for a [view](https://docs.microsoft.com/aspnet/core). The `ViewLocalizer` class implements this interface and finds the resource location from the view file path. The following code shows how to use the default implementation of `IViewLocalizer`: -[!code-HTML[Main](localization/sample/Localization/Views/Home/About.cshtml)] +[!code-cshtml[Main](localization/sample/Localization/Views/Home/About.cshtml)] The default implementation of `IViewLocalizer` finds the resource file based on the view's file name. There is no option to use a global shared resource file. `ViewLocalizer` implements the localizer using `IHtmlLocalizer`, so Razor doesn't HTML encode the localized string. You can parameterize resource strings and `IViewLocalizer` will HTML encode the parameters, but not the resource string. Consider the following Razor markup: @@ -85,7 +85,7 @@ Notes: To use a shared resource file in a view, inject `IHtmlLocalizer`: -[!code-HTML[Main](../fundamentals/localization/sample/Localization/Views/Test/About.cshtml?highlight=5,12)] +[!code-cshtml[Main](../fundamentals/localization/sample/Localization/Views/Test/About.cshtml?highlight=5,12)] ## DataAnnotations localization @@ -114,7 +114,7 @@ public void ConfigureServices(IServiceCollection services) } ``` -In the preceeding code, `SharedResource` is the class corresponding to the resx where your validation messages are stored. With this approach, DataAnnotations will only use `SharedResource`, rather than the resource for each class. +In the preceeding code, `SharedResource` is the class corresponding to the resx where your validation messages are stored. With this approach, DataAnnotations will only use `SharedResource`, rather than the resource for each class. ## Provide localized resources for the languages and cultures you support @@ -284,11 +284,11 @@ Use `RequestLocalizationOptions` to add or remove localization providers. This sample **Localization.StarterWeb** project on [GitHub](https://github.com/aspnet/entropy) contains UI to set the `Culture`. The *Views/Shared/_SelectLanguagePartial.cshtml* file allows you to select the culture from the list of supported cultures: -[!code-HTML[Main](localization/sample/Localization/Views/Shared/_SelectLanguagePartial.cshtml)] +[!code-cshtml[Main](localization/sample/Localization/Views/Shared/_SelectLanguagePartial.cshtml)] The *Views/Shared/_SelectLanguagePartial.cshtml* file is added to the `footer` section of the layout file so it will be available to all views: -[!code-HTML[Main](localization/sample/Localization/Views/Shared/_Layout.cshtml?range=43-56&highlight=10)] +[!code-cshtml[Main](localization/sample/Localization/Views/Shared/_Layout.cshtml?range=43-56&highlight=10)] The `SetLanguage` method sets the culture cookie. From afc945db9c2b6cbf3db4d439b6e2a688f10adc70 Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Thu, 12 Oct 2017 21:22:25 -0500 Subject: [PATCH 30/34] Remove Localization.AspNetCore.TagHelpers package mention (#4553) --- aspnetcore/fundamentals/localization.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/aspnetcore/fundamentals/localization.md b/aspnetcore/fundamentals/localization.md index a406b1fcf6..218bd7fabe 100644 --- a/aspnetcore/fundamentals/localization.md +++ b/aspnetcore/fundamentals/localization.md @@ -43,7 +43,7 @@ Use the `IHtmlLocalizer` implementation for resources that contain HTML. `IHt [!code-csharp[Main](../fundamentals/localization/sample/Localization/Controllers/BookController.cs?highlight=3,5,20&start=1&end=24)] -Note: You generally want to only localize text and not HTML. +**Note:** You generally want to only localize text and not HTML. At the lowest level, you can get `IStringLocalizerFactory` out of [Dependency Injection](dependency-injection.md): @@ -55,7 +55,7 @@ You can partition your localized strings by controller, area, or have just one c [!code-csharp[Main](localization/sample/Localization/Resources/SharedResource.cs)] -Some developers use the `Startup` class to contain global or shared strings. In the sample below, the `InfoController` and the `SharedResource` localizers are used: +Some developers use the `Startup` class to contain global or shared strings. In the sample below, the `InfoController` and the `SharedResource` localizers are used: [!code-csharp[Main](localization/sample/Localization/Controllers/InfoController.cs?range=9-26)] @@ -79,9 +79,7 @@ A French resource file could contain the following: The rendered view would contain the HTML markup from the resource file. -Notes: -- View localization requires the "Localization.AspNetCore.TagHelpers" NuGet package. -- You generally want to only localize text and not HTML. +**Note:** You generally want to only localize text and not HTML. To use a shared resource file in a view, inject `IHtmlLocalizer`: @@ -145,7 +143,7 @@ A resource file is a useful mechanism for separating localizable strings from co -If you are using Visual Studio 2017 Preview version 15.3, you'll get an error indicator in the resource editor. Remove the *ResXFileCodeGenerator* value from the *Custom Tool* properties grid to prevent this error message: +If you are using Visual Studio 2017 Preview version 15.3, you'll get an error indicator in the resource editor. Remove the *ResXFileCodeGenerator* value from the *Custom Tool* properties grid to prevent this error message: ![Resx editor](localization/_static/err.png) @@ -221,9 +219,9 @@ If you only pass in one of the two (`culture` or `ui-culture`), the query string ### CookieRequestCultureProvider -Production apps will often provide a mechanism to set the culture with the ASP.NET Core culture cookie. Use the `MakeCookieValue` method to create a cookie. +Production apps will often provide a mechanism to set the culture with the ASP.NET Core culture cookie. Use the `MakeCookieValue` method to create a cookie. -The `CookieRequestCultureProvider` `DefaultCookieName` returns the default cookie name used to track the user’s preferred culture information. The default cookie name is ".AspNetCore.Culture". +The `CookieRequestCultureProvider` `DefaultCookieName` returns the default cookie name used to track the user’s preferred culture information. The default cookie name is ".AspNetCore.Culture". The cookie format is `c=%LANGCODE%|uic=%LANGCODE%`, where `c` is `Culture` and `uic` is `UICulture`, for example: From e9bd53f53c0ba148343cd2057c714a7c72ee81e9 Mon Sep 17 00:00:00 2001 From: Rick Anderson Date: Thu, 12 Oct 2017 16:41:57 -1000 Subject: [PATCH 31/34] Update index.md --- aspnet/mvc/overview/getting-started/introduction/index.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aspnet/mvc/overview/getting-started/introduction/index.md b/aspnet/mvc/overview/getting-started/introduction/index.md index 8954f96823..0092617e93 100644 --- a/aspnet/mvc/overview/getting-started/introduction/index.md +++ b/aspnet/mvc/overview/getting-started/introduction/index.md @@ -17,6 +17,8 @@ Getting Started with ASP.NET MVC 5 ==================== > Introduction to ASP.NET MVC 5 +An updated version of this tutorial is available [here](https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/start-mvc) using the latest version of [Visual Studio.](https://www.visualstudio.com) The new tutorial uses [ASP.NET Core MVC](https://docs.microsoft.com/en-us/aspnet/core/mvc/), which provides **many** improvements over this tutorial. + - [Getting Started](getting-started.md) - [Adding a Controller](adding-a-controller.md) From 364790b5035fac16aedfd62018d3e502ef799c4b Mon Sep 17 00:00:00 2001 From: Michael DePouw Date: Fri, 13 Oct 2017 09:34:02 -0400 Subject: [PATCH 32/34] fix illegal links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit aspnetcore/security/authorization/policies.md • Line 19: [Warning] Illegal link: `[role authorization](roles.md#security-authorization-role-based)` -- missing bookmark. The file security/authorization/roles.md doesn't contain a bookmark named security-authorization-role-based. • Line 19: [Warning] Illegal link: `[claims authorization](claims.md#security-authorization-claims-based)` -- missing bookmark. The file security/authorization/claims.md doesn't contain a bookmark named security-authorization-claims-based. --- aspnetcore/security/authorization/policies.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/security/authorization/policies.md b/aspnetcore/security/authorization/policies.md index 4e0f9660a0..386c129ab7 100644 --- a/aspnetcore/security/authorization/policies.md +++ b/aspnetcore/security/authorization/policies.md @@ -16,7 +16,7 @@ uid: security/authorization/policies -Underneath the covers the [role authorization](roles.md#security-authorization-role-based) and [claims authorization](claims.md#security-authorization-claims-based) make use of a requirement, a handler for the requirement and a pre-configured policy. These building blocks allow you to express authorization evaluations in code, allowing for a richer, reusable, and easily testable authorization structure. +Underneath the covers the [role authorization](roles.md) and [claims authorization](claims.md) make use of a requirement, a handler for the requirement and a pre-configured policy. These building blocks allow you to express authorization evaluations in code, allowing for a richer, reusable, and easily testable authorization structure. An authorization policy is made up of one or more requirements and registered at application startup as part of the Authorization service configuration, in `ConfigureServices` in the *Startup.cs* file. From 912a1efc8f16e463188fb645eda224cc66d4e38d Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Fri, 13 Oct 2017 15:50:30 -0500 Subject: [PATCH 33/34] Fix invalid bookmarks (#4570) --- aspnetcore/aspnetcore-1.1.md | 2 +- aspnetcore/client-side/angular.md | 2 +- aspnetcore/client-side/bootstrap.md | 2 +- aspnetcore/fundamentals/app-state.md | 5 ++- aspnetcore/fundamentals/configuration.md | 8 ++-- .../fundamentals/dependency-injection.md | 2 +- aspnetcore/fundamentals/localization.md | 2 +- aspnetcore/fundamentals/middleware.md | 6 +-- aspnetcore/fundamentals/owin.md | 2 +- aspnetcore/fundamentals/routing.md | 4 +- aspnetcore/fundamentals/static-files.md | 2 +- aspnetcore/fundamentals/url-rewriting.md | 2 +- .../includes/mvc-intro/adding-model4.md | 2 +- aspnetcore/migration/http-modules.md | 4 +- aspnetcore/migration/identity.md | 2 +- aspnetcore/migration/mvc.md | 2 +- .../mvc/controllers/dependency-injection.md | 2 +- aspnetcore/mvc/controllers/filters.md | 4 +- aspnetcore/mvc/controllers/routing.md | 38 +++++++++---------- aspnetcore/mvc/controllers/testing.md | 2 +- aspnetcore/mvc/views/layout.md | 6 +-- aspnetcore/mvc/views/tag-helpers/intro.md | 6 +-- aspnetcore/mvc/views/working-with-forms.md | 2 +- .../security/authentication/social/index.md | 2 +- .../authentication/social/other-logins.md | 2 +- aspnetcore/security/authorization/claims.md | 2 +- .../authorization/dependencyinjection.md | 2 +- .../security/authorization/introduction.md | 2 +- aspnetcore/security/authorization/policies.md | 10 ++--- .../security/authorization/resourcebased.md | 4 +- aspnetcore/security/authorization/roles.md | 4 +- .../security/authorization/secure-data.md | 2 +- aspnetcore/security/authorization/simple.md | 2 +- aspnetcore/security/authorization/views.md | 2 +- aspnetcore/security/cors.md | 2 +- aspnetcore/security/cross-site-scripting.md | 4 +- .../compatibility/replacing-machinekey.md | 2 +- .../configuration/default-settings.md | 2 +- .../configuration/machine-wide-policy.md | 4 +- .../data-protection/configuration/overview.md | 18 ++++----- .../consumer-apis/dangerous-unprotect.md | 2 +- .../consumer-apis/purpose-strings.md | 4 +- .../extensibility/core-crypto.md | 14 +++---- .../extensibility/key-management.md | 6 +-- .../extensibility/misc-apis.md | 2 +- .../authenticated-encryption-details.md | 2 +- .../implementation/context-headers.md | 4 +- .../implementation/key-encryption-at-rest.md | 6 +-- .../implementation/key-management.md | 4 +- .../implementation/key-storage-ephemeral.md | 2 +- .../implementation/key-storage-format.md | 2 +- .../implementation/key-storage-providers.md | 2 +- .../implementation/subkeyderivation.md | 4 +- .../data-protection/using-data-protection.md | 2 +- .../web-api-help-pages-using-swagger.md | 2 +- 55 files changed, 117 insertions(+), 116 deletions(-) diff --git a/aspnetcore/aspnetcore-1.1.md b/aspnetcore/aspnetcore-1.1.md index 912388acef..190ac8d1f2 100644 --- a/aspnetcore/aspnetcore-1.1.md +++ b/aspnetcore/aspnetcore-1.1.md @@ -21,7 +21,7 @@ ASP.NET Core 1.1 includes the following new features: - [Response Caching Middleware](xref:performance/caching/middleware) - [View Components as Tag Helpers](xref:mvc/views/view-components#invoking-a-view-component-as-a-tag-helper) - [Middleware as MVC filters](xref:mvc/controllers/filters#using-middleware-in-the-filter-pipeline) -- [Cookie-based TempData provider](xref:fundamentals/app-state#cookie-based-tempdata-provider ) +- [Cookie-based TempData provider](xref:fundamentals/app-state#tempdata-providers) - [Azure App Service logging provider](xref:fundamentals/logging#appservice) - [Azure Key Vault configuration provider](xref:security/key-vault-configuration) - [Azure and Redis Storage Data Protection Key Repositories](xref:security/data-protection/implementation/key-storage-providers#azure-and-redis) diff --git a/aspnetcore/client-side/angular.md b/aspnetcore/client-side/angular.md index 5bdea5b52a..645921754d 100644 --- a/aspnetcore/client-side/angular.md +++ b/aspnetcore/client-side/angular.md @@ -38,7 +38,7 @@ To start using AngularJS in your ASP.NET application, you must either install it There are several ways to add AngularJS to your application. If you’re starting a new ASP.NET Core web application in Visual Studio, you can add AngularJS using the built-in [Bower](bower.md) support. Open *bower.json*, and add an entry to the `dependencies` property: - + [!code-json[Main](../client-side/angular/sample/AngularJSSample/src/AngularJSSample/bower.json?highlight=9)] diff --git a/aspnetcore/client-side/bootstrap.md b/aspnetcore/client-side/bootstrap.md index d1a64d2038..69f2acc3ba 100644 --- a/aspnetcore/client-side/bootstrap.md +++ b/aspnetcore/client-side/bootstrap.md @@ -14,7 +14,7 @@ uid: client-side/bootstrap --- # Building beautiful, responsive sites with Bootstrap - + By [Steve Smith](https://ardalis.com/) diff --git a/aspnetcore/fundamentals/app-state.md b/aspnetcore/fundamentals/app-state.md index 3f383ee903..0a0c7071e3 100644 --- a/aspnetcore/fundamentals/app-state.md +++ b/aspnetcore/fundamentals/app-state.md @@ -39,6 +39,7 @@ The in-memory session provider stores session data on the local server. If you p ASP.NET Core MVC exposes the [TempData](https://docs.microsoft.com/dotnet/api/microsoft.aspnetcore.mvc.controller.tempdata?view=aspnetcore-2.0#Microsoft_AspNetCore_Mvc_Controller_TempData) property on a [controller](https://docs.microsoft.com/dotnet/api/microsoft.aspnetcore.mvc.controller?view=aspnetcore-2.0). This property stores data until it is read. The `Keep` and `Peek` methods can be used to examine the data without deletion. `TempData` is particularly useful for redirection, when data is needed for more than a single request. `TempData` is implemented by TempData providers, for example, using either cookies or session state. + ### TempData providers # [ASP.NET Core 2.x](#tab/aspnetcore2x) @@ -102,7 +103,7 @@ The `Items` collection is a good location to store data that is needed only whil Caching is an efficient way to store and retrieve data. You can control the lifetime of cached items based on time and other considerations. Learn more about [Caching](../performance/caching/index.md). - + ## Working with Session State ### Configuring Session @@ -228,7 +229,7 @@ public class HomeController : Controller This approach also has the advantage of eliminating repetition of "magic strings" in multiple places in the code. - + ## Application state data diff --git a/aspnetcore/fundamentals/configuration.md b/aspnetcore/fundamentals/configuration.md index 438570abfe..77e9ca1d9e 100644 --- a/aspnetcore/fundamentals/configuration.md +++ b/aspnetcore/fundamentals/configuration.md @@ -76,7 +76,7 @@ Configuration considerations: * **Never** store passwords or other sensitive data in configuration provider code or in plain text configuration files. Don't use production secrets in your development or test environments. Instead, specify secrets outside the project tree, so they cannot be accidentally committed into your repository. Learn more about [Working with Multiple Environments](environments.md) and managing [safe storage of app secrets during development](../security/app-secrets.md). * If `:` cannot be used in environment variables in your system, replace `:` with `__` (double underscore). - + ## Using Options and configuration objects @@ -89,7 +89,7 @@ The options class must be non-abstract with a public parameterless constructor. [!code-csharp[Main](configuration/sample/UsingOptions/Models/MyOptions.cs)] - + In the following code, the JSON configuration provider is enabled. The `MyOptions` class is added to the service container and bound to configuration. @@ -143,7 +143,7 @@ You can also supply options in a view model or inject `IOptions` direc [!code-html[Main](configuration/sample/UsingOptions/Views/Home/Index.cshtml?highlight=3-4,16-17,20-21)] - + ## IOptionsSnapshot @@ -242,7 +242,7 @@ public void CanBindObjectTree() } ``` - + ## Basic sample of Entity Framework custom provider diff --git a/aspnetcore/fundamentals/dependency-injection.md b/aspnetcore/fundamentals/dependency-injection.md index 1c36863b72..d3e86ffc4a 100644 --- a/aspnetcore/fundamentals/dependency-injection.md +++ b/aspnetcore/fundamentals/dependency-injection.md @@ -15,7 +15,7 @@ ms.custom: H1Hack27Feb2017 --- # Introduction to Dependency Injection in ASP.NET Core - + By [Steve Smith](https://ardalis.com/) and [Scott Addie](https://scottaddie.com) diff --git a/aspnetcore/fundamentals/localization.md b/aspnetcore/fundamentals/localization.md index 218bd7fabe..9b55f62efe 100644 --- a/aspnetcore/fundamentals/localization.md +++ b/aspnetcore/fundamentals/localization.md @@ -96,7 +96,7 @@ DataAnnotations error messages are localized with `IStringLocalizer`. Using t In ASP.NET Core MVC 1.1.0 and higher, non-validation attributes are localized. ASP.NET Core MVC 1.0 does **not** look up localized strings for non-validation attributes. - + ### Using one resource string for multiple classes The following code shows how to use one resource string for validation attributes with multiple classes: diff --git a/aspnetcore/fundamentals/middleware.md b/aspnetcore/fundamentals/middleware.md index 819c2f0274..dfce1f0dc2 100644 --- a/aspnetcore/fundamentals/middleware.md +++ b/aspnetcore/fundamentals/middleware.md @@ -14,7 +14,7 @@ uid: fundamentals/middleware --- # ASP.NET Core Middleware Fundamentals - + By [Rick Anderson](https://twitter.com/RickAndMSFT) and [Steve Smith](https://ardalis.com/) @@ -133,7 +133,7 @@ public void Configure(IApplicationBuilder app) } ``` - + ### Use, Run, and Map @@ -201,7 +201,7 @@ ASP.NET Core ships with the following middleware components: | [Static Files](xref:fundamentals/static-files) | Provides support for serving static files and directory browsing. | | [URL Rewriting Middleware](xref:fundamentals/url-rewriting) | Provides support for rewriting URLs and redirecting requests. | - + ## Writing middleware diff --git a/aspnetcore/fundamentals/owin.md b/aspnetcore/fundamentals/owin.md index 79aa5cd467..d8f994f41e 100644 --- a/aspnetcore/fundamentals/owin.md +++ b/aspnetcore/fundamentals/owin.md @@ -86,7 +86,7 @@ app.UseOwin(pipeline => }); ``` - + ## Using ASP.NET Hosting on an OWIN-based server diff --git a/aspnetcore/fundamentals/routing.md b/aspnetcore/fundamentals/routing.md index 805cff54f5..03f45c0ab1 100644 --- a/aspnetcore/fundamentals/routing.md +++ b/aspnetcore/fundamentals/routing.md @@ -35,7 +35,7 @@ Generally, an app has a single collection of routes. When a request arrives, the Routing is connected to the [middleware](middleware.md) pipeline by the `RouterMiddleware` class. [ASP.NET MVC](../mvc/overview.md) adds routing to the middleware pipeline as part of its configuration. To learn about using routing as a standalone component, see [using-routing-middleware](#using-routing-middleware). - + ### URL matching @@ -155,7 +155,7 @@ This template will match a URL path like `/Products/5` and will extract the valu ![Locals Windows tokens](routing/_static/tokens.png) - + ### URL generation diff --git a/aspnetcore/fundamentals/static-files.md b/aspnetcore/fundamentals/static-files.md index 3f145dd65a..ed99b18d28 100644 --- a/aspnetcore/fundamentals/static-files.md +++ b/aspnetcore/fundamentals/static-files.md @@ -16,7 +16,7 @@ ms.custom: H1Hack27Feb2017 # Working with static files in ASP.NET Core - + By [Rick Anderson](https://twitter.com/RickAndMSFT) diff --git a/aspnetcore/fundamentals/url-rewriting.md b/aspnetcore/fundamentals/url-rewriting.md index 458f5abdc5..73143f36f2 100644 --- a/aspnetcore/fundamentals/url-rewriting.md +++ b/aspnetcore/fundamentals/url-rewriting.md @@ -93,7 +93,7 @@ The part of the expression contained within parentheses is called a *capture gro In the replacement string, captured groups are injected into the string with the dollar sign (`$`) followed by the sequence number of the capture. The first capture group value is obtained with `$1`, the second with `$2`, and they continue in sequence for the capture groups in your regex. There's only one captured group in the redirect rule regex in the sample app, so there's only one injected group in the replacement string, which is `$1`. When the rule is applied, the URL becomes `/redirected/1234/5678`. - + ### URL redirect to a secure endpoint Use `AddRedirectToHttps` to redirect HTTP requests to the same host and path using HTTPS (`https://`). If the status code isn't supplied, the middleware defaults to 302 (Found). If the port isn't supplied, the middleware defaults to `null`, which means the protocol changes to `https://` and the client accesses the resource on port 443. The example shows how to set the status code to 301 (Moved Permanently) and change the port to 5001. ```csharp diff --git a/aspnetcore/includes/mvc-intro/adding-model4.md b/aspnetcore/includes/mvc-intro/adding-model4.md index c7641228cc..943ccb608d 100644 --- a/aspnetcore/includes/mvc-intro/adding-model4.md +++ b/aspnetcore/includes/mvc-intro/adding-model4.md @@ -8,7 +8,7 @@ Open the *Controllers/MoviesController.cs* file and examine the constructor: The constructor uses [Dependency Injection](xref:fundamentals/dependency-injection) to inject the database context (`MvcMovieContext `) into the controller. The database context is used in each of the [CRUD](https://wikipedia.org/wiki/Create,_read,_update_and_delete) methods in the controller. - + ## Strongly typed models and the @model keyword diff --git a/aspnetcore/migration/http-modules.md b/aspnetcore/migration/http-modules.md index e20dc20103..2ddcdd9828 100644 --- a/aspnetcore/migration/http-modules.md +++ b/aspnetcore/migration/http-modules.md @@ -92,7 +92,7 @@ An existing HTTP module will look similar to this: As shown in the [Middleware](../fundamentals/middleware.md) page, an ASP.NET Core middleware is a class that exposes an `Invoke` method taking an `HttpContext` and returning a `Task`. Your new middleware will look like this: - + [!code-csharp[Main](../migration/http-modules/sample/Asp.Net.Core/Middleware/MyMiddleware.cs?highlight=9,13,20,24,28,30,32)] @@ -100,7 +100,7 @@ The above middleware template was taken from the section on [writing middleware] The *MyMiddlewareExtensions* helper class makes it easier to configure your middleware in your `Startup` class. The `UseMyMiddleware` method adds your middleware class to the request pipeline. Services required by the middleware get injected in the middleware's constructor. - + Your module might terminate a request, for example if the user is not authorized: diff --git a/aspnetcore/migration/identity.md b/aspnetcore/migration/identity.md index daa304a953..552a71040d 100644 --- a/aspnetcore/migration/identity.md +++ b/aspnetcore/migration/identity.md @@ -14,7 +14,7 @@ uid: migration/identity --- # Migrating Authentication and Identity - + By [Steve Smith](https://ardalis.com/) diff --git a/aspnetcore/migration/mvc.md b/aspnetcore/migration/mvc.md index 7ccb58e455..1ff134dfa0 100644 --- a/aspnetcore/migration/mvc.md +++ b/aspnetcore/migration/mvc.md @@ -145,7 +145,7 @@ Upon saving the file, Bower will automatically download the dependencies to the See [Manage Client-Side Packages with Bower](../client-side/bower.md) for more information. - + ## Migrate the layout file diff --git a/aspnetcore/mvc/controllers/dependency-injection.md b/aspnetcore/mvc/controllers/dependency-injection.md index d4d298a541..5773eeee88 100644 --- a/aspnetcore/mvc/controllers/dependency-injection.md +++ b/aspnetcore/mvc/controllers/dependency-injection.md @@ -14,7 +14,7 @@ uid: mvc/controllers/dependency-injection --- # Dependency injection into controllers - + By [Steve Smith](https://ardalis.com/) diff --git a/aspnetcore/mvc/controllers/filters.md b/aspnetcore/mvc/controllers/filters.md index fef302adbd..b012a13e9d 100644 --- a/aspnetcore/mvc/controllers/filters.md +++ b/aspnetcore/mvc/controllers/filters.md @@ -78,7 +78,7 @@ You can implement `IFilterFactory` on your own attribute implementations as anot The framework includes built-in attribute-based filters that you can subclass and customize. For example, the following Result filter adds a header to the response. - + [!code-csharp[Main](./filters/sample/src/FiltersSample/Filters/AddHeaderAttribute.cs?highlight=5,16)] @@ -164,7 +164,7 @@ The `Order` property trumps scope when determining the order in which filters wi You can short-circuit the filter pipeline at any point by setting the `Result` property on the `context` parameter provided to the filter method. For instance, the following Resource filter prevents the rest of the pipeline from executing. - + [!code-csharp[Main](./filters/sample/src/FiltersSample/Filters/ShortCircuitingResourceFilterAttribute.cs?highlight=12,13,14,15)] diff --git a/aspnetcore/mvc/controllers/routing.md b/aspnetcore/mvc/controllers/routing.md index 2a973f2812..fb01e4294b 100644 --- a/aspnetcore/mvc/controllers/routing.md +++ b/aspnetcore/mvc/controllers/routing.md @@ -113,7 +113,7 @@ app.UseRouter(routes.Build()); `UseMvc` does not directly define any routes, it adds a placeholder to the route collection for the `attribute` route. The overload `UseMvc(Action)` lets you add your own routes and also supports attribute routing. `UseMvc` and all of its variations adds a placeholder for the attribute route - attribute routing is always available regardless of how you configure `UseMvc`. `UseMvcWithDefaultRoute` defines a default route and supports attribute routing. The [Attribute Routing](#attribute-routing-ref-label) section includes more details on attribute routing. - + ## Conventional routing @@ -185,7 +185,7 @@ You will only need to write custom `IActionConstraint` implementations in specia If multiple routes match, and MVC can't find a 'best' route, it will throw an `AmbiguousActionException`. - + ### Route names @@ -205,7 +205,7 @@ The route names give the route a logical name so that the named route can be use Route names have no impact on URL matching or handling of requests; they are used only for URL generation. [Routing](xref:fundamentals/routing) has more detailed information on URL generation including URL generation in MVC-specific helpers. - + ## Attribute routing @@ -319,7 +319,7 @@ Route names can be used to generate a URL based on a specific route. Route names > [!NOTE] > Contrast this with the conventional *default route*, which defines the `id` parameter as optional (`{id?}`). This ability to precisely specify APIs has advantages, such as allowing `/products` and `/products/5` to be dispatched to different actions. - + ### Combining routes @@ -364,7 +364,7 @@ public class HomeController : Controller } ``` - + ### Ordering attribute routes @@ -377,7 +377,7 @@ Attribute routes can configure an order, using the `Order` property of all of th > [!TIP] > Avoid depending on `Order`. If your URL-space requires explicit order values to route correctly, then it's likely confusing to clients as well. In general attribute routing will select the correct route with URL matching. If the default order used for URL generation isn't working, using route name as an override is usually simpler than applying the `Order` property. - + ## Token replacement in route templates ([controller], [action], [area]) @@ -409,7 +409,7 @@ Token replacement also applies to route names defined by attribute routes. `[Rou To match the literal token replacement delimiter `[` or `]`, escape it by repeating the character (`[[` or `]]`). - + ### Multiple Routes @@ -453,7 +453,7 @@ public class ProductsController : Controller > [!TIP] > While using multiple routes on actions can seem powerful, it's better to keep your application's URL space simple and well-defined. Use multiple routes on actions only where needed, for example to support existing clients. - + ### Specifying attribute route optional parameters, default values, and constraints @@ -469,7 +469,7 @@ public IActionResult ShowProduct(int id) See [Route Template Reference](../../fundamentals/routing.md#route-template-reference) for a detailed description of route template syntax. - + ### Custom route attributes using `IRouteTemplateProvider` @@ -490,7 +490,7 @@ public class MyApiControllerAttribute : Attribute, IRouteTemplateProvider The attribute from the above example automatically sets the `Template` to `"api/[controller]"` when `[MyApiController]` is applied. - + ### Using Application Model to customize attribute routes @@ -498,7 +498,7 @@ The *application model* is an object model created at startup with all of the me [!code-csharp[Main](routing/sample/main/NamespaceRoutingConvention.cs)] - + ## Mixed routing: Attribute routing vs conventional routing @@ -509,7 +509,7 @@ Actions are either conventionally routed or attribute routed. Placing a route on > [!NOTE] > What distinguishes the two types of routing systems is the process applied after a URL matches a route template. In conventional routing, the route values from the match are used to choose the action and controller from a lookup table of all conventional routed actions. In attribute routing, each template is already associated with an action, and no further lookup is needed. - + ## URL Generation @@ -562,7 +562,7 @@ Longer overloads of `Url.Action` also take an additional *route values* object t > [!TIP] > To create an absolute URL, use an overload that accepts a `protocol`: `Url.Action("Buy", "Products", new { id = 17 }, protocol: Request.Scheme)` - + ### Generating URLs by route @@ -570,7 +570,7 @@ The code above demonstrated generating a URL by passing in the controller and ac [!code-csharp[Main](routing/sample/main/Controllers/UrlGenerationControllerRouting.cs?name=snippet_1)] - + ### Generating URLs in HTML @@ -580,7 +580,7 @@ TagHelpers generate URLs through the `form` TagHelper and the `` TagHelper. B Inside views, the `IUrlHelper` is available through the `Url` property for any ad-hoc URL generation not covered by the above. - + ### Generating URLS in Action Results @@ -601,7 +601,7 @@ public Task Edit(int id, Customer customer) The action results factory methods follow a similar pattern to the methods on `IUrlHelper`. - + ### Special case for dedicated conventional routes @@ -620,7 +620,7 @@ Using these route definitions, `Url.Action("Index", "Home")` will generate the U Dedicated conventional routes rely on a special behavior of default values that don't have a corresponding route parameter that prevents the route from being "too greedy" with URL generation. In this case the default values are `{ controller = Blog, action = Article }`, and neither `controller` nor `action` appears as a route parameter. When routing performs URL generation, the values provided must match the default values. URL generation using `blog` will fail because the values `{ controller = Home, action = Index }` don't match `{ controller = Blog, action = Article }`. Routing then falls back to try `default`, which succeeds. - + ## Areas @@ -665,7 +665,7 @@ When executing an action inside an area, the route value for `area` will be avai [!code-csharp[Main](routing/sample/AreasRouting/Areas/Duck/Controllers/UsersController.cs)] - + ## Understanding IActionConstraint @@ -690,7 +690,7 @@ When the `HttpGetAttribute` executes, it will say that *Edit()* is a match for * Conceptually, `IActionConstraint` is a form of *overloading*, but instead of overloading methods with the same name, it is overloading between actions that match the same URL. Attribute routing also uses `IActionConstraint` and can result in actions from different controllers both being considered candidates. - + ### Implementing IActionConstraint diff --git a/aspnetcore/mvc/controllers/testing.md b/aspnetcore/mvc/controllers/testing.md index 5084beab4b..a3177a788c 100644 --- a/aspnetcore/mvc/controllers/testing.md +++ b/aspnetcore/mvc/controllers/testing.md @@ -79,7 +79,7 @@ The controller action has three cases to test, one for each `return` statement: The app exposes functionality as a web API (a list of ideas associated with a brainstorming session and a method for adding new ideas to a session): - + [!code-csharp[Main](testing/sample/TestingControllersSample/src/TestingControllersSample/Api/IdeasController.cs?highlight=21,22,27,30,31,32,33,34,35,36,41,42,46,52,65)] diff --git a/aspnetcore/mvc/views/layout.md b/aspnetcore/mvc/views/layout.md index ff0a5c695d..475fb34faf 100644 --- a/aspnetcore/mvc/views/layout.md +++ b/aspnetcore/mvc/views/layout.md @@ -46,7 +46,7 @@ The layout specified can use a full path (example: `/Views/Shared/_Layout.cshtml By default, every layout must call `RenderBody`. Wherever the call to `RenderBody` is placed, the contents of the view will be rendered. - + ### Sections @@ -72,7 +72,7 @@ To instruct the view engine to ignore the body or sections, call the `IgnoreBody The body and every section in a Razor page must be either rendered or ignored. - + ## Importing Shared Directives @@ -116,7 +116,7 @@ If multiple `_ViewImports.cshtml` files are run for a view, combined behavior of * `@inject`: for each property, the closest one to the view overrides any others with the same property name - + ## Running Code Before Each View diff --git a/aspnetcore/mvc/views/tag-helpers/intro.md b/aspnetcore/mvc/views/tag-helpers/intro.md index f80af701eb..b7ae10001b 100644 --- a/aspnetcore/mvc/views/tag-helpers/intro.md +++ b/aspnetcore/mvc/views/tag-helpers/intro.md @@ -51,7 +51,7 @@ The `asp-for` attribute is made available by the `For` property in the `LabelTag Tag Helpers scope is controlled by a combination of `@addTagHelper`, `@removeTagHelper`, and the "!" opt-out character. - + ### `@addTagHelper` makes Tag Helpers available @@ -82,7 +82,7 @@ To add a Tag Helper to a view using an FQN, you first add the FQN (`AuthoringTag As mentioned previously, adding the `@addTagHelper` directive to the *Views/_ViewImports.cshtml* file makes the Tag Helper available to all view files in the *Views* directory and sub-directories. You can use the `@addTagHelper` directive in specific view files if you want to opt-in to exposing the Tag Helper to only those views. - + ### `@removeTagHelper` removes Tag Helpers @@ -104,7 +104,7 @@ You can disable a Tag Helper at the element level with the Tag Helper opt-out ch You must apply the Tag Helper opt-out character to the opening and closing tag. (The Visual Studio editor automatically adds the opt-out character to the closing tag when you add one to the opening tag). After you add the opt-out character, the element and Tag Helper attributes are no longer displayed in a distinctive font. - + ### Using `@tagHelperPrefix` to make Tag Helper usage explicit diff --git a/aspnetcore/mvc/views/working-with-forms.md b/aspnetcore/mvc/views/working-with-forms.md index 03b3ce1894..6ef64a687e 100644 --- a/aspnetcore/mvc/views/working-with-forms.md +++ b/aspnetcore/mvc/views/working-with-forms.md @@ -21,7 +21,7 @@ This document demonstrates working with Forms and the HTML elements commonly use In many cases, HTML Helpers provide an alternative approach to a specific Tag Helper, but it's important to recognize that Tag Helpers do not replace HTML Helpers and there is not a Tag Helper for each HTML Helper. When an HTML Helper alternative exists, it is mentioned. - + ## The Form Tag Helper diff --git a/aspnetcore/security/authentication/social/index.md b/aspnetcore/security/authentication/social/index.md index a8280db0b9..0d0509be18 100644 --- a/aspnetcore/security/authentication/social/index.md +++ b/aspnetcore/security/authentication/social/index.md @@ -15,7 +15,7 @@ uid: security/authentication/social/index # Enabling authentication using Facebook, Google and other external providers - + By [Valeriy Novytskyy](https://github.com/01binary) and [Rick Anderson](https://twitter.com/RickAndMSFT) diff --git a/aspnetcore/security/authentication/social/other-logins.md b/aspnetcore/security/authentication/social/other-logins.md index 394d8cd357..390ed00119 100644 --- a/aspnetcore/security/authentication/social/other-logins.md +++ b/aspnetcore/security/authentication/social/other-logins.md @@ -11,7 +11,7 @@ uid: security/authentication/otherlogins --- # Short survey of other authentication providers - + By [Rick Anderson](https://twitter.com/RickAndMSFT), [Pranav Rastogi](https://github.com/rustd), and [Valeriy Novytskyy](https://github.com/01binary) diff --git a/aspnetcore/security/authorization/claims.md b/aspnetcore/security/authorization/claims.md index 4f692ed0cb..4b15faa5e8 100644 --- a/aspnetcore/security/authorization/claims.md +++ b/aspnetcore/security/authorization/claims.md @@ -14,7 +14,7 @@ uid: security/authorization/claims --- # Claims-Based Authorization - + When an identity is created it may be assigned one or more claims issued by a trusted party. A claim is name value pair that represents what the subject is, not what the subject can do. For example you may have a Drivers License, issued by a local driving license authority. Your driver's license has your date of birth on it. In this case the claim name would be `DateOfBirth`, the claim value would be your date of birth, for example `8th June 1970` and the issuer would be the driving license authority. Claims based authorization, at its simplest, checks the value of a claim and allows access to a resource based upon that value. For example if you want access to a night club the authorization process might be: diff --git a/aspnetcore/security/authorization/dependencyinjection.md b/aspnetcore/security/authorization/dependencyinjection.md index e71d5d61e5..c594b6c107 100644 --- a/aspnetcore/security/authorization/dependencyinjection.md +++ b/aspnetcore/security/authorization/dependencyinjection.md @@ -14,7 +14,7 @@ uid: security/authorization/dependencyinjection --- # Dependency Injection in requirement handlers - + [Authorization handlers must be registered](policies.md#security-authorization-policies-based-handler-registration) in the service collection during configuration (using [dependency injection](../../fundamentals/dependency-injection.md#fundamentals-dependency-injection)). diff --git a/aspnetcore/security/authorization/introduction.md b/aspnetcore/security/authorization/introduction.md index 177ff98123..2aec46e157 100644 --- a/aspnetcore/security/authorization/introduction.md +++ b/aspnetcore/security/authorization/introduction.md @@ -14,7 +14,7 @@ uid: security/authorization/introduction --- # Introduction - + Authorization refers to the process that determines what a user is able to do. For example, an administrative user is allowed to create a document library, add documents, edit documents, and delete them. A non-administrative user working with the library is only authorized to read the documents. diff --git a/aspnetcore/security/authorization/policies.md b/aspnetcore/security/authorization/policies.md index 386c129ab7..01369cd1b3 100644 --- a/aspnetcore/security/authorization/policies.md +++ b/aspnetcore/security/authorization/policies.md @@ -14,7 +14,7 @@ uid: security/authorization/policies --- # Custom Policy-Based Authorization - + Underneath the covers the [role authorization](roles.md) and [claims authorization](claims.md) make use of a requirement, a handler for the requirement and a pre-configured policy. These building blocks allow you to express authorization evaluations in code, allowing for a richer, reusable, and easily testable authorization structure. @@ -69,13 +69,13 @@ public class MinimumAgeRequirement : IAuthorizationRequirement A requirement doesn't need to have data or properties. - + ## Authorization Handlers An authorization handler is responsible for the evaluation of any properties of a requirement. The authorization handler must evaluate them against a provided `AuthorizationHandlerContext` to decide if authorization is allowed. A requirement can have [multiple handlers](policies.md#security-authorization-policies-based-multiple-handlers). Handlers must inherit `AuthorizationHandler` where T is the requirement it handles. - + The minimum age handler might look like this: @@ -111,7 +111,7 @@ public class MinimumAgeHandler : AuthorizationHandler In the code above we first look to see if the current user principal has a date of birth claim which has been issued by an Issuer we know and trust. If the claim is missing we can't authorize so we return. If we have a claim, we figure out how old the user is, and if they meet the minimum age passed in by the requirement then authorization has been successful. Once authorization is successful we call `context.Succeed()` passing in the requirement that has been successful as a parameter. - + Handlers must be registered in the services collection during configuration, for example; @@ -145,7 +145,7 @@ You can see in our [handler example](policies.md#security-authorization-handler- Regardless of what you call inside your handler all handlers for a requirement will be called when a policy requires the requirement. This allows requirements to have side effects, such as logging, which will always take place even if `context.Fail()` has been called in another handler. - + ## Why would I want multiple handlers for a requirement? diff --git a/aspnetcore/security/authorization/resourcebased.md b/aspnetcore/security/authorization/resourcebased.md index e54f2adde5..bd4adbd0a8 100644 --- a/aspnetcore/security/authorization/resourcebased.md +++ b/aspnetcore/security/authorization/resourcebased.md @@ -14,7 +14,7 @@ uid: security/authorization/resourcebased --- # Resource Based Authorization - + Often authorization depends upon the resource being accessed. For example, a document may have an author property. Only the document author would be allowed to update it, so the resource must be loaded from the document repository before an authorization evaluation can be made. This cannot be done with an Authorize attribute, as attribute evaluation takes place before data binding and before your own code to load a resource runs inside an action. Instead of declarative authorization, the attribute method, we must use imperative authorization, where a developer calls an authorize function within their own code. @@ -45,7 +45,7 @@ Task AuthorizeAsync(ClaimsPrincipal user, string policyName); ``` - + To call the service, load your resource within your action then call the `AuthorizeAsync` overload you require. For example: diff --git a/aspnetcore/security/authorization/roles.md b/aspnetcore/security/authorization/roles.md index 853c6424a7..b21c5acb97 100644 --- a/aspnetcore/security/authorization/roles.md +++ b/aspnetcore/security/authorization/roles.md @@ -14,7 +14,7 @@ uid: security/authorization/roles --- # Role based Authorization - + When an identity is created it may belong to one or more roles, for example Tracy may belong to the Administrator and User roles whilst Scott may only belong to the user role. How these roles are created and managed depends on the backing store of the authorization process. Roles are exposed to the developer through the [IsInRole](https://docs.microsoft.com/dotnet/api/system.security.principal.genericprincipal.isinrole) property on the [ClaimsPrincipal](https://docs.microsoft.com/dotnet/api/system.security.claims.claimsprincipal) class. @@ -88,7 +88,7 @@ public class ControlPanelController : Controller } ``` - + ## Policy based role checks diff --git a/aspnetcore/security/authorization/secure-data.md b/aspnetcore/security/authorization/secure-data.md index 48a276a729..f5776dc090 100644 --- a/aspnetcore/security/authorization/secure-data.md +++ b/aspnetcore/security/authorization/secure-data.md @@ -311,7 +311,7 @@ Test that the app seeded the database. The seed method does not run if there are [!code-csharp[Main](secure-data/samples/final/Authorization/ContactOperations.cs)] - + ### Additional resources diff --git a/aspnetcore/security/authorization/simple.md b/aspnetcore/security/authorization/simple.md index 1820ca5470..d36e1cb562 100644 --- a/aspnetcore/security/authorization/simple.md +++ b/aspnetcore/security/authorization/simple.md @@ -14,7 +14,7 @@ uid: security/authorization/simple --- # Simple Authorization - + Authorization in MVC is controlled through the `AuthorizeAttribute` attribute and its various parameters. At its simplest applying the `AuthorizeAttribute` attribute to a controller or action limits access to the controller or action to any authenticated user. diff --git a/aspnetcore/security/authorization/views.md b/aspnetcore/security/authorization/views.md index 2d4d557edb..eccbb82c7e 100644 --- a/aspnetcore/security/authorization/views.md +++ b/aspnetcore/security/authorization/views.md @@ -14,7 +14,7 @@ uid: security/authorization/views --- # View Based Authorization - + Often a developer will want to show, hide or otherwise modify a UI based on the current user identity. You can access the authorization service within MVC views via [dependency injection](../../fundamentals/dependency-injection.md#fundamentals-dependency-injection). To inject the authorization service into a Razor view use the `@inject` directive, for example `@inject IAuthorizationService AuthorizationService` (requires `@using Microsoft.AspNetCore.Authorization`). If you want the authorization service in every view then place the `@inject` directive into the `_ViewImports.cshtml` file in the `Views` directory. For more information on dependency injection into views see [Dependency injection into views](../../mvc/views/dependency-injection.md). diff --git a/aspnetcore/security/cors.md b/aspnetcore/security/cors.md index a7bf7c2d0f..d714e5f97f 100644 --- a/aspnetcore/security/cors.md +++ b/aspnetcore/security/cors.md @@ -214,7 +214,7 @@ The Access-Control-Max-Age header specifies how long the response to the preflig [!code-csharp[Main](cors/sample/CorsExample4/Startup.cs?range=89-94)] - + ## How CORS works diff --git a/aspnetcore/security/cross-site-scripting.md b/aspnetcore/security/cross-site-scripting.md index 89788f1be8..110ff577cd 100644 --- a/aspnetcore/security/cross-site-scripting.md +++ b/aspnetcore/security/cross-site-scripting.md @@ -14,7 +14,7 @@ uid: security/cross-site-scripting --- # Preventing Cross-Site Scripting - + Cross-Site Scripting (XSS) is a security vulnerability which enables an attacker to place client side scripts (usually JavaScript) into web pages. When other users load affected pages the attackers scripts will run, enabling the attacker to steal cookies and session tokens, change the contents of the web page through DOM manipulation or redirect the browser to another page. XSS vulnerabilities generally occur when an application takes user input and outputs it in a page without validating, encoding or escaping it. @@ -178,7 +178,7 @@ After encoding the encodedValue variable will contain `%22Quoted%20Value%20with% >[!WARNING] > Do not use untrusted input as part of a URL path. Always pass untrusted input as a query string value. - + ## Customizing the Encoders diff --git a/aspnetcore/security/data-protection/compatibility/replacing-machinekey.md b/aspnetcore/security/data-protection/compatibility/replacing-machinekey.md index ab4dec2f27..2d52f8a3c4 100644 --- a/aspnetcore/security/data-protection/compatibility/replacing-machinekey.md +++ b/aspnetcore/security/data-protection/compatibility/replacing-machinekey.md @@ -14,7 +14,7 @@ uid: security/data-protection/compatibility/replacing-machinekey --- # Replacing `` in ASP.NET - + The implementation of the `` element in ASP.NET [is replaceable](https://blogs.msdn.microsoft.com/webdev/2012/10/23/cryptographic-improvements-in-asp-net-4-5-pt-2/). This allows most calls to ASP.NET cryptographic routines to be routed through a replacement data protection mechanism, including the new data protection system. diff --git a/aspnetcore/security/data-protection/configuration/default-settings.md b/aspnetcore/security/data-protection/configuration/default-settings.md index 880cfd6656..39308dfde6 100644 --- a/aspnetcore/security/data-protection/configuration/default-settings.md +++ b/aspnetcore/security/data-protection/configuration/default-settings.md @@ -14,7 +14,7 @@ uid: security/data-protection/configuration/default-settings --- # Key management and lifetime - + ## Key Management diff --git a/aspnetcore/security/data-protection/configuration/machine-wide-policy.md b/aspnetcore/security/data-protection/configuration/machine-wide-policy.md index cea8a4df0f..9675dd5bc1 100644 --- a/aspnetcore/security/data-protection/configuration/machine-wide-policy.md +++ b/aspnetcore/security/data-protection/configuration/machine-wide-policy.md @@ -14,7 +14,7 @@ uid: security/data-protection/configuration/machine-wide-policy --- # Machine Wide Policy - + When running on Windows, the data protection system has limited support for setting default machine-wide policy for all applications which consume data protection. The general idea is that an administrator might wish to change some default setting (such as algorithms used or key lifetime) without needing to manually update every application on the machine. @@ -37,7 +37,7 @@ The supported values are: * KeyEscrowSinks [string] - specifies the types which will be used for key escrow. This value is a semicolon-delimited list of key escrow sinks, where each element in the list is the assembly qualified name of a type which implements IKeyEscrowSink. - + ### Encryption types diff --git a/aspnetcore/security/data-protection/configuration/overview.md b/aspnetcore/security/data-protection/configuration/overview.md index 0701bbfe0c..2d4092ac77 100644 --- a/aspnetcore/security/data-protection/configuration/overview.md +++ b/aspnetcore/security/data-protection/configuration/overview.md @@ -14,11 +14,11 @@ uid: security/data-protection/configuration/overview --- # Configuring data protection - + When the data protection system is initialized it applies some [default settings](default-settings.md#data-protection-default-settings) based on the operational environment. These settings are generally good for applications running on a single machine. There are some cases where a developer may want to change these (perhaps because their application is spread across multiple machines or for compliance reasons), and for these scenarios the data protection system offers a rich configuration API. - + There is an extension method AddDataProtection which returns an IDataProtectionBuilder which itself exposes extension methods that you can chain together to configure various data protection options. For instance, to store keys at a UNC share instead of %LOCALAPPDATA% (the default), configure the system as follows: @@ -33,7 +33,7 @@ public void ConfigureServices(IServiceCollection services) >[!WARNING] > If you change the key persistence location, the system will no longer automatically encrypt keys at rest since it doesn't know whether DPAPI is an appropriate encryption mechanism. - + You can configure the system to protect keys at rest by calling any of the ProtectKeysWith\* configuration APIs. Consider the example below, which stores keys at a UNC share and encrypts those keys at rest with a specific X.509 certificate. @@ -60,7 +60,7 @@ public void ConfigureServices(IServiceCollection services) By default the data protection system isolates applications from one another, even if they're sharing the same physical key repository. This prevents the applications from understanding each other's protected payloads. To share protected payloads between two different applications, configure the system passing in the same application name for both applications as in the below example: - + ```csharp public void ConfigureServices(IServiceCollection services) @@ -70,7 +70,7 @@ public void ConfigureServices(IServiceCollection services) } ``` - + Finally, you may have a scenario where you do not want an application to automatically roll keys as they approach expiration. One example of this might be applications set up in a primary / secondary relationship, where only the primary application is responsible for key management concerns, and all secondary applications simply have a read-only view of the key ring. The secondary applications can be configured to treat the key ring as read-only by configuring the system as below: @@ -82,7 +82,7 @@ public void ConfigureServices(IServiceCollection services) } ``` - + ## Per-application isolation @@ -100,7 +100,7 @@ This isolation mechanism assumes that the applications are not malicious. A mali If the data protection system is not provided by an ASP.NET Core host (e.g., if the developer instantiates it himself via the DataProtectionProvider concrete type), application isolation is disabled by default, and all applications backed by the same keying material can share payloads as long as they provide the appropriate purposes. To provide application isolation in this environment, call the SetApplicationName method on the configuration object, see the [code sample](#data-protection-code-sample-application-name) above. - + ## Changing algorithms @@ -139,7 +139,7 @@ The developer can manually specify an implementation if desired via a call to Us >[!TIP] > Changing algorithms does not affect existing keys in the key ring. It only affects newly-generated keys. - + ### Specifying custom managed algorithms @@ -188,7 +188,7 @@ Generally the \*Type properties must point to concrete, instantiable (via a publ > [!NOTE] > The SymmetricAlgorithm must have a key length of ≥ 128 bits and a block size of ≥ 64 bits, and it must support CBC-mode encryption with PKCS #7 padding. The KeyedHashAlgorithm must have a digest size of >= 128 bits, and it must support keys of length equal to the hash algorithm's digest length. The KeyedHashAlgorithm is not strictly required to be HMAC. - + ### Specifying custom Windows CNG algorithms diff --git a/aspnetcore/security/data-protection/consumer-apis/dangerous-unprotect.md b/aspnetcore/security/data-protection/consumer-apis/dangerous-unprotect.md index 7d6cd6edd2..50c0047363 100644 --- a/aspnetcore/security/data-protection/consumer-apis/dangerous-unprotect.md +++ b/aspnetcore/security/data-protection/consumer-apis/dangerous-unprotect.md @@ -14,7 +14,7 @@ uid: security/data-protection/consumer-apis/dangerous-unprotect --- # Unprotecting payloads whose keys have been revoked - + The ASP.NET Core data protection APIs are not primarily intended for indefinite persistence of confidential payloads. Other technologies like [Windows CNG DPAPI](https://msdn.microsoft.com/library/windows/desktop/hh706794%28v=vs.85%29.aspx) and [Azure Rights Management](https://docs.microsoft.com/rights-management/) are more suited to the scenario of indefinite storage, and they have correspondingly strong key management capabilities. That said, there is nothing prohibiting a developer from using the ASP.NET Core data protection APIs for long-term protection of confidential data. Keys are never removed from the key ring, so IDataProtector.Unprotect can always recover existing payloads as long as the keys are available and valid. diff --git a/aspnetcore/security/data-protection/consumer-apis/purpose-strings.md b/aspnetcore/security/data-protection/consumer-apis/purpose-strings.md index 0e7b486936..a5b4c1ab0f 100644 --- a/aspnetcore/security/data-protection/consumer-apis/purpose-strings.md +++ b/aspnetcore/security/data-protection/consumer-apis/purpose-strings.md @@ -14,7 +14,7 @@ uid: security/data-protection/consumer-apis/purpose-strings --- # Purpose Strings - + Components which consume IDataProtectionProvider must pass a unique *purposes* parameter to the CreateProtector method. The purposes *parameter* is inherent to the security of the data protection system, as it provides isolation between cryptographic consumers, even if the root cryptographic keys are the same. @@ -33,7 +33,7 @@ The purpose string doesn't have to be secret. It should simply be unique in the Since the purposes parameter to CreateProtector is a string array, the above could have been instead specified as [ "Contoso.Security.BearerToken", "v1" ]. This allows establishing a hierarchy of purposes and opens up the possibility of multi-tenancy scenarios with the data protection system. - + >[!WARNING] > Components should not allow untrusted user input to be the sole source of input for the purposes chain. diff --git a/aspnetcore/security/data-protection/extensibility/core-crypto.md b/aspnetcore/security/data-protection/extensibility/core-crypto.md index e4da35c8e5..d1f9c3de5a 100644 --- a/aspnetcore/security/data-protection/extensibility/core-crypto.md +++ b/aspnetcore/security/data-protection/extensibility/core-crypto.md @@ -13,12 +13,12 @@ uid: security/data-protection/extensibility/core-crypto --- # Core cryptography extensibility - + >[!WARNING] > Types that implement any of the following interfaces should be thread-safe for multiple callers. - + ## IAuthenticatedEncryptor @@ -35,8 +35,8 @@ The Encrypt method returns a blob that includes the enciphered plaintext and an > [!NOTE] > The IAuthenticatedEncryptor instance itself doesn't actually need to contain the key material. For example, the implementation could delegate to an HSM for all operations. - - + + ## How to create an IAuthenticatedEncryptor @@ -97,7 +97,7 @@ byte[] roundTripped = encryptor2.Decrypt(new ArraySegment(ciphertext), aad --- - + ## IAuthenticatedEncryptorDescriptor (ASP.NET Core 2.x only) @@ -115,7 +115,7 @@ The **IAuthenticatedEncryptorDescriptor** interface represents a type that knows The primary difference between IAuthenticatedEncryptor and IAuthenticatedEncryptorDescriptor is that the descriptor knows how to create the encryptor and supply it with valid arguments. Consider an IAuthenticatedEncryptor whose implementation relies on SymmetricAlgorithm and KeyedHashAlgorithm. The encryptor's job is to consume these types, but it doesn't necessarily know where these types came from, so it can't really write out a proper description of how to recreate itself if the application restarts. The descriptor acts as a higher level on top of this. Since the descriptor knows how to create the encryptor instance (e.g., it knows how to create the required algorithms), it can serialize that knowledge in XML form so that the encryptor instance can be recreated after an application reset. - + The descriptor can be serialized via its ExportToXml routine. This routine returns an XmlSerializedDescriptorInfo which contains two properties: the XElement representation of the descriptor and the Type which represents an [IAuthenticatedEncryptorDescriptorDeserializer](xref:security/data-protection/extensibility/core-crypto#data-protection-extensibility-core-crypto-iauthenticatedencryptordescriptordeserializer) which can be used to resurrect this descriptor given the corresponding XElement. @@ -126,7 +126,7 @@ The serialized descriptor may contain sensitive information such as cryptographi There can also be cases where the serialized descriptor doesn't contain sensitive information. Consider again the case of a cryptographic key stored in an HSM. The descriptor cannot write out the key material when serializing itself since the HSM will not expose the material in plaintext form. Instead, the descriptor might write out the key-wrapped version of the key (if the HSM allows export in this fashion) or the HSM's own unique identifier for the key. - + ## IAuthenticatedEncryptorDescriptorDeserializer diff --git a/aspnetcore/security/data-protection/extensibility/key-management.md b/aspnetcore/security/data-protection/extensibility/key-management.md index 27dbae9c14..3329c22358 100644 --- a/aspnetcore/security/data-protection/extensibility/key-management.md +++ b/aspnetcore/security/data-protection/extensibility/key-management.md @@ -14,7 +14,7 @@ uid: security/data-protection/extensibility/key-management --- # Key management extensibility - + >[!TIP] > Read the [key management](../implementation/key-management.md#data-protection-implementation-key-management) section before reading this section, as it explains some of the fundamental concepts behind these APIs. @@ -58,7 +58,7 @@ The IKeyManager interface represents an object responsible for general key stora >[!WARNING] > Writing an IKeyManager is a very advanced task, and the majority of developers should not attempt it. Instead, most developers should take advantage of the facilities offered by the [XmlKeyManager](xref:security/data-protection/extensibility/key-management#data-protection-extensibility-key-management-xmlkeymanager) class. - + ## XmlKeyManager @@ -134,7 +134,7 @@ Implementations of IXmlRepository don't need to parse the XML passing through th There are two built-in concrete types which implement IXmlRepository: FileSystemXmlRepository and RegistryXmlRepository. See the [key storage providers document](../implementation/key-storage-providers.md#data-protection-implementation-key-storage-providers) for more information. Registering a custom IXmlRepository would be the appropriate manner to use a different backing store, e.g., Azure Blob Storage. To change the default repository application-wide, register a custom singleton IXmlRepository in the service provider. - + ## IXmlEncryptor diff --git a/aspnetcore/security/data-protection/extensibility/misc-apis.md b/aspnetcore/security/data-protection/extensibility/misc-apis.md index 4cd2e5b8ea..fd64020bf9 100644 --- a/aspnetcore/security/data-protection/extensibility/misc-apis.md +++ b/aspnetcore/security/data-protection/extensibility/misc-apis.md @@ -14,7 +14,7 @@ uid: security/data-protection/extensibility/misc-apis --- # Miscellaneous APIs - + >[!WARNING] > Types that implement any of the following interfaces should be thread-safe for multiple callers. diff --git a/aspnetcore/security/data-protection/implementation/authenticated-encryption-details.md b/aspnetcore/security/data-protection/implementation/authenticated-encryption-details.md index 46eda9f7d3..ceff18b9c7 100644 --- a/aspnetcore/security/data-protection/implementation/authenticated-encryption-details.md +++ b/aspnetcore/security/data-protection/implementation/authenticated-encryption-details.md @@ -14,7 +14,7 @@ uid: security/data-protection/implementation/authenticated-encryption-details --- # Authenticated encryption details. - + Calls to IDataProtector.Protect are authenticated encryption operations. The Protect method offers both confidentiality and authenticity, and it is tied to the purpose chain that was used to derive this particular IDataProtector instance from its root IDataProtectionProvider. diff --git a/aspnetcore/security/data-protection/implementation/context-headers.md b/aspnetcore/security/data-protection/implementation/context-headers.md index 0562ae6325..a282547b82 100644 --- a/aspnetcore/security/data-protection/implementation/context-headers.md +++ b/aspnetcore/security/data-protection/implementation/context-headers.md @@ -14,7 +14,7 @@ uid: security/data-protection/implementation/context-headers --- # Context headers - + ## Background and theory @@ -28,7 +28,7 @@ We use this concept of strong PRPs and PRFs to build up a context header. This c ## CBC-mode encryption + HMAC authentication - + The context header consists of the following components: diff --git a/aspnetcore/security/data-protection/implementation/key-encryption-at-rest.md b/aspnetcore/security/data-protection/implementation/key-encryption-at-rest.md index 8906cf05ed..4b7a4ba0bd 100644 --- a/aspnetcore/security/data-protection/implementation/key-encryption-at-rest.md +++ b/aspnetcore/security/data-protection/implementation/key-encryption-at-rest.md @@ -14,14 +14,14 @@ uid: security/data-protection/implementation/key-encryption-at-rest --- # Key Encryption At Rest - + By default the data protection system [employs a heuristic](../configuration/default-settings.md#data-protection-default-settings) to determine how cryptographic key material should be encrypted at rest. The developer can override the heuristic and manually specify how keys should be encrypted at rest. > [!NOTE] > If you specify an explicit key encryption at rest mechanism, the data protection system will deregister the default key storage mechanism that the heuristic provided. You must [specify an explicit key storage mechanism](key-storage-providers.md#data-protection-implementation-key-storage-providers), otherwise the data protection system will fail to start. - + The data protection system ships with three in-box key encryption mechanisms. @@ -59,7 +59,7 @@ sc.AddDataProtection() Due to .NET Framework limitations only certificates with CAPI private keys are supported. See [Certificate-based encryption with Windows DPAPI-NG](#data-protection-implementation-key-encryption-at-rest-dpapi-ng) below for possible workarounds to these limitations. - + ## Windows DPAPI-NG diff --git a/aspnetcore/security/data-protection/implementation/key-management.md b/aspnetcore/security/data-protection/implementation/key-management.md index 3ec580da2d..1ad957a0d9 100644 --- a/aspnetcore/security/data-protection/implementation/key-management.md +++ b/aspnetcore/security/data-protection/implementation/key-management.md @@ -14,7 +14,7 @@ uid: security/data-protection/implementation/key-management --- # Key Management - + The data protection system automatically manages the lifetime of master keys used to protect and unprotect payloads. Each key can exist in one of four stages. @@ -41,7 +41,7 @@ The reason the data protection system generates a new key immediately rather tha There is an exception. If the application developer has [disabled automatic key generation](../configuration/overview.md#data-protection-configuring-disable-automatic-key-generation), then the data protection system must choose something as the default key. In this fallback scenario, the system will choose the non-revoked key with the most recent activation date, with preference given to keys that have had time to propagate to other machines in the cluster. The fallback system may end up choosing an expired default key as a result. The fallback system will never choose a revoked key as the default key, and if the key ring is empty or every key has been revoked then the system will produce an error upon initialization. - + ## Key expiration and rolling diff --git a/aspnetcore/security/data-protection/implementation/key-storage-ephemeral.md b/aspnetcore/security/data-protection/implementation/key-storage-ephemeral.md index 30a5c94bcb..08a1127561 100644 --- a/aspnetcore/security/data-protection/implementation/key-storage-ephemeral.md +++ b/aspnetcore/security/data-protection/implementation/key-storage-ephemeral.md @@ -14,7 +14,7 @@ uid: security/data-protection/implementation/key-storage-ephemeral --- # Ephemeral data protection providers - + There are scenarios where an application needs a throwaway IDataProtectionProvider. For example, the developer might just be experimenting in a one-off console application, or the application itself is transient (it's scripted or a unit test project). To support these scenarios the package Microsoft.AspNetCore.DataProtection includes a type EphemeralDataProtectionProvider. This type provides a basic implementation of IDataProtectionProvider whose key repository is held solely in-memory and isn't written out to any backing store. diff --git a/aspnetcore/security/data-protection/implementation/key-storage-format.md b/aspnetcore/security/data-protection/implementation/key-storage-format.md index 73fb338c97..c4adad09a4 100644 --- a/aspnetcore/security/data-protection/implementation/key-storage-format.md +++ b/aspnetcore/security/data-protection/implementation/key-storage-format.md @@ -14,7 +14,7 @@ uid: security/data-protection/implementation/key-storage-format --- # Key Storage Format - + Objects are stored at rest in XML representation. The default directory for key storage is %LOCALAPPDATA%\ASP.NET\DataProtection-Keys\. diff --git a/aspnetcore/security/data-protection/implementation/key-storage-providers.md b/aspnetcore/security/data-protection/implementation/key-storage-providers.md index 19f6adcecc..c46cb20a35 100644 --- a/aspnetcore/security/data-protection/implementation/key-storage-providers.md +++ b/aspnetcore/security/data-protection/implementation/key-storage-providers.md @@ -14,7 +14,7 @@ uid: security/data-protection/implementation/key-storage-providers --- # Key storage providers - + By default the data protection system [employs a heuristic](../configuration/default-settings.md#data-protection-default-settings) to determine where cryptographic key material should be persisted. The developer can override the heuristic and manually specify the location. diff --git a/aspnetcore/security/data-protection/implementation/subkeyderivation.md b/aspnetcore/security/data-protection/implementation/subkeyderivation.md index 96a83e1c87..04d1ed9e0a 100644 --- a/aspnetcore/security/data-protection/implementation/subkeyderivation.md +++ b/aspnetcore/security/data-protection/implementation/subkeyderivation.md @@ -14,14 +14,14 @@ uid: security/data-protection/implementation/subkeyderivation --- # Subkey Derivation and Authenticated Encryption - + Most keys in the key ring will contain some form of entropy and will have algorithmic information stating "CBC-mode encryption + HMAC validation" or "GCM encryption + validation". In these cases, we refer to the embedded entropy as the master keying material (or KM) for this key, and we perform a key derivation function to derive the keys that will be used for the actual cryptographic operations. > [!NOTE] > Keys are abstract, and a custom implementation might not behave as below. If the key provides its own implementation of IAuthenticatedEncryptor rather than using one of our built-in factories, the mechanism described in this section no longer applies. - + ## Additional authenticated data and subkey derivation diff --git a/aspnetcore/security/data-protection/using-data-protection.md b/aspnetcore/security/data-protection/using-data-protection.md index 29cbdecb74..0cdbc730f4 100644 --- a/aspnetcore/security/data-protection/using-data-protection.md +++ b/aspnetcore/security/data-protection/using-data-protection.md @@ -14,7 +14,7 @@ uid: security/data-protection/using-data-protection --- # Getting Started with the Data Protection APIs - + At its simplest protecting data consists of the following steps: diff --git a/aspnetcore/tutorials/web-api-help-pages-using-swagger.md b/aspnetcore/tutorials/web-api-help-pages-using-swagger.md index 2eefacec4b..909153c218 100644 --- a/aspnetcore/tutorials/web-api-help-pages-using-swagger.md +++ b/aspnetcore/tutorials/web-api-help-pages-using-swagger.md @@ -14,7 +14,7 @@ uid: tutorials/web-api-help-pages-using-swagger --- # ASP.NET Core Web API Help Pages using Swagger - + By [Shayne Boyer](https://twitter.com/spboyer) and [Scott Addie](https://twitter.com/Scott_Addie) From 8f4d4fad1ca27adf9e396f5c205c9875a3963664 Mon Sep 17 00:00:00 2001 From: Richard D Date: Fri, 13 Oct 2017 22:06:17 +0100 Subject: [PATCH 34/34] Included closing brace in code sample (#4569) * Used an explicit code sample rather than a snippet. The snippet is from a larger class, this modification allows it to be copied and build without modification. * Included closing brace in link to example as suggested --- aspnetcore/fundamentals/app-state.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aspnetcore/fundamentals/app-state.md b/aspnetcore/fundamentals/app-state.md index 0a0c7071e3..c34207c670 100644 --- a/aspnetcore/fundamentals/app-state.md +++ b/aspnetcore/fundamentals/app-state.md @@ -164,7 +164,7 @@ Session is accessed through the `Session` property on `HttpContext`. This proper The following example shows setting and getting an int and a string: -[!code-csharp[Main](app-state/sample/src/WebAppSession/Controllers/HomeController.cs?name=snippet1)] +[!code-csharp[Main](app-state/sample/src/WebAppSession/Controllers/HomeController.cs?range=8-27,49)] If you add the following extension methods, you can set and get serializable objects to Session: