Skip to content

Commit 9bb5b6c

Browse files
authored
Create Blazor Server security node (#18028)
1 parent 6f8cbad commit 9bb5b6c

11 files changed

Lines changed: 266 additions & 220 deletions

File tree

.openpublishing.redirection.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,11 @@
919919
"source_path": "aspnetcore/blazor/javascript-interop.md",
920920
"redirect_url": "/aspnet/core/blazor/call-javascript-from-dotnet",
921921
"redirect_document_id": false
922+
},
923+
{
924+
"source_path": "aspnetcore/security/blazor/server.md",
925+
"redirect_url": "/aspnet/core/security/blazor/server",
926+
"redirect_document_id": false
922927
}
923928
]
924929
}

aspnetcore/blazor/call-javascript-from-dotnet.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ JS interop may fail due to networking errors and should be treated as unreliable
450450
TimeSpan.FromSeconds({SECONDS}), new[] { "Arg1" });
451451
```
452452

453-
For more information on resource exhaustion, see <xref:security/blazor/server>.
453+
For more information on resource exhaustion, see <xref:security/blazor/server/threat-mitigation>.
454454

455455
[!INCLUDE[Share interop code in a class library](~/includes/blazor-share-interop-code.md)]
456456

aspnetcore/blazor/components.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -958,4 +958,4 @@ However, inline SVG markup isn't supported in all scenarios. If you place an `<s
958958

959959
## Additional resources
960960

961-
* <xref:security/blazor/server> &ndash; Includes guidance on building Blazor Server apps that must contend with resource exhaustion.
961+
* <xref:security/blazor/server/threat-mitigation> &ndash; Includes guidance on building Blazor Server apps that must contend with resource exhaustion.

aspnetcore/blazor/hosting-models.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ A UI update in Blazor is triggered by:
107107

108108
The graph is rerendered, and a UI *diff* (difference) is calculated. This diff is the smallest set of DOM edits required to update the UI on the client. The diff is sent to the client in a binary format and applied by the browser.
109109

110-
A component is disposed after the user navigates away from it on the client. While a user is interacting with a component, the component's state (services, resources) must be held in the server's memory. Because the state of many components might be maintained by the server concurrently, memory exhaustion is a concern that must be addressed. For guidance on how to author a Blazor Server app to ensure the best use of server memory, see <xref:security/blazor/server>.
110+
A component is disposed after the user navigates away from it on the client. While a user is interacting with a component, the component's state (services, resources) must be held in the server's memory. Because the state of many components might be maintained by the server concurrently, memory exhaustion is a concern that must be addressed. For guidance on how to author a Blazor Server app to ensure the best use of server memory, see <xref:security/blazor/server/threat-mitigation>.
111111

112112
### Circuits
113113

@@ -125,12 +125,12 @@ UI latency is the time it takes from an initiated action to the time the UI is u
125125

126126
For a line of business app that's limited to a private corporate network, the effect on user perceptions of latency due to network latency are usually imperceptible. For an app deployed over the Internet, latency may become noticeable to users, particularly if users are widely distributed geographically.
127127

128-
Memory usage can also contribute to app latency. Increased memory usage results in frequent garbage collection or paging memory to disk, both of which degrade app performance and consequently increase UI latency. For more information, see <xref:security/blazor/server>.
128+
Memory usage can also contribute to app latency. Increased memory usage results in frequent garbage collection or paging memory to disk, both of which degrade app performance and consequently increase UI latency.
129129

130130
Blazor Server apps should be optimized to minimize UI latency by reducing network latency and memory usage. For an approach to measuring network latency, see <xref:host-and-deploy/blazor/server#measure-network-latency>. For more information on SignalR and Blazor, see:
131131

132132
* <xref:host-and-deploy/blazor/server>
133-
* <xref:security/blazor/server>
133+
* <xref:security/blazor/server/threat-mitigation>
134134

135135
### Connection to the server
136136

aspnetcore/host-and-deploy/blazor/server.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ A web server capable of hosting an ASP.NET Core app is required. Visual Studio i
2828
Plan a deployment to make the best use of the available infrastructure for a Blazor Server app. See the following resources to address Blazor Server app scalability:
2929

3030
* [Fundamentals of Blazor Server apps](xref:blazor/hosting-models#blazor-server)
31-
* <xref:security/blazor/server>
31+
* <xref:security/blazor/server/threat-mitigation>
3232

3333
### Deployment server
3434

@@ -37,7 +37,7 @@ When considering the scalability of a single server (scale up), the memory avail
3737
* Number of active circuits that a server can support.
3838
* UI latency on the client.
3939

40-
For guidance on building secure and scalable Blazor server apps, see <xref:security/blazor/server>.
40+
For guidance on building secure and scalable Blazor server apps, see <xref:security/blazor/server/threat-mitigation>.
4141

4242
Each circuit uses approximately 250 KB of memory for a minimal *Hello World*-style app. The size of a circuit depends on the app's code and the state maintenance requirements associated with each component. We recommend that you measure resource demands during development for your app and infrastructure, but the following baseline can be a starting point in planning your deployment target: If you expect your app to support 5,000 concurrent users, consider budgeting at least 1.3 GB of server memory to the app (or ~273 KB per user).
4343

aspnetcore/security/blazor/index.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ For more information on creating apps and configuration, see <xref:security/blaz
5353

5454
Blazor Server apps operate over a real-time connection that's created using SignalR. [Authentication in SignalR-based apps](xref:signalr/authn-and-authz) is handled when the connection is established. Authentication can be based on a cookie or some other bearer token.
5555

56-
For more information on creating apps and configuration, see <xref:security/blazor/server>.
56+
For more information on creating apps and configuration, see <xref:security/blazor/server/index>.
5757

5858
## AuthenticationStateProvider service
5959

@@ -491,6 +491,5 @@ The `CascadingAuthenticationState` supplies the `Task<AuthenticationState>` casc
491491
## Additional resources
492492

493493
* <xref:security/index>
494-
* <xref:security/blazor/server>
495494
* <xref:security/authentication/windowsauth>
496495
* [Awesome Blazor: Authentication](https://github.com/AdrienTorris/awesome-blazor#authentication) community sample links
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
---
2+
title: ASP.NET Core Blazor Server additional security scenarios
3+
author: guardrex
4+
description: Learn how to configure Blazor Server for additional security scenarios.
5+
monikerRange: '>= aspnetcore-3.1'
6+
ms.author: riande
7+
ms.custom: mvc
8+
ms.date: 04/27/2020
9+
no-loc: [Blazor, SignalR]
10+
uid: security/blazor/server/additional-scenarios
11+
---
12+
# ASP.NET Core Blazor Server additional security scenarios
13+
14+
By [Javier Calvarro Nelson](https://github.com/javiercn)
15+
16+
## Pass tokens to a Blazor Server app
17+
18+
Tokens available outside of the Razor components in a Blazor Server app can be passed to components with the approach described in this section. For sample code, including a complete `Startup.ConfigureServices` example, see the [Passing tokens to a server-side Blazor application](https://github.com/javiercn/blazor-server-aad-sample).
19+
20+
Authenticate the Blazor Server app as you would with a regular Razor Pages or MVC app. Provision and save the tokens to the authentication cookie. For example:
21+
22+
```csharp
23+
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
24+
25+
...
26+
27+
services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>
28+
{
29+
options.ResponseType = "code";
30+
options.SaveTokens = true;
31+
32+
options.Scope.Add("offline_access");
33+
options.Scope.Add("{SCOPE}");
34+
options.Resource = "{RESOURCE}";
35+
});
36+
```
37+
38+
Define a class to pass in the initial app state with the access and refresh tokens:
39+
40+
```csharp
41+
public class InitialApplicationState
42+
{
43+
public string AccessToken { get; set; }
44+
public string RefreshToken { get; set; }
45+
}
46+
```
47+
48+
Define a **scoped** token provider service that can be used within the Blazor app to resolve the tokens from [dependency injection (DI)](xref:blazor/dependency-injection):
49+
50+
```csharp
51+
public class TokenProvider
52+
{
53+
public string AccessToken { get; set; }
54+
public string RefreshToken { get; set; }
55+
}
56+
```
57+
58+
In `Startup.ConfigureServices`, add services for:
59+
60+
* `IHttpClientFactory`
61+
* `TokenProvider`
62+
63+
```csharp
64+
services.AddHttpClient();
65+
services.AddScoped<TokenProvider>();
66+
```
67+
68+
In the *_Host.cshtml* file, create and instance of `InitialApplicationState` and pass it as a parameter to the app:
69+
70+
```cshtml
71+
@using Microsoft.AspNetCore.Authentication
72+
73+
...
74+
75+
@{
76+
var tokens = new InitialApplicationState
77+
{
78+
AccessToken = await HttpContext.GetTokenAsync("access_token"),
79+
RefreshToken = await HttpContext.GetTokenAsync("refresh_token")
80+
};
81+
}
82+
83+
<app>
84+
<component type="typeof(App)" param-InitialState="tokens"
85+
render-mode="ServerPrerendered" />
86+
</app>
87+
```
88+
89+
In the `App` component (*App.razor*), resolve the service and initialize it with the data from the parameter:
90+
91+
```razor
92+
@inject TokenProvider TokenProvider
93+
94+
...
95+
96+
@code {
97+
[Parameter]
98+
public InitialApplicationState InitialState { get; set; }
99+
100+
protected override Task OnInitializedAsync()
101+
{
102+
TokenProvider.AccessToken = InitialState.AccessToken;
103+
TokenProvider.RefreshToken = InitialState.RefreshToken;
104+
105+
return base.OnInitializedAsync();
106+
}
107+
}
108+
```
109+
110+
In the service that makes a secure API request, inject the token provider and retrieve the token to call the API:
111+
112+
```csharp
113+
public class WeatherForecastService
114+
{
115+
private readonly TokenProvider _store;
116+
117+
public WeatherForecastService(IHttpClientFactory clientFactory,
118+
TokenProvider tokenProvider)
119+
{
120+
Client = clientFactory.CreateClient();
121+
_store = tokenProvider;
122+
}
123+
124+
public HttpClient Client { get; }
125+
126+
public async Task<WeatherForecast[]> GetForecastAsync(DateTime startDate)
127+
{
128+
var token = _store.AccessToken;
129+
var request = new HttpRequestMessage(HttpMethod.Get,
130+
"https://localhost:5003/WeatherForecast");
131+
request.Headers.Add("Authorization", $"Bearer {token}");
132+
var response = await Client.SendAsync(request);
133+
response.EnsureSuccessStatusCode();
134+
135+
return await response.Content.ReadAsAsync<WeatherForecast[]>();
136+
}
137+
}
138+
```
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
---
2+
title: Secure ASP.NET Core Blazor Server apps
3+
author: guardrex
4+
description: Learn how to secure Blazor Server apps as ASP.NET Core applications.
5+
monikerRange: '>= aspnetcore-3.1'
6+
ms.author: riande
7+
ms.custom: mvc
8+
ms.date: 04/27/2020
9+
no-loc: [Blazor, SignalR]
10+
uid: security/blazor/server/index
11+
---
12+
# Secure ASP.NET Core Blazor Server apps
13+
14+
By [Luke Latham](https://github.com/guardrex)
15+
16+
## Blazor Server project template
17+
18+
The Blazor Server project template can be configured for authentication when the project is created.
19+
20+
# [Visual Studio](#tab/visual-studio)
21+
22+
Follow the Visual Studio guidance in the <xref:blazor/get-started> article to create a new Blazor Server project with an authentication mechanism.
23+
24+
After choosing the **Blazor Server App** template in the **Create a new ASP.NET Core Web Application** dialog, select **Change** under **Authentication**.
25+
26+
A dialog opens to offer the same set of authentication mechanisms available for other ASP.NET Core projects:
27+
28+
* **No Authentication**
29+
* **Individual User Accounts** &ndash; User accounts can be stored:
30+
* Within the app using ASP.NET Core's [Identity](xref:security/authentication/identity) system.
31+
* With [Azure AD B2C](xref:security/authentication/azure-ad-b2c).
32+
* **Work or School Accounts**
33+
* **Windows Authentication**
34+
35+
# [Visual Studio Code](#tab/visual-studio-code)
36+
37+
Follow the Visual Studio Code guidance in the <xref:blazor/get-started> article to create a new Blazor Server project with an authentication mechanism:
38+
39+
```dotnetcli
40+
dotnet new blazorserver -o {APP NAME} -au {AUTHENTICATION}
41+
```
42+
43+
Permissible authentication values (`{AUTHENTICATION}`) are shown in the following table.
44+
45+
| Authentication mechanism | Description |
46+
| ------------------------ | ----------- |
47+
| `None` (default) | No authentication |
48+
| `Individual` | Users stored in the app with ASP.NET Core Identity |
49+
| `IndividualB2C` | Users stored in [Azure AD B2C](xref:security/authentication/azure-ad-b2c) |
50+
| `SingleOrg` | Organizational authentication for a single tenant |
51+
| `MultiOrg` | Organizational authentication for multiple tenants |
52+
| `Windows` | Windows Authentication |
53+
54+
Using the `-o|--output` option, the command uses the value provided for the `{APP NAME}` placeholder to:
55+
56+
* Create a folder for the project.
57+
* Name the project.
58+
59+
For more information, see the [dotnet new](/dotnet/core/tools/dotnet-new) command in the .NET Core Guide.
60+
61+
# [Visual Studio for Mac](#tab/visual-studio-mac)
62+
63+
1. Follow the Visual Studio for Mac guidance in the <xref:blazor/get-started> article.
64+
65+
1. On the **Configure your new Blazor Server App** step, select **Individual Authentication (in-app)** from the **Authentication** drop down.
66+
67+
1. The app is created for individual users stored in the app with ASP.NET Core Identity.
68+
69+
# [.NET Core CLI](#tab/netcore-cli/)
70+
71+
Follow the .NET Core CLI guidance in the <xref:blazor/get-started> article to create a new Blazor Server project with an authentication mechanism:
72+
73+
```dotnetcli
74+
dotnet new blazorserver -o {APP NAME} -au {AUTHENTICATION}
75+
```
76+
77+
Permissible authentication values (`{AUTHENTICATION}`) are shown in the following table.
78+
79+
| Authentication mechanism | Description |
80+
| ------------------------ | ----------- |
81+
| `None` (default) | No authentication |
82+
| `Individual` | Users stored in the app with ASP.NET Core Identity |
83+
| `IndividualB2C` | Users stored in [Azure AD B2C](xref:security/authentication/azure-ad-b2c) |
84+
| `SingleOrg` | Organizational authentication for a single tenant |
85+
| `MultiOrg` | Organizational authentication for multiple tenants |
86+
| `Windows` | Windows Authentication |
87+
88+
Using the `-o|--output` option, the command uses the value provided for the `{APP NAME}` placeholder to:
89+
90+
* Create a folder for the project.
91+
* Name the project.
92+
93+
For more information, see the [dotnet new](/dotnet/core/tools/dotnet-new) command in the .NET Core Guide.
94+
95+
---

0 commit comments

Comments
 (0)