--- title: Migrate authentication and Identity to ASP.NET Core 2.0 author: rick-anderson description: This article outlines the most common steps for migrating ASP.NET Core 1.x authentication and Identity to ASP.NET Core 2.0. ms.author: wpickett ms.date: 06/21/2019 uid: migration/1x-to-2x/identity-2x --- # Migrate authentication and Identity to ASP.NET Core 2.0 By [Scott Addie](https://github.com/scottaddie) and [Hao Kung](https://github.com/HaoK) ASP.NET Core 2.0 has a new model for authentication and [Identity](xref:security/authentication/identity) that simplifies configuration by using services. ASP.NET Core 1.x applications that use authentication or Identity can be updated to use the new model as outlined below. ## Update namespaces In 1.x, classes such `IdentityRole` and `IdentityUser` were found in the `Microsoft.AspNetCore.Identity.EntityFrameworkCore` namespace. In 2.0, the namespace became the new home for several of such classes. With the default Identity code, affected classes include `ApplicationUser` and `Startup`. Adjust your `using` statements to resolve the affected references. ## Authentication Middleware and services In 1.x projects, authentication is configured via middleware. A middleware method is invoked for each authentication scheme you want to support. The following 1.x example configures Facebook authentication with Identity in `Startup.cs`: ```csharp public void ConfigureServices(IServiceCollection services) { services.AddIdentity() .AddEntityFrameworkStores(); } public void Configure(IApplicationBuilder app, ILoggerFactory loggerfactory) { app.UseIdentity(); app.UseFacebookAuthentication(new FacebookOptions { AppId = Configuration["auth:facebook:appid"], AppSecret = Configuration["auth:facebook:appsecret"] }); } ``` In 2.0 projects, authentication is configured via services. Each authentication scheme is registered in the `ConfigureServices` method of `Startup.cs`. The `UseIdentity` method is replaced with `UseAuthentication`. The following 2.0 example configures Facebook authentication with Identity in `Startup.cs`: ```csharp public void ConfigureServices(IServiceCollection services) { services.AddIdentity() .AddEntityFrameworkStores(); // If you want to tweak Identity cookies, they're no longer part of IdentityOptions. services.ConfigureApplicationCookie(options => options.LoginPath = "/Account/LogIn"); services.AddAuthentication() .AddFacebook(options => { options.AppId = Configuration["auth:facebook:appid"]; options.AppSecret = Configuration["auth:facebook:appsecret"]; }); } public void Configure(IApplicationBuilder app, ILoggerFactory loggerfactory) { app.UseAuthentication(); } ``` The `UseAuthentication` method adds a single authentication middleware component, which is responsible for automatic authentication and the handling of remote authentication requests. It replaces all of the individual middleware components with a single, common middleware component. Below are 2.0 migration instructions for each major authentication scheme. ### Cookie-based authentication Select one of the two options below, and make the necessary changes in `Startup.cs`: 1. Use cookies with Identity * Replace `UseIdentity` with `UseAuthentication` in the `Configure` method: ```csharp app.UseAuthentication(); ``` * Invoke the `AddIdentity` method in the `ConfigureServices` method to add the cookie authentication services. * Optionally, invoke the `ConfigureApplicationCookie` or `ConfigureExternalCookie` method in the `ConfigureServices` method to tweak the Identity cookie settings. ```csharp services.AddIdentity() .AddEntityFrameworkStores() .AddDefaultTokenProviders(); services.ConfigureApplicationCookie(options => options.LoginPath = "/Account/LogIn"); ``` 2. Use cookies without Identity * Replace the `UseCookieAuthentication` method call in the `Configure` method with `UseAuthentication`: ```csharp app.UseAuthentication(); ``` * Invoke the `AddAuthentication` and `AddCookie` methods in the `ConfigureServices` method: ```csharp // If you don't want the cookie to be automatically authenticated and assigned to HttpContext.User, // remove the CookieAuthenticationDefaults.AuthenticationScheme parameter passed to AddAuthentication. services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.LoginPath = "/Account/LogIn"; options.LogoutPath = "/Account/LogOff"; }); ``` ### JWT Bearer Authentication Make the following changes in `Startup.cs`: * Replace the `UseJwtBearerAuthentication` method call in the `Configure` method with `UseAuthentication`: ```csharp app.UseAuthentication(); ``` * Invoke the `AddJwtBearer` method in the `ConfigureServices` method: ```csharp services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.Audience = "http://localhost:5001/"; options.Authority = "http://localhost:5000/"; }); ``` This code snippet doesn't use Identity, so the default scheme should be set by passing `JwtBearerDefaults.AuthenticationScheme` to the `AddAuthentication` method. ### OpenID Connect (OIDC) authentication Make the following changes in `Startup.cs`: * Replace the `UseOpenIdConnectAuthentication` method call in the `Configure` method with `UseAuthentication`: ```csharp app.UseAuthentication(); ``` * Invoke the `AddOpenIdConnect` method in the `ConfigureServices` method: ```csharp services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; }) .AddCookie() .AddOpenIdConnect(options => { options.Authority = Configuration["auth:oidc:authority"]; options.ClientId = Configuration["auth:oidc:clientid"]; }); ``` * Replace the `PostLogoutRedirectUri` property in the `OpenIdConnectOptions` action with `SignedOutRedirectUri`: ```csharp .AddOpenIdConnect(options => { options.SignedOutRedirectUri = "https://contoso.com"; }); ``` ### Facebook authentication Make the following changes in `Startup.cs`: * Replace the `UseFacebookAuthentication` method call in the `Configure` method with `UseAuthentication`: ```csharp app.UseAuthentication(); ``` * Invoke the `AddFacebook` method in the `ConfigureServices` method: ```csharp services.AddAuthentication() .AddFacebook(options => { options.AppId = Configuration["auth:facebook:appid"]; options.AppSecret = Configuration["auth:facebook:appsecret"]; }); ``` ### Google authentication Make the following changes in `Startup.cs`: * Replace the `UseGoogleAuthentication` method call in the `Configure` method with `UseAuthentication`: ```csharp app.UseAuthentication(); ``` * Invoke the `AddGoogle` method in the `ConfigureServices` method: ```csharp services.AddAuthentication() .AddGoogle(options => { options.ClientId = Configuration["auth:google:clientid"]; options.ClientSecret = Configuration["auth:google:clientsecret"]; }); ``` ### Microsoft Account authentication For more information on Microsoft account authentication, see [this GitHub issue](https://github.com/dotnet/AspNetCore.Docs/issues/14455). Make the following changes in `Startup.cs`: * Replace the `UseMicrosoftAccountAuthentication` method call in the `Configure` method with `UseAuthentication`: ```csharp app.UseAuthentication(); ``` * Invoke the `AddMicrosoftAccount` method in the `ConfigureServices` method: ```csharp services.AddAuthentication() .AddMicrosoftAccount(options => { options.ClientId = Configuration["auth:microsoft:clientid"]; options.ClientSecret = Configuration["auth:microsoft:clientsecret"]; }); ``` ### Twitter authentication Make the following changes in `Startup.cs`: * Replace the `UseTwitterAuthentication` method call in the `Configure` method with `UseAuthentication`: ```csharp app.UseAuthentication(); ``` * Invoke the `AddTwitter` method in the `ConfigureServices` method: ```csharp services.AddAuthentication() .AddTwitter(options => { options.ConsumerKey = Configuration["auth:twitter:consumerkey"]; options.ConsumerSecret = Configuration["auth:twitter:consumersecret"]; }); ``` ### Setting default authentication schemes In 1.x, the `AutomaticAuthenticate` and `AutomaticChallenge` properties of the base class were intended to be set on a single authentication scheme. There was no good way to enforce this. In 2.0, these two properties have been removed as properties on the individual `AuthenticationOptions` instance. They can be configured in the `AddAuthentication` method call within the `ConfigureServices` method of `Startup.cs`: ```csharp services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme); ``` In the preceding code snippet, the default scheme is set to `CookieAuthenticationDefaults.AuthenticationScheme` ("Cookies"). Alternatively, use an overloaded version of the `AddAuthentication` method to set more than one property. In the following overloaded method example, the default scheme is set to `CookieAuthenticationDefaults.AuthenticationScheme`. The authentication scheme may alternatively be specified within your individual `[Authorize]` attributes or authorization policies. ```csharp services.AddAuthentication(options => { options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; }); ``` Define a default scheme in 2.0 if one of the following conditions is true: * You want the user to be automatically signed in * You use the `[Authorize]` attribute or authorization policies without specifying schemes An exception to this rule is the `AddIdentity` method. This method adds cookies for you and sets the default authenticate and challenge schemes to the application cookie `IdentityConstants.ApplicationScheme`. Additionally, it sets the default sign-in scheme to the external cookie `IdentityConstants.ExternalScheme`. ## Use HttpContext authentication extensions The `IAuthenticationManager` interface is the main entry point into the 1.x authentication system. It has been replaced with a new set of `HttpContext` extension methods in the `Microsoft.AspNetCore.Authentication` namespace. For example, 1.x projects reference an `Authentication` property: [!code-csharp[](../1x-to-2x/samples/AspNetCoreDotNetCore1App/AspNetCoreDotNetCore1App/Controllers/AccountController.cs?name=snippet_AuthenticationProperty)] In 2.0 projects, import the `Microsoft.AspNetCore.Authentication` namespace, and delete the `Authentication` property references: [!code-csharp[](../1x-to-2x/samples/AspNetCoreDotNetCore2App/AspNetCoreDotNetCore2App/Controllers/AccountController.cs?name=snippet_AuthenticationProperty)] ## Windows Authentication (HTTP.sys / IISIntegration) There are two variations of Windows authentication: * The host only allows authenticated users. This variation isn't affected by the 2.0 changes. * The host allows both anonymous and authenticated users. This variation is affected by the 2.0 changes. For example, the app should allow anonymous users at the [IIS](xref:host-and-deploy/iis/index) or [HTTP.sys](xref:fundamentals/servers/httpsys) layer but authorize users at the controller level. In this scenario, set the default scheme in the `Startup.ConfigureServices` method. For [Microsoft.AspNetCore.Server.IISIntegration](https://www.nuget.org/packages/Microsoft.AspNetCore.Server.IISIntegration/), set the default scheme to `IISDefaults.AuthenticationScheme`: ```csharp using Microsoft.AspNetCore.Server.IISIntegration; services.AddAuthentication(IISDefaults.AuthenticationScheme); ``` For [Microsoft.AspNetCore.Server.HttpSys](https://www.nuget.org/packages/Microsoft.AspNetCore.Server.HttpSys/), set the default scheme to `HttpSysDefaults.AuthenticationScheme`: ```csharp using Microsoft.AspNetCore.Server.HttpSys; services.AddAuthentication(HttpSysDefaults.AuthenticationScheme); ``` Failure to set the default scheme prevents the authorize (challenge) request from working with the following exception: > `System.InvalidOperationException`: No authenticationScheme was specified, and there was no DefaultChallengeScheme found. For more information, see . ## IdentityCookieOptions instances A side effect of the 2.0 changes is the switch to using named options instead of cookie options instances. The ability to customize the Identity cookie scheme names is removed. For example, 1.x projects use [constructor injection](xref:mvc/controllers/dependency-injection#constructor-injection) to pass an `IdentityCookieOptions` parameter into `AccountController.cs` and `ManageController.cs`. The external cookie authentication scheme is accessed from the provided instance: [!code-csharp[](../1x-to-2x/samples/AspNetCoreDotNetCore1App/AspNetCoreDotNetCore1App/Controllers/AccountController.cs?name=snippet_AccountControllerConstructor&highlight=4,11)] The aforementioned constructor injection becomes unnecessary in 2.0 projects, and the `_externalCookieScheme` field can be deleted: [!code-csharp[](../1x-to-2x/samples/AspNetCoreDotNetCore2App/AspNetCoreDotNetCore2App/Controllers/AccountController.cs?name=snippet_AccountControllerConstructor)] 1.x projects used the `_externalCookieScheme` field as follows: [!code-csharp[](../1x-to-2x/samples/AspNetCoreDotNetCore1App/AspNetCoreDotNetCore1App/Controllers/AccountController.cs?name=snippet_AuthenticationProperty)] In 2.0 projects, replace the preceding code with the following. The `IdentityConstants.ExternalScheme` constant can be used directly. [!code-csharp[](../1x-to-2x/samples/AspNetCoreDotNetCore2App/AspNetCoreDotNetCore2App/Controllers/AccountController.cs?name=snippet_AuthenticationProperty)] Resolve the newly added `SignOutAsync` call by importing the following namespace: [!code-csharp[](../1x-to-2x/samples/AspNetCoreDotNetCore2App/AspNetCoreDotNetCore2App/Controllers/AccountController.cs?name=snippet_AuthenticationImport)] ## Add IdentityUser POCO navigation properties The Entity Framework (EF) Core navigation properties of the base `IdentityUser` POCO (Plain Old CLR Object) have been removed. If your 1.x project used these properties, manually add them back to the 2.0 project: ```csharp /// /// Navigation property for the roles this user belongs to. /// public virtual ICollection> Roles { get; } = new List>(); /// /// Navigation property for the claims this user possesses. /// public virtual ICollection> Claims { get; } = new List>(); /// /// Navigation property for this users login accounts. /// public virtual ICollection> Logins { get; } = new List>(); ``` To prevent duplicate foreign keys when running EF Core Migrations, add the following to your `IdentityDbContext` class' `OnModelCreating` method (after the `base.OnModelCreating();` call): ```csharp protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); // Customize the ASP.NET Core Identity model and override the defaults if needed. // For example, you can rename the ASP.NET Core Identity table names and more. // Add your customizations after calling base.OnModelCreating(builder); builder.Entity() .HasMany(e => e.Claims) .WithOne() .HasForeignKey(e => e.UserId) .IsRequired() .OnDelete(DeleteBehavior.Cascade); builder.Entity() .HasMany(e => e.Logins) .WithOne() .HasForeignKey(e => e.UserId) .IsRequired() .OnDelete(DeleteBehavior.Cascade); builder.Entity() .HasMany(e => e.Roles) .WithOne() .HasForeignKey(e => e.UserId) .IsRequired() .OnDelete(DeleteBehavior.Cascade); } ``` ## Replace GetExternalAuthenticationSchemes The synchronous method `GetExternalAuthenticationSchemes` was removed in favor of an asynchronous version. 1.x projects have the following code in `Controllers/ManageController.cs`: [!code-csharp[](../1x-to-2x/samples/AspNetCoreDotNetCore1App/AspNetCoreDotNetCore1App/Controllers/ManageController.cs?name=snippet_GetExternalAuthenticationSchemes)] This method appears in `Views/Account/Login.cshtml` too: [!code-cshtml[](../1x-to-2x/samples/AspNetCoreDotNetCore1App/AspNetCoreDotNetCore1App/Views/Account/Login.cshtml?name=snippet_GetExtAuthNSchemes&highlight=2)] In 2.0 projects, use the method. The change in `ManageController.cs` resembles the following code: [!code-csharp[](../1x-to-2x/samples/AspNetCoreDotNetCore2App/AspNetCoreDotNetCore2App/Controllers/ManageController.cs?name=snippet_GetExternalAuthenticationSchemesAsync)] In `Login.cshtml`, the `AuthenticationScheme` property accessed in the `foreach` loop changes to `Name`: [!code-cshtml[](../1x-to-2x/samples/AspNetCoreDotNetCore2App/AspNetCoreDotNetCore2App/Views/Account/Login.cshtml?name=snippet_GetExtAuthNSchemesAsync&highlight=2,19)] ## ManageLoginsViewModel property change A `ManageLoginsViewModel` object is used in the `ManageLogins` action of `ManageController.cs`. In 1.x projects, the object's `OtherLogins` property return type is `IList`. This return type requires an import of `Microsoft.AspNetCore.Http.Authentication`: [!code-csharp[](../1x-to-2x/samples/AspNetCoreDotNetCore1App/AspNetCoreDotNetCore1App/Models/ManageViewModels/ManageLoginsViewModel.cs?name=snippet_ManageLoginsViewModel&highlight=2,11)] In 2.0 projects, the return type changes to `IList`. This new return type requires replacing the `Microsoft.AspNetCore.Http.Authentication` import with a `Microsoft.AspNetCore.Authentication` import. [!code-csharp[](../1x-to-2x/samples/AspNetCoreDotNetCore2App/AspNetCoreDotNetCore2App/Models/ManageViewModels/ManageLoginsViewModel.cs?name=snippet_ManageLoginsViewModel&highlight=2,11)] ## Additional resources For more information, see the [Discussion for Auth 2.0](https://github.com/aspnet/Security/issues/1338) issue on GitHub.