You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
# Account confirmation and password recovery in ASP.NET Core Blazor
@@ -22,7 +22,7 @@ The app's namespace used by the example in this article is `BlazorSample`. Updat
22
22
23
23
In this article, [Mailchimp's Transactional API](https://mailchimp.com/developer/transactional/api/) is used via [Mandrill.net](https://www.nuget.org/packages/Mandrill.net) to send email. We recommend using an email service to send email rather than SMTP. SMTP is difficult to configure and secure properly. Whichever email service you use, access their guidance for .NET apps, create an account, configure an API key for their service, and install any NuGet packages required.
24
24
25
-
Create a class to fetch the secure email API key. The example in this article uses a class named `AuthMessageSenderOptions` with a`EmailAuthKey` property to hold the key.
25
+
Create a class to hold the secret email provider API key. The example in this article uses a class named `AuthMessageSenderOptions` with an`EmailAuthKey` property to hold the key.
26
26
27
27
`AuthMessageSenderOptions.cs`:
28
28
@@ -49,7 +49,7 @@ If the project has already been initialized for the [Secret Manager tool](xref:s
49
49
dotnet user-secrets init
50
50
```
51
51
52
-
Set the key with the Secret Manager tool. In the following example, the key name is `EmailAuthKey`, and the key is represented by the `{KEY}` placeholder. In a command shell, navigate to the app's root folder and execute the following command with the API key:
52
+
Set the API key with the Secret Manager tool. In the following example, the key name is `EmailAuthKey` to match `AuthMessageSenderOptions.EmailAuthKey`, and the key is represented by the `{KEY}` placeholder. Execute the following command with the API key:
53
53
54
54
```dotnetcli
55
55
dotnet user-secrets set "EmailAuthKey" "{KEY}"
@@ -67,7 +67,7 @@ The following example is based on Mailchimp's Transactional API using [Mandrill.
67
67
68
68
Add the [Mandrill.net](https://www.nuget.org/packages/Mandrill.net) NuGet package to the project.
69
69
70
-
Add the following `EmailSender` class to implement <xref:Microsoft.AspNetCore.Identity.IEmailSender%601>. In the following example, `ApplicationUser` is a<xref:Microsoft.AspNetCore.Identity.IdentityUser>. The message HTML markup can be further customized. As long as the `message` passed to `MandrillMessage` starts with the `<` character, the Mandrill.net API assumes that the message body is composed in HTML.
70
+
Add the following `EmailSender` class to implement <xref:Microsoft.AspNetCore.Identity.IEmailSender%601>. In the following example, `ApplicationUser` is an<xref:Microsoft.AspNetCore.Identity.IdentityUser>. The message HTML markup can be further customized. As long as the `message` passed to `MandrillMessage` starts with the `<` character, the Mandrill.net API assumes that the message body is composed in HTML.
71
71
72
72
`Components/Account/EmailSender.cs`:
73
73
@@ -126,7 +126,7 @@ public class EmailSender(IOptions<AuthMessageSenderOptions> optionsAccessor,
126
126
```
127
127
128
128
> [!NOTE]
129
-
> Body content for messages might require special encoding for the email service provider. If links in the message body can't be followed, consult the service provider's documentation.
129
+
> Body content for messages might require special encoding for the email service provider. If links in the message body can't be followed in the email message, consult the service provider's documentation to troubleshoot the problem.
130
130
131
131
## Configure app to support email
132
132
@@ -167,6 +167,13 @@ Also in the `RegisterConfirmation` component, remove the Razor markup and code f
167
167
}
168
168
```
169
169
170
+
## Enable account confirmation after a site has users
171
+
172
+
Enabling account confirmation on a site with users locks out all the existing users. Existing users are locked out because their accounts aren't confirmed. To work around existing user lockout, use one of the following approaches:
173
+
174
+
* Update the database to mark all existing users as confirmed.
175
+
* Confirm existing users. For example, batch-send emails with confirmation links.
176
+
170
177
## Email and activity timeout
171
178
172
179
The default inactivity timeout is 14 days. The following code sets the inactivity timeout to five days with sliding expiration:
@@ -197,7 +204,7 @@ The default token lifespan of the [Identity user tokens](https://github.com/dotn
To change the email token lifespan, add a custom <xref:Microsoft.AspNetCore.Identity.DataProtectorTokenProvider%601> and <xref:Microsoft.AspNetCore.Identity.DataProtectionTokenProviderOptions>:
207
+
To change the email token lifespan, add a custom <xref:Microsoft.AspNetCore.Identity.DataProtectorTokenProvider%601> and <xref:Microsoft.AspNetCore.Identity.DataProtectionTokenProviderOptions>.
## Enable account confirmation after a site has users
277
-
278
-
Enabling account confirmation on a site with users locks out all the existing users. Existing users are locked out because their accounts aren't confirmed. To work around existing user lockout, use one of the following approaches:
279
-
280
-
* Update the database to mark all existing users as confirmed.
281
-
* Confirm existing users. For example, batch-send emails with confirmation links.
Copy file name to clipboardExpand all lines: aspnetcore/blazor/security/webassembly/standalone-with-identity/account-confirmation-and-password-recovery.md
+41-32Lines changed: 41 additions & 32 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,7 @@ author: guardrex
4
4
description: Learn how to configure an ASP.NET Core Blazor WebAssembly app with ASP.NET Core Identity with email confirmation and password recovery.
# Account confirmation and password recovery in ASP.NET Core Blazor WebAssembly with ASP.NET Core Identity
@@ -18,8 +18,8 @@ This article explains how to configure an ASP.NET Core Blazor WebAssembly app wi
18
18
19
19
The namespaces used by the examples in this article are:
20
20
21
-
*`Backend` for the backend server web API project.
22
-
*`BlazorWasmAuth` for the front-end standalone Blazor WebAssembly app.
21
+
*`Backend` for the backend server web API project ("server project" in this article).
22
+
*`BlazorWasmAuth` for the front-end client standalone Blazor WebAssembly app ("client project" in this article).
23
23
24
24
These namespaces correspond to the projects in the `BlazorWebAssemblyStandaloneWithIdentity` sample solution in the [`dotnet/blazor-samples` GitHub repository](https://github.com/dotnet/blazor-samples). For more information, see <xref:blazor/security/webassembly/standalone-with-identity/index#sample-apps>.
25
25
@@ -29,7 +29,7 @@ If you aren't using the `BlazorWebAssemblyStandaloneWithIdentity` sample solutio
29
29
30
30
In this article, [Mailchimp's Transactional API](https://mailchimp.com/developer/transactional/api/) is used via [Mandrill.net](https://www.nuget.org/packages/Mandrill.net) to send email. We recommend using an email service to send email rather than SMTP. SMTP is difficult to configure and secure properly. Whichever email service you use, access their guidance for .NET apps, create an account, configure an API key for their service, and install any NuGet packages required.
31
31
32
-
In the backend server project, create a class to fetch the secure email API key. The example in this article uses a class named `AuthMessageSenderOptions` with a`EmailAuthKey` property to hold the key.
32
+
In the server project, create a class to hold the secret email provider API key. The example in this article uses a class named `AuthMessageSenderOptions` with an`EmailAuthKey` property to hold the key.
33
33
34
34
`AuthMessageSenderOptions.cs`:
35
35
@@ -42,21 +42,21 @@ public class AuthMessageSenderOptions
42
42
}
43
43
```
44
44
45
-
Register the `AuthMessageSenderOptions` configuration instance in the backend server project's `Program` file:
45
+
Register the `AuthMessageSenderOptions` configuration instance in the server project's `Program` file:
## Configure a user secret for the provider's security key
52
52
53
-
If the backend server web API project (`Backend` in the [sample solution](xref:blazor/security/webassembly/standalone-with-identity/index#sample-apps)) has already been initialized for the [Secret Manager tool](xref:security/app-secrets), it will already have a app secrets identifier (`<AppSecretsId>`) in its project file (`.csproj`). In Visual Studio, you can tell if the app secrets ID is present by looking at the **Properties** panel when the project is selected in **Solution Explorer**. If the app hasn't been initialized, execute the following command in a command shell opened to the backend server project's directory. In Visual Studio, you can use the Developer PowerShell command prompt (use the `cd` command to change the directory to the server project after you open the command shell).
53
+
If the server project has already been initialized for the [Secret Manager tool](xref:security/app-secrets), it will already have a app secrets identifier (`<AppSecretsId>`) in its project file (`.csproj`). In Visual Studio, you can tell if the app secrets ID is present by looking at the **Properties** panel when the project is selected in **Solution Explorer**. If the app hasn't been initialized, execute the following command in a command shell opened to the server project's directory. In Visual Studio, you can use the Developer PowerShell command prompt (use the `cd` command to change the directory to the server project after you open the command shell).
54
54
55
55
```dotnetcli
56
56
dotnet user-secrets init
57
57
```
58
58
59
-
Set the email API key with the Secret Manager tool. In the following example, the key name is `EmailAuthKey`, and the key is represented by the `{KEY}` placeholder. Execute the following command with the API key:
59
+
Set the API key with the Secret Manager tool. In the following example, the key name is `EmailAuthKey` to match `AuthMessageSenderOptions.EmailAuthKey`, and the key is represented by the `{KEY}` placeholder. Execute the following command with the API key:
60
60
61
61
```dotnetcli
62
62
dotnet user-secrets set "EmailAuthKey" "{KEY}"
@@ -72,9 +72,9 @@ For more information, see <xref:security/app-secrets>.
72
72
73
73
The following example is based on Mailchimp's Transactional API using [Mandrill.net](https://www.nuget.org/packages/Mandrill.net). For a different provider, refer to their documentation on how to implement sending an email message.
74
74
75
-
Add the [Mandrill.net](https://www.nuget.org/packages/Mandrill.net) NuGet package to the backend server project.
75
+
Add the [Mandrill.net](https://www.nuget.org/packages/Mandrill.net) NuGet package to the server project.
76
76
77
-
Add the following `EmailSender` class to implement <xref:Microsoft.AspNetCore.Identity.IEmailSender%601>. In the following example, `AppUser` is a<xref:Microsoft.AspNetCore.Identity.IdentityUser>. The message HTML markup can be further customized. As long as the `message` passed to `MandrillMessage` starts with the `<` character, the Mandrill.net API assumes that the message body is composed in HTML.
77
+
Add the following `EmailSender` class to implement <xref:Microsoft.AspNetCore.Identity.IEmailSender%601>. In the following example, `AppUser` is an<xref:Microsoft.AspNetCore.Identity.IdentityUser>. The message HTML markup can be further customized. As long as the `message` passed to `MandrillMessage` starts with the `<` character, the Mandrill.net API assumes that the message body is composed in HTML.
78
78
79
79
`EmailSender.cs`:
80
80
@@ -132,23 +132,25 @@ public class EmailSender(IOptions<AuthMessageSenderOptions> optionsAccessor,
132
132
```
133
133
134
134
> [!NOTE]
135
-
> Body content for messages might require special encoding for the email service provider. If links in the message body can't be followed, consult the service provider's documentation.
135
+
> Body content for messages might require special encoding for the email service provider. If links in the message body can't be followed in the email message, consult the service provider's documentation to troubleshoot the problem.
136
136
137
-
## Configure the server project to support email
137
+
Add the following <xref:Microsoft.AspNetCore.Identity.IEmailSender%601> service registration to the server project's `Program` file:
138
138
139
-
In the backend server's `Program` file, require a confirmed email to register an account. Locate the line that calls <xref:Microsoft.Extensions.DependencyInjection.IdentityServiceCollectionExtensions.AddIdentityCore%2A> and set the <xref:Microsoft.AspNetCore.Identity.SignInOptions.RequireConfirmedEmail> property to `true`:
## Configure the server project to require email confirmation
144
+
145
+
In the server's `Program` file, require a confirmed email address to sign in to the app.
146
+
147
+
Locate the line that calls <xref:Microsoft.Extensions.DependencyInjection.IdentityServiceCollectionExtensions.AddIdentityCore%2A> and set the <xref:Microsoft.AspNetCore.Identity.SignInOptions.RequireConfirmedEmail> property to `true`:
Add the following service registration to set the email sender implementation to `EmailSender` for <xref:Microsoft.AspNetCore.Identity.IEmailSender%601>:
## Update the client project's account registration response
153
155
154
156
In the client project's `Register` component (`Components/Identity/Register.razor`), change the message to users on a successful account registration to instruct them to confirm their account. The following example includes a link to trigger Identity on the server to resend the confirmation email.
@@ -191,18 +193,29 @@ In the server project's seed data class (`SeedData.cs`), change the code in the
191
193
+ }
192
194
```
193
195
196
+
## Enable account confirmation after a site has users
197
+
198
+
Enabling account confirmation on a site with users locks out all the existing users. Existing users are locked out because their accounts aren't confirmed. To work around existing user lockout, use one of the following approaches:
199
+
200
+
* Update the database to mark all existing users as confirmed.
201
+
* Confirm existing users. For example, batch-send emails with confirmation links.
202
+
194
203
## Password recovery
195
204
196
-
Password recovery requires the server app to adopt an email provider in order to send password resent codes to users. Therefore, the guidance earlier in this article to enable account confirmation should be followed to enable an email provider.
205
+
Password recovery requires the server app to adopt an email provider in order to send password reset codes to users. Therefore, follow the guidance earlier in this article to adopt an email provider:
206
+
207
+
*[Select and configure an email provider for the server project](#select-and-configure-an-email-provider-for-the-server-project)
208
+
*[Configure a user secret for the provider's security key](#configure-a-user-secret-for-the-providers-security-key)
209
+
*[Implement `IEmailSender` in the server project](#implement-iemailsender-in-the-server-project)
197
210
198
211
Password recovery is a two-step process:
199
212
200
213
1. A POST request is made to the `/forgotPassword` endpoint provided by <xref:Microsoft.AspNetCore.Routing.IdentityApiEndpointRouteBuilderExtensions.MapIdentityApi%2A> in the server project. A message in the UI instructs the user to check their email for a reset code.
201
-
1. A POST request is made to the `/resetPassword` endpoint of the server project with the user's email addres, password reset code, and new password.
214
+
1. A POST request is made to the `/resetPassword` endpoint of the server project with the user's email address, password reset code, and new password.
202
215
203
-
The preceding steps are demonstrated by the following implementation guidance for the [sample apps](xref:blazor/security/webassembly/standalone-with-identity/index#sample-apps).
216
+
The preceding steps are demonstrated by the following implementation guidance for the [sample solution](xref:blazor/security/webassembly/standalone-with-identity/index#sample-apps).
204
217
205
-
Add the following method signatures to the `IAccountManagement` class (`Identity/IAccountManagement.cs`) in the client project (`BlazorWasmAuth`).
218
+
In the client project, add the following method signatures to the `IAccountManagement` class (`Identity/IAccountManagement.cs`):
206
219
207
220
```csharp
208
221
publicTask<bool>ForgotPasswordAsync(stringemail);
@@ -211,7 +224,7 @@ public Task<FormResult> ResetPasswordAsync(string email, string resetCode,
211
224
stringnewPassword);
212
225
```
213
226
214
-
Provide implementations for the preceding methods in the `CookieAuthenticationStateProvider` class (`Identity/CookieAuthenticationStateProvider.cs`):
227
+
In the client project, add implementations for the preceding methods in the `CookieAuthenticationStateProvider` class (`Identity/CookieAuthenticationStateProvider.cs`):
Add the following `ForgotPassword` component to the client project (`BlazorWasmAuth`). Code lines in the following component are shortened for display in this article.
329
+
In the client project, add the following `ForgotPassword` component.
330
+
331
+
> [!NOTE]
332
+
> Code lines in the following example are broken across two or more lines to eliminate or reduce horizontal scrolling in this article, but you can place the following code as shown into a test app. The code executes regardless of the artificial line breaks.
317
333
318
334
`Components/Identity/ForgotPassword.razor`:
319
335
@@ -523,7 +539,7 @@ The default token lifespan of the [Identity user tokens](https://github.com/dotn
To change the email token lifespan, add a custom <xref:Microsoft.AspNetCore.Identity.DataProtectorTokenProvider%601> and <xref:Microsoft.AspNetCore.Identity.DataProtectionTokenProviderOptions>:
542
+
To change the email token lifespan, add a custom <xref:Microsoft.AspNetCore.Identity.DataProtectorTokenProvider%601> and <xref:Microsoft.AspNetCore.Identity.DataProtectionTokenProviderOptions>.
## Enable account confirmation after a site has users
603
-
604
-
Enabling account confirmation on a site with users locks out all the existing users. Existing users are locked out because their accounts aren't confirmed. To work around existing user lockout, use one of the following approaches:
605
-
606
-
* Update the database to mark all existing users as confirmed.
607
-
* Confirm existing users. For example, batch-send emails with confirmation links.
0 commit comments