diff --git a/aspnetcore/security/authentication/identity.md b/aspnetcore/security/authentication/identity.md index 00121c8836..821426a96a 100644 --- a/aspnetcore/security/authentication/identity.md +++ b/aspnetcore/security/authentication/identity.md @@ -1,143 +1,133 @@ --- -title: Introduction to Identity +title: Introduction to Identity on ASP.NET Core author: rick-anderson -description: -keywords: ASP.NET Core, +description: Using Identity with an ASP.NET Core app +keywords: ASP.NET Core, Identity, authorization, security ms.author: riande manager: wpickett -ms.date: 10/14/2016 +ms.date: 7/7/2017 ms.topic: article ms.assetid: cf119f21-1a2b-49a2-b052-547ccb66ee83 ms.technology: aspnet ms.prod: asp.net-core uid: security/authentication/identity --- -# Introduction to Identity +# Introduction to Identity on ASP.NET Core -By [Pranav Rastogi](https://github.com/rustd), [Rick Anderson](https://twitter.com/RickAndMSFT), [Tom Dykstra](https://github.com/tdykstra), Jon Galloway, and [Erik Reitan](https://github.com/Erikre) +By [Pranav Rastogi](https://github.com/rustd), [Rick Anderson](https://twitter.com/RickAndMSFT), [Tom Dykstra](https://github.com/tdykstra), Jon Galloway, [Erik Reitan](https://github.com/Erikre), and [Steve Smith](http://ardalis.com) -ASP.NET Core Identity is a membership system which allows you to add login functionality to your application. Users can create an account and login with a user name and password or they can use an external login providers such as Facebook, Google, Microsoft Account, Twitter and more. +ASP.NET Core Identity is a membership system which allows you to add login functionality to your application. Users can create an account and login with a user name and password or they can use an external login provider such as Facebook, Google, Microsoft Account, Twitter or others. -You can configure ASP.NET Core Identity to use a SQL Server database to store user names, passwords, and profile data. Alternatively, you can use your own persistent store to store data in another persistent storage, such as Azure Table Storage. +You can configure ASP.NET Core Identity to use a SQL Server database to store user names, passwords, and profile data. Alternatively, you can use your own persistent store, for example Azure Table Storage. This document contains instructions for Visual Studio and for using the CLI. ## Overview of Identity -In this topic, you'll learn how to use ASP.NET Core Identity to add functionality to register, log in, and log out a user. You can follow along step by step or just read the details. For more detailed instructions about creating apps using ASP.NET Core Identity, see the Next Steps section at the end of this article. +In this topic, you'll learn how to use ASP.NET Core Identity to add functionality to register, log in, and log out a user. For more detailed instructions about creating apps using ASP.NET Core Identity, see the Next Steps section at the end of this article. -1. Create an ASP.NET Core Web Application project in Visual Studio with Individual User Accounts. +1. Create an ASP.NET Core Web Application project with Individual User Accounts. - In Visual Studio, select **File** -> **New** -> **Project**. Then, select the **ASP.NET Web Application** from the **New Project** dialog box. Continue by selecting an ASP.NET Core **Web Application** with **Individual User Accounts** as the authentication method. + In Visual Studio, select **File** -> **New** -> **Project**. Select the **ASP.NET Web Application** from the **New Project** dialog box. Selecting an ASP.NET Core **Web Application** with **Individual User Accounts** as the authentication method. + + Note: You must select **Individual User Accounts**. ![New Project dialog](identity/_static/01-mvc.png) + + If using the dotnet CLI, create the new project using ``dotnet new mvc --auth Individual``. This will create a new project with the same identity template code Visual Studio creates. The created project contains the `Microsoft.AspNetCore.Identity.EntityFrameworkCore` package, which will persist the identity data and schema to SQL Server using [Entity Framework Core](https://docs.efproject.net). - > [!NOTE] - >In Visual Studio, you can view NuGet packages details by selecting **Tools** -> **NuGet Package Manager** -> **Manage NuGet Packages for Solution**. - +2. Configure identity services and add middleware in `Startup`. + The identity services are added to the application in the `ConfigureServices` method in the `Startup` class: - [!code-csharp[Main](identity/sample/src/ASPNET-IdentityDemo/Startup.cs?highlight=10-12&range=38-56)] + [!code-csharp[Main](identity/sample/src/ASPNET-IdentityDemo/Startup.cs?name=configureservices&highlight=7-9,13-34)] - These services are then made available to the application through [dependency injection](../../fundamentals/dependency-injection.md). + These services are made available to the application through [dependency injection](xref:fundamentals/dependency-injection). - Identity is enabled for the application by calling `UseIdentity` in the `Configure` method of the `Startup` class. This adds cookie-based authentication to the request pipeline. + Identity is enabled for the application by calling `UseIdentity` in the `Configure` method. `UseIdentity` adds cookie-based authentication [middleware](xref:fundamentals/middleware) to the request pipeline. - [!code-csharp[Main](identity/sample/src/ASPNET-IdentityDemo/Startup.cs?highlight=22&range=58-89)] + [!code-csharp[Main](identity/sample/src/ASPNET-IdentityDemo/Startup.cs?name=configure&highlight=21)] - For more information about the application start up process, see [Application Startup](../../fundamentals/startup.md). + For more information about the application start up process, see [Application Startup](xref:fundamentals/startup). -2. Creating a user. +3. Create a user. - Launch the application from Visual Studio (**Debug** -> **Start Debugging**) and then click on the **Register** link in the browser to create a user. The following image shows the Register page which collects the user name and password. - - ![Register page with user input fields for Email (Username), Password, and Confirm Password](identity/_static/02-reg.png) - - When the user clicks the **Register** link, the `UserManager` and `SignInManager` services are injected into the Controller: - - [!code-csharp[Main](identity/sample/src/ASPNET-IdentityDemo/Controllers/AccountController.cs?highlight=3-4,11-12,17-18&range=19-43)] - - Then, the **Register** action creates the user by calling `CreateAsync` function of the `UserManager` object, as shown below: - - [!code-csharp[Main](identity/sample/src/ASPNET-IdentityDemo/Controllers/AccountController.cs?highlight=9&range=101-128)] - -3. Log in. - - If the user was successfully created, the user is logged in by the `SignInAsync` method, also contained in the `Register` action. By signing in, the `SignInAsync` method stores a cookie with the user's claims. - - [!code-csharp[Main](identity/sample/src/ASPNET-IdentityDemo/Controllers/AccountController.cs?range=101-128&highlight=18)] - - The above `SignInAsync` method calls the below `SignInAsync` task, which is contained in the `SignInManager` class. - - If needed, you can access the user's identity details inside a controller action. For instance, by setting a breakpoint inside the `HomeController.Index` action method, you can view the `User.claims` details. By having the user signed-in, you can make authorization decisions. For more information, see [Authorization](../authorization/index.md). - - As a registered user, you can log in to the web app by clicking the **Log in** link. When a registered user logs in, the `Login` action of the `AccountController` is called. Then, the **Login** action signs in the user using the `PasswordSignInAsync` method contained in the `Login` action. - - [!code-csharp[Main](identity/sample/src/ASPNET-IdentityDemo/Controllers/AccountController.cs?highlight=11&range=54-89)] - -4. Log off. - - Clicking the **Log off** link calls the `LogOut` action in the account controller. - - [!code-csharp[Main](identity/sample/src/ASPNET-IdentityDemo/Controllers/AccountController.cs?highlight=5&range=131-138)] - - The code above shows the `SignInManager.SignOutAsync` method. The `SignOutAsync` method clears the users claims stored in a cookie. - -5. Configuration. + Launch the application and then click on the **Register** link. - Identity has some default behaviors that you can override in your application's startup class. + If this is the first time you're performing this action, you may be required to run migrations. The application prompts you to **Apply Migrations**: + + ![Apply Migrations Web Page](identity/_static/apply-migrations.png) + + Alternately, you can test using ASP.NET Core Identity with your app without a persistent database by using an in-memory database. To use an in-memory database, add the ``Microsoft.EntityFrameworkCore.InMemory`` package to your app and modify your app's call to ``AddDbContext`` in ``ConfigureServices`` as follows: + + ``` + services.AddDbContext(options => + options.UseInMemoryDatabase(Guid.NewGuid().ToString())); + ``` + + When the user clicks the **Register** link, the ``Register`` action is invoked on ``AccountController``. The ``Register`` action creates the user by calling `CreateAsync` on the `_userManager` object (provided to ``AccountController`` by dependency injection): - [!code-csharp[Main](identity/sample/src/ASPNET-IdentityDemo/Startup.cs?highlight=5&range=57-78)] + [!code-csharp[Main](identity/sample/src/ASPNET-IdentityDemo/Controllers/AccountController.cs?name=register&highlight=11)] + + If the user was created successfully, the user is logged in by the call to ``_signInManager.SignInAsync``. + + **Note:** See [account confirmation](xref:security/authentication/accconfirm#prevent-login-at-registration) for steps to prevent immediate login at registration. + +4. Log in. + + Users can sign in by clicking the **Log in** link at the top of the site, or they may be navigated to the Login page if they attempt to access a part of the site that requires authorization. When the user submits the form on the Login page, the ``AccountController`` ``Login`` action is called. + + [!code-csharp[Main](identity/sample/src/ASPNET-IdentityDemo/Controllers/AccountController.cs?name=login&highlight=13-14)] + + The ``Login`` action calls ``PasswordSignInAsync`` on the ``_signInManager`` object (provided to ``AccountController`` by dependency injection). + + The base ``Controller`` class exposes a ``User`` property that you can access from controller methods. For instance, you can enumerate `User.Claims` and make authorization decisions. For more information, see [Authorization](xref:security/authorization/index). + +5. Log out. + + Clicking the **Log out** link calls the `LogOut` action. + + [!code-csharp[Main](identity/sample/src/ASPNET-IdentityDemo/Controllers/AccountController.cs?name=logout&highlight=7)] + + The preceding code above the `_signInManager.SignOutAsync` method. The `SignOutAsync` method clears the user's claims stored in a cookie. + +6. Configuration. + + Identity has some default behaviors that you can override in your application's startup class. You do not need to configure ``IdentityOptions`` if you are using the default behaviors. + + [!code-csharp[Main](identity/sample/src/ASPNET-IdentityDemo/Startup.cs?name=configureservices&highlight=13-34)] - For more information about how to configure Identity, see [Configure Identity](identity-configuration.md). + For more information about how to configure Identity, see [Configure Identity](xref:security/authentication/identity-configuration). - You also can configure the data type of the primary key, see [Configure Identity primary keys data type](identity-primary-key-configuration.md). + You also can configure the data type of the primary key, see [Configure Identity primary keys data type](xref:security/authentication/identity-primary-key-configuration). -6. View the database. +7. View the database. + + If your app is using a SQL Server database (the default on Windows and for Visual Studio users), you can view the database the app created. You can use **SQL Server Management Studio**. Alternatively, from Visual Studio, select **View** -> **SQL Server Object Explorer**. Connect to **(localdb)\MSSQLLocalDB**. The database with a name matching **aspnet-<*name of your project*>-<*date string*>** is displayed. - After stopping the application, view the user database from Visual Studio by selecting **View** -> **SQL Server Object Explorer**. Then, expand the following within the **SQL Server Object Explorer**: - - * (localdb)\MSSQLLocalDB - - * Databases - - * aspnet5-<*the name of your application*> - - * Tables - - Next, right-click the **dbo.AspNetUsers** table and select **View Data** to see the properties of the user you created. - ![Contextual menu on AspNetUsers database table](identity/_static/04-db.png) + + Expand the database and its **Tables**, then right-click the **dbo.AspNetUsers** table and select **View Data**. ## Identity Components -The primary reference assembly for the identity system is `Microsoft.AspNetCore.Identity`. This package contains the core set of interfaces for ASP.NET Core Identity. - -![Project references of ASP.NET Core Identity](identity/_static/05-dependencies.png) +The primary reference assembly for the identity system 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`. These dependencies are needed to use the identity system in ASP.NET Core applications: -* `EntityFramework.SqlServer` - Entity Framework is Microsoft's recommended data access technology for relational databases. +* `Microsoft.AspNetCore.Identity.EntityFrameworkCore` - Contains the required types to use Identity with Entity Framework Core. -* `Microsoft.AspNetCore.Authentication.Cookies` - Middleware that enables an application to use cookie based authentication, similar to ASP.NET's Forms Authentication. +* `Microsoft.EntityFrameworkCore.SqlServer` - Entity Framework Core is Microsoft's recommended data access technology for relational databases like SQL Server. For testing, you can use `Microsoft.EntityFrameworkCore.InMemory`. -* `Microsoft.AspNetCore.Cryptography.KeyDerivation` - Utilities for key derivation. - -* `Microsoft.AspNetCore.Hosting.Abstractions` - Hosting abstractions. +* `Microsoft.AspNetCore.Authentication.Cookies` - Middleware that enables an app to use cookie-based authentication. ## Migrating to ASP.NET Core Identity -For additional information and guidance on migrating your existing identity store see [Migrating Authentication and Identity](../../migration/identity.md) - - +For additional information and guidance on migrating your existing identity store see [Migrating Authentication and Identity](xref:migration/identity). ## Next Steps * [Migrating Authentication and Identity](xref:migration/identity) -* [Account Confirmation and Password Recovery](accconfirm.md) -* [Two-factor authentication with SMS](2fa.md) -* [Enabling authentication using Facebook, Google and other external providers](social/index.md) +* [Account Confirmation and Password Recovery](xref:security/authentication/accconfirm) +* [Two-factor authentication with SMS](xref:security/authentication/2fa) +* [Enabling authentication using Facebook, Google and other external providers](xref:security/authentication/social/index) diff --git a/aspnetcore/security/authentication/identity/_static/01-mvc.png b/aspnetcore/security/authentication/identity/_static/01-mvc.png index 223582a0bd..8c83000884 100644 Binary files a/aspnetcore/security/authentication/identity/_static/01-mvc.png and b/aspnetcore/security/authentication/identity/_static/01-mvc.png differ diff --git a/aspnetcore/security/authentication/identity/_static/02-reg.png b/aspnetcore/security/authentication/identity/_static/02-reg.png deleted file mode 100644 index 8b0919673c..0000000000 Binary files a/aspnetcore/security/authentication/identity/_static/02-reg.png and /dev/null differ diff --git a/aspnetcore/security/authentication/identity/_static/04-db.png b/aspnetcore/security/authentication/identity/_static/04-db.png index fa4deb9401..31734d0b53 100644 Binary files a/aspnetcore/security/authentication/identity/_static/04-db.png and b/aspnetcore/security/authentication/identity/_static/04-db.png differ diff --git a/aspnetcore/security/authentication/identity/_static/05-dependencies.png b/aspnetcore/security/authentication/identity/_static/05-dependencies.png deleted file mode 100644 index 0b12bd7bc4..0000000000 Binary files a/aspnetcore/security/authentication/identity/_static/05-dependencies.png and /dev/null differ diff --git a/aspnetcore/security/authentication/identity/_static/apply-migrations.png b/aspnetcore/security/authentication/identity/_static/apply-migrations.png new file mode 100644 index 0000000000..cb5130824f Binary files /dev/null and b/aspnetcore/security/authentication/identity/_static/apply-migrations.png differ diff --git a/aspnetcore/security/authentication/identity/sample/src/ASPNET-IdentityDemo/Controllers/AccountController.cs b/aspnetcore/security/authentication/identity/sample/src/ASPNET-IdentityDemo/Controllers/AccountController.cs index cbb913f208..24440e8f4a 100644 --- a/aspnetcore/security/authentication/identity/sample/src/ASPNET-IdentityDemo/Controllers/AccountController.cs +++ b/aspnetcore/security/authentication/identity/sample/src/ASPNET-IdentityDemo/Controllers/AccountController.cs @@ -48,7 +48,7 @@ namespace webapptemplate.Controllers ViewData["ReturnUrl"] = returnUrl; return View(); } - + #region login // // POST: /Account/Login [HttpPost] @@ -61,7 +61,8 @@ namespace webapptemplate.Controllers { // 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(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false); + var result = await _signInManager.PasswordSignInAsync(model.Email, + model.Password, model.RememberMe, lockoutOnFailure: false); if (result.Succeeded) { _logger.LogInformation(1, "User logged in."); @@ -86,6 +87,7 @@ namespace webapptemplate.Controllers // If we got this far, something failed, redisplay form return View(model); } + #endregion // // GET: /Account/Register @@ -95,7 +97,7 @@ namespace webapptemplate.Controllers { return View(); } - + #region register // // POST: /Account/Register [HttpPost] @@ -125,7 +127,9 @@ namespace webapptemplate.Controllers // If we got this far, something failed, redisplay form return View(model); } + #endregion + #region logout // // POST: /Account/LogOut [HttpPost] @@ -136,6 +140,7 @@ namespace webapptemplate.Controllers _logger.LogInformation(4, "User logged out."); return RedirectToAction(nameof(HomeController.Index), "Home"); } + #endregion // // POST: /Account/ExternalLogin diff --git a/aspnetcore/security/authentication/identity/sample/src/ASPNET-IdentityDemo/Startup.cs b/aspnetcore/security/authentication/identity/sample/src/ASPNET-IdentityDemo/Startup.cs index 204c4724f9..de02d45abc 100644 --- a/aspnetcore/security/authentication/identity/sample/src/ASPNET-IdentityDemo/Startup.cs +++ b/aspnetcore/security/authentication/identity/sample/src/ASPNET-IdentityDemo/Startup.cs @@ -1,48 +1,45 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNet.Builder; -using Microsoft.AspNet.Hosting; -using Microsoft.AspNet.Identity.EntityFramework; -using Microsoft.Data.Entity; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Identity.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using webapptemplate.Models; -using webapptemplate.Services; +using IdentityDemo.Data; +using IdentityDemo.Models; +using IdentityDemo.Services; +using System; -namespace webapptemplate +namespace IdentityDemo { public class Startup { public Startup(IHostingEnvironment env) { - // Set up configuration sources. var builder = new ConfigurationBuilder() - .AddJsonFile("appsettings.json") + .SetBasePath(env.ContentRootPath) + .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true); if (env.IsDevelopment()) { - // For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709 - builder.AddUserSecrets(); + // For more details on using the user secret store see https://go.microsoft.com/fwlink/?LinkID=532709 + builder.AddUserSecrets(); } builder.AddEnvironmentVariables(); - Configuration = builder.Build().ReloadOnChanged("appsettings.json"); + Configuration = builder.Build(); } - public IConfigurationRoot Configuration { get; set; } + public IConfigurationRoot Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. + #region configureservices public void ConfigureServices(IServiceCollection services) { // Add framework services. - services.AddEntityFramework() - .AddSqlServer() - .AddDbContext(options => - options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"])); + services.AddDbContext(options => + options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); services.AddIdentity() .AddEntityFrameworkStores() @@ -50,10 +47,6 @@ namespace webapptemplate services.AddMvc(); - // Add application services. - services.AddTransient(); - services.AddTransient(); - // Configure Identity services.Configure(options => { @@ -63,45 +56,51 @@ namespace webapptemplate options.Password.RequireNonAlphanumeric = false; options.Password.RequireUppercase = true; options.Password.RequireLowercase = false; - + // Lockout settings options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30); options.Lockout.MaxFailedAccessAttempts = 10; - + // Cookie settings options.Cookies.ApplicationCookie.ExpireTimeSpan = TimeSpan.FromDays(150); options.Cookies.ApplicationCookie.LoginPath = "/Account/LogIn"; options.Cookies.ApplicationCookie.LogoutPath = "/Account/LogOut"; - + // User settings options.User.RequireUniqueEmail = true; }); + + // Add application services. + services.AddTransient(); + services.AddTransient(); } + #endregion // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) + #region configure + public void Configure(IApplicationBuilder app, + IHostingEnvironment env, + ILoggerFactory loggerFactory) { loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug(); if (env.IsDevelopment()) { - app.UseBrowserLink(); app.UseDeveloperExceptionPage(); app.UseDatabaseErrorPage(); + app.UseBrowserLink(); } else { app.UseExceptionHandler("/Home/Error"); } - app.UseIISPlatformHandler(options => options.AuthenticationDescriptions.Clear()); - app.UseStaticFiles(); app.UseIdentity(); - // To configure external authentication please see http://go.microsoft.com/fwlink/?LinkID=532715 + // Add external authentication middleware below. To configure them please see https://go.microsoft.com/fwlink/?LinkID=532715 app.UseMvc(routes => { @@ -110,8 +109,6 @@ namespace webapptemplate template: "{controller=Home}/{action=Index}/{id?}"); }); } - - // Entry point for the application. - public static void Main(string[] args) => WebApplication.Run(args); + #endregion } }