diff --git a/aspnetcore/security/authentication/identity-configuration.md b/aspnetcore/security/authentication/identity-configuration.md index 5c172ba397..cab1980545 100644 --- a/aspnetcore/security/authentication/identity-configuration.md +++ b/aspnetcore/security/authentication/identity-configuration.md @@ -12,6 +12,7 @@ uid: security/authentication/identity-configuration :::moniker range=">= aspnetcore-6.0" + ASP.NET Core Identity uses default values for settings such as password policy, lockout, and cookie configuration. These settings can be overridden at application startup. ## Identity options @@ -114,6 +115,8 @@ The following code sets `SignIn` settings (to default values): | | Allowed characters in the username. | abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
0123456789
-.\_@+ | | | Requires each user to have a unique email. | `false` | + + ### Cookie settings Configure the app's cookie in `Program.cs`. [ConfigureApplicationCookie](xref:Microsoft.Extensions.DependencyInjection.IdentityServiceCollectionExtensions.ConfigureApplicationCookie(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Action{Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationOptions})) must be called **after** calling `AddIdentity` or `AddDefaultIdentity`. @@ -146,6 +149,16 @@ builder.Services.Configure(option => [!INCLUDE[](~/includes/requireAuth.md)] + + +## ISecurityStampValidator and SignOut everywhere + +Apps need to react to events involving security sensitive actions by regenerating the users . For example, the `ClaimsPrincipal` should be regenerated when joining a role, changing the password, or other security sensitive events. Identity uses the interface to regenerate the `ClaimsPrincipal`. The default implementation of Identity registers a [SecurityStampValidator](/dotnet/api/microsoft.aspnetcore.identity.securitystampvalidator) with the main [application cookie](#cs6) and the two-factor cookie. The validator hooks into the event of each cookie to call into Identity to verify that the user's security stamp claim is unchanged from what's stored in the cookie. The validator calls in at regular intervals. The call interval is a tradeoff between hitting the datastore too frequently and not often enough. Checking with a long interval results in stale claims. Call `userManager.UpdateSecurityStampAsync(user)`to force existing cookies to be invalided the next time they are checked. Most of the Identity UI account and manage pages call `userManager.UpdateSecurityStampAsync(user)` after changing the password or adding a login. Apps can call `userManager.UpdateSecurityStampAsync(user)` to implement a sign out everywhere action. + +Changing the validation interval is shown in the following highlighted code: + +:::code language="csharp" source="~/security/authentication/identity-configuration/Program.cs" highlight="17-19"::: + :::moniker-end :::moniker range="< aspnetcore-6.0" diff --git a/aspnetcore/security/authentication/identity-configuration/Program.cs b/aspnetcore/security/authentication/identity-configuration/Program.cs new file mode 100644 index 0000000000..5eae07a013 --- /dev/null +++ b/aspnetcore/security/authentication/identity-configuration/Program.cs @@ -0,0 +1,44 @@ +using Microsoft.AspNetCore.Identity; +using Microsoft.EntityFrameworkCore; +using WebClaimsPrincipal.Data; + +var builder = WebApplication.CreateBuilder(args); + +var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") + ?? throw new InvalidOperationException("'DefaultConnection' not found."); +builder.Services.AddDbContext(options => + options.UseSqlServer(connectionString)); +builder.Services.AddDatabaseDeveloperPageExceptionFilter(); + +builder.Services.AddDefaultIdentity(options => +options.SignIn.RequireConfirmedAccount = true) + .AddEntityFrameworkStores(); + +// Force Identity's security stamp to be validated every minute. +builder.Services.Configure(o => + o.ValidationInterval = TimeSpan.FromMinutes(1)); + +builder.Services.AddRazorPages(); + +var app = builder.Build(); + +if (app.Environment.IsDevelopment()) +{ + app.UseMigrationsEndPoint(); +} +else +{ + app.UseExceptionHandler("/Error"); + app.UseHsts(); +} + +app.UseHttpsRedirection(); +app.UseStaticFiles(); + +app.UseRouting(); + +app.UseAuthorization(); + +app.MapRazorPages(); + +app.Run();