Is an API that supports user interface (UI) login functionality.
Manages users, passwords, profile data, roles, claims, tokens, email confirmation, and more.
Users can create an account with the login information stored in Identity or they can use an external login provider. Supported external login providers include Facebook, Google, Microsoft Account, and Twitter.
Identity is typically configured using a SQL Server database to store user names, passwords, and profile data. Alternatively, another persistent store can be used, for example, Azure Table Storage.
In this topic, you learn how to use Identity to register, log in, and log out a user. Note: the templates treat username and email as the same for users. For more detailed instructions about creating apps that use Identity, see Next Steps.
Select the ASP.NET Core Web App template. Name the project WebApp1 to have the same namespace as the project download. Click OK.
In the Authentication type input, select Individual User Accounts.
dotnet new webapp --auth Individual -o WebApp1
The preceding command creates a Razor web app using SQLite. To create the web app with LocalDB, run the following command:
dotnet new webapp --auth Individual -uld -o WebApp1
The generated project provides ASP.NET Core Identity as a Razor class library. The Identity Razor class library exposes endpoints with the Identity area. For example:
By default the architecture of the .NET binaries to install represents the currently running OS architecture. To specify a different OS architecture, see dotnet tool install, --arch option.
For more information, see GitHub issue dotnet/AspNetCore.Docs #29262.
For LocalDB, run the following command:
dotnet ef database update
Test Register and Login
Run the app and register a user. Depending on your screen size, you might need to select the navigation toggle button to see the Register and Login links.
The preceding code configures Identity with default option values. Services are made available to the app through dependency injection.
Identity is enabled by calling UseAuthentication. UseAuthentication adds authentication middleware to the request pipeline.
The template-generated app doesn't use authorization. app.UseAuthorization is included to ensure it's added in the correct order should the app add authorization. UseRouting, UseAuthentication, and UseAuthorization must be called in the order shown in the preceding code.
If you created the project with name WebApp1, and you're not using SQLite, run the following commands. Otherwise, use the correct namespace for the ApplicationDbContext:
PowerShell uses semicolon as a command separator. When using PowerShell, escape the semicolons in the file list or put the file list in double quotes, as the preceding example shows.
When a user clicks the Register button on the Register page, the RegisterModel.OnPostAsync action is invoked. The user is created by CreateAsync(TUser) on the _userManager object:
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync())
.ToList();
if (ModelState.IsValid)
{
var user = new IdentityUser { UserName = Input.Email, Email = Input.Email };
var result = await _userManager.CreateAsync(user, Input.Password);
if (result.Succeeded)
{
_logger.LogInformation("User created a new account with password.");
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
var callbackUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new { area = "Identity", userId = user.Id, code = code },
protocol: Request.Scheme);
await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
if (_userManager.Options.SignIn.RequireConfirmedAccount)
{
return RedirectToPage("RegisterConfirmation",
new { email = Input.Email });
}
else
{
await _signInManager.SignInAsync(user, isPersistent: false);
return LocalRedirect(returnUrl);
}
}
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
// If we got this far, something failed, redisplay form
return Page();
}
Disable default account verification
With the default templates, the user is redirected to the Account.RegisterConfirmation where they can select a link to have the account confirmed. The default Account.RegisterConfirmation is used only for testing, automatic account verification should be disabled in a production app.
To require a confirmed account and prevent immediate login at registration, set DisplayConfirmAccountLink = false in /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs:
[AllowAnonymous]
public class RegisterConfirmationModel : PageModel
{
private readonly UserManager<IdentityUser> _userManager;
private readonly IEmailSender _sender;
public RegisterConfirmationModel(UserManager<IdentityUser> userManager, IEmailSender sender)
{
_userManager = userManager;
_sender = sender;
}
public string Email { get; set; }
public bool DisplayConfirmAccountLink { get; set; }
public string EmailConfirmationUrl { get; set; }
public async Task<IActionResult> OnGetAsync(string email, string returnUrl = null)
{
if (email == null)
{
return RedirectToPage("/Index");
}
var user = await _userManager.FindByEmailAsync(email);
if (user == null)
{
return NotFound($"Unable to load user with email '{email}'.");
}
Email = email;
// Once you add a real email sender, you should remove this code that lets you confirm the account
DisplayConfirmAccountLink = false;
if (DisplayConfirmAccountLink)
{
var userId = await _userManager.GetUserIdAsync(user);
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
EmailConfirmationUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new { area = "Identity", userId = userId, code = code, returnUrl = returnUrl },
protocol: Request.Scheme);
}
return Page();
}
}
Log in
The Login form is displayed when:
The Log in link is selected.
A user attempts to access a restricted page that they aren't authorized to access or when they haven't been authenticated by the system.
When the form on the Login page is submitted, the OnPostAsync action is called. PasswordSignInAsync is called on the _signInManager object.
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
if (ModelState.IsValid)
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout,
// set lockoutOnFailure: true
var result = await _signInManager.PasswordSignInAsync(Input.Email,
Input.Password, Input.RememberMe, lockoutOnFailure: true);
if (result.Succeeded)
{
_logger.LogInformation("User logged in.");
return LocalRedirect(returnUrl);
}
if (result.RequiresTwoFactor)
{
return RedirectToPage("./LoginWith2fa", new
{
ReturnUrl = returnUrl,
RememberMe = Input.RememberMe
});
}
if (result.IsLockedOut)
{
_logger.LogWarning("User account locked out.");
return RedirectToPage("./Lockout");
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return Page();
}
}
// If we got this far, something failed, redisplay form
return Page();
}
The Log out link invokes the LogoutModel.OnPost action.
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;
namespace WebApp1.Areas.Identity.Pages.Account
{
[AllowAnonymous]
public class LogoutModel : PageModel
{
private readonly SignInManager<IdentityUser> _signInManager;
private readonly ILogger<LogoutModel> _logger;
public LogoutModel(SignInManager<IdentityUser> signInManager, ILogger<LogoutModel> logger)
{
_signInManager = signInManager;
_logger = logger;
}
public void OnGet()
{
}
public async Task<IActionResult> OnPost(string returnUrl = null)
{
await _signInManager.SignOutAsync();
_logger.LogInformation("User logged out.");
if (returnUrl != null)
{
return LocalRedirect(returnUrl);
}
else
{
return RedirectToPage();
}
}
}
}
In the preceding code, the code return RedirectToPage(); needs to be a redirect so that the browser performs a new request and the identity for the user gets updated.
SignOutAsync clears the user's claims stored in a cookie.
Post is specified in the Pages/Shared/_LoginPartial.cshtml:
The default web project templates allow anonymous access to the home pages. To test Identity, add [Authorize]:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
namespace WebApp1.Pages
{
[Authorize]
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;
public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
}
If you are signed in, sign out. Run the app and select the Privacy link. You are redirected to the login page.
The primary package for Identity is Microsoft.AspNetCore.Identity. This package contains the core set of interfaces for ASP.NET Core Identity, and is included by Microsoft.AspNetCore.Identity.EntityFrameworkCore.
To prevent publishing static Identity assets (stylesheets and JavaScript files for Identity UI) to the web root, add the following ResolveStaticWebAssetsInputsDependsOn property and RemoveIdentityAssets target to the app's project file:
Is an API that supports user interface (UI) login functionality.
Manages users, passwords, profile data, roles, claims, tokens, email confirmation, and more.
Users can create an account with the login information stored in Identity or they can use an external login provider. Supported external login providers include Facebook, Google, Microsoft Account, and Twitter.
Identity is typically configured using a SQL Server database to store user names, passwords, and profile data. Alternatively, another persistent store can be used, for example, Azure Table Storage.
In this topic, you learn how to use Identity to register, log in, and log out a user. Note: the templates treat username and email as the same for users. For more detailed instructions about creating apps that use Identity, see Next Steps.
Select ASP.NET Core Web Application. Name the project WebApp1 to have the same namespace as the project download. Click OK.
Select an ASP.NET Core Web Application, then select Change Authentication.
Select Individual User Accounts and click OK.
dotnet new webapp --auth Individual -o WebApp1
The preceding command creates a Razor web app using SQLite. To create the web app with LocalDB, run the following command:
dotnet new webapp --auth Individual -uld -o WebApp1
The generated project provides ASP.NET Core Identity as a Razor class library. The Identity Razor class library exposes endpoints with the Identity area. For example:
By default the architecture of the .NET binaries to install represents the currently running OS architecture. To specify a different OS architecture, see dotnet tool install, --arch option.
For more information, see GitHub issue dotnet/AspNetCore.Docs #29262.
For LocalDB, run the following command:
dotnet ef database update
Test Register and Login
Run the app and register a user. Depending on your screen size, you might need to select the navigation toggle button to see the Register and Login links.
From the View menu, select SQL Server Object Explorer (SSOX).
Navigate to (localdb)MSSQLLocalDB(SQL Server 13). Right-click on dbo.AspNetUsers > View Data:
There are many third party tools you can download to manage and view a SQLite database, for example DB Browser for SQLite.
Configure Identity services
Services are added in ConfigureServices. The typical pattern is to call all the Add{Service} methods, and then call all the services.Configure{Service} methods.
The template-generated app doesn't use authorization. app.UseAuthorization is included to ensure it's added in the correct order should the app add authorization. UseRouting, UseAuthentication, UseAuthorization, and UseEndpoints must be called in the order shown in the preceding code.
If you created the project with name WebApp1, and you're not using SQLite, run the following commands. Otherwise, use the correct namespace for the ApplicationDbContext:
PowerShell uses semicolon as a command separator. When using PowerShell, escape the semicolons in the file list or put the file list in double quotes, as the preceding example shows.
When a user clicks the Register button on the Register page, the RegisterModel.OnPostAsync action is invoked. The user is created by CreateAsync(TUser) on the _userManager object:
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync())
.ToList();
if (ModelState.IsValid)
{
var user = new IdentityUser { UserName = Input.Email, Email = Input.Email };
var result = await _userManager.CreateAsync(user, Input.Password);
if (result.Succeeded)
{
_logger.LogInformation("User created a new account with password.");
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
var callbackUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new { area = "Identity", userId = user.Id, code = code },
protocol: Request.Scheme);
await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
$"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
if (_userManager.Options.SignIn.RequireConfirmedAccount)
{
return RedirectToPage("RegisterConfirmation",
new { email = Input.Email });
}
else
{
await _signInManager.SignInAsync(user, isPersistent: false);
return LocalRedirect(returnUrl);
}
}
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
// If we got this far, something failed, redisplay form
return Page();
}
Disable default account verification
With the default templates, the user is redirected to the Account.RegisterConfirmation where they can select a link to have the account confirmed. The default Account.RegisterConfirmation is used only for testing, automatic account verification should be disabled in a production app.
To require a confirmed account and prevent immediate login at registration, set DisplayConfirmAccountLink = false in /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs:
[AllowAnonymous]
public class RegisterConfirmationModel : PageModel
{
private readonly UserManager<IdentityUser> _userManager;
private readonly IEmailSender _sender;
public RegisterConfirmationModel(UserManager<IdentityUser> userManager, IEmailSender sender)
{
_userManager = userManager;
_sender = sender;
}
public string Email { get; set; }
public bool DisplayConfirmAccountLink { get; set; }
public string EmailConfirmationUrl { get; set; }
public async Task<IActionResult> OnGetAsync(string email, string returnUrl = null)
{
if (email == null)
{
return RedirectToPage("/Index");
}
var user = await _userManager.FindByEmailAsync(email);
if (user == null)
{
return NotFound($"Unable to load user with email '{email}'.");
}
Email = email;
// Once you add a real email sender, you should remove this code that lets you confirm the account
DisplayConfirmAccountLink = false;
if (DisplayConfirmAccountLink)
{
var userId = await _userManager.GetUserIdAsync(user);
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
EmailConfirmationUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new { area = "Identity", userId = userId, code = code, returnUrl = returnUrl },
protocol: Request.Scheme);
}
return Page();
}
}
Log in
The Login form is displayed when:
The Log in link is selected.
A user attempts to access a restricted page that they aren't authorized to access or when they haven't been authenticated by the system.
When the form on the Login page is submitted, the OnPostAsync action is called. PasswordSignInAsync is called on the _signInManager object.
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
if (ModelState.IsValid)
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout,
// set lockoutOnFailure: true
var result = await _signInManager.PasswordSignInAsync(Input.Email,
Input.Password, Input.RememberMe, lockoutOnFailure: true);
if (result.Succeeded)
{
_logger.LogInformation("User logged in.");
return LocalRedirect(returnUrl);
}
if (result.RequiresTwoFactor)
{
return RedirectToPage("./LoginWith2fa", new
{
ReturnUrl = returnUrl,
RememberMe = Input.RememberMe
});
}
if (result.IsLockedOut)
{
_logger.LogWarning("User account locked out.");
return RedirectToPage("./Lockout");
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return Page();
}
}
// If we got this far, something failed, redisplay form
return Page();
}
The Log out link invokes the LogoutModel.OnPost action.
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;
namespace WebApp1.Areas.Identity.Pages.Account
{
[AllowAnonymous]
public class LogoutModel : PageModel
{
private readonly SignInManager<IdentityUser> _signInManager;
private readonly ILogger<LogoutModel> _logger;
public LogoutModel(SignInManager<IdentityUser> signInManager, ILogger<LogoutModel> logger)
{
_signInManager = signInManager;
_logger = logger;
}
public void OnGet()
{
}
public async Task<IActionResult> OnPost(string returnUrl = null)
{
await _signInManager.SignOutAsync();
_logger.LogInformation("User logged out.");
if (returnUrl != null)
{
return LocalRedirect(returnUrl);
}
else
{
return RedirectToPage();
}
}
}
}
In the preceding code, the code return RedirectToPage(); needs to be a redirect so that the browser performs a new request and the identity for the user gets updated.
SignOutAsync clears the user's claims stored in a cookie.
Post is specified in the Pages/Shared/_LoginPartial.cshtml:
The default web project templates allow anonymous access to the home pages. To test Identity, add [Authorize]:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
namespace WebApp1.Pages
{
[Authorize]
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;
public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
}
}
If you are signed in, sign out. Run the app and select the Privacy link. You are redirected to the login page.
The primary package for Identity is Microsoft.AspNetCore.Identity. This package contains the core set of interfaces for ASP.NET Core Identity, and is included by Microsoft.AspNetCore.Identity.EntityFrameworkCore.
See Configuration for a sample that sets the minimum password requirements.
Prevent publish of static Identity assets
To prevent publishing static Identity assets (stylesheets and JavaScript files for Identity UI) to the web root, add the following ResolveStaticWebAssetsInputsDependsOn property and RemoveIdentityAssets target to the app's project file:
The source for this content can be found on GitHub, where you can also create and review issues and pull requests. For more information, see our contributor guide.
ASP.NET Core feedback
ASP.NET Core is an open source project. Select a link to provide feedback: