認証を移行 Identity し、ASP.NET Core 2.0 に移行する

提供 : Scott Addie、Hao Kung

ASP.NET Core 2.0 には認証用の新しいモデルが用意され、サービスを使用して Identity 構成が簡略化されます。 ASP.NET 使用する Core 1.x アプリケーション、または以下に示す新しいモデルを使用するために更新できる Core 1.x Identity アプリケーション。

名前空間を更新する

1.x では、 や などの IdentityRole クラス IdentityUser が 名前空間で見 Microsoft.AspNetCore.Identity.EntityFrameworkCore つかりました。

2.0 では、名前空間 Microsoft.AspNetCore.Identity は、このようなクラスのいくつかの新しいホームになりました。 既定のコードでは Identity 、影響を受けるクラスには と が含 ApplicationUser まれます Startup 。 ステートメントを using 調整して、影響を受ける参照を解決します。

認証ミドルウェアとサービス

1.x プロジェクトでは、認証はミドルウェアを介して構成されます。 サポートする認証スキームごとにミドルウェア メソッドが呼び出されます。

次の 1.x の例では、Startup.cs で を使用して Identity Facebook 認証を構成します

public void ConfigureServices(IServiceCollection services)
{
    services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>();
}

public void Configure(IApplicationBuilder app, ILoggerFactory loggerfactory)
{
    app.UseIdentity();
    app.UseFacebookAuthentication(new FacebookOptions {
        AppId = Configuration["auth:facebook:appid"],
        AppSecret = Configuration["auth:facebook:appsecret"]
    });
}

2.0 プロジェクトでは、認証はサービスを介して構成されます。 各認証スキームは ConfigureServices 、Startup.cs の メソッドに登録されます。 メソッド UseIdentity は に置き換えられる UseAuthentication

次の 2.0 の例では、Startup.cs で を使用して Identity Facebook 認証を構成します

public void ConfigureServices(IServiceCollection services)
{
    services.AddIdentity<ApplicationUser, IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>();

    // 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();
}

メソッドは、自動認証とリモート認証要求の処理を担当する単一の認証 UseAuthentication ミドルウェア コンポーネントを追加します。 個々のミドルウェアコンポーネントはすべて、単一の共通ミドルウェアコンポーネントに置き換えられます。

次に、各主要な認証スキームの2.0 移行手順を示します。

次の2つのオプションのいずれかを選択し、スタートアップで必要な変更を行い ます。

  1. cookieでを使用するIdentity

    • UseIdentity UseAuthentication メソッド内のをに置き換え Configure ます。

      app.UseAuthentication();
      
    • AddIdentityメソッドでメソッドを呼び出して ConfigureServices 、認証サービスを追加し cookie ます。

    • 必要に応じて、 ConfigureApplicationCookie メソッドでメソッドまたはメソッドを呼び出して、設定を調整し ConfigureExternalCookie ConfigureServices Identity cookie ます。

      services.AddIdentity<ApplicationUser, IdentityRole>()
              .AddEntityFrameworkStores<ApplicationDbContext>()
              .AddDefaultTokenProviders();
      
      services.ConfigureApplicationCookie(options => options.LoginPath = "/Account/LogIn");
      
  2. を cookie 指定せずにを使用する Identity

    • メソッドの UseCookieAuthentication メソッド呼び出しを Configure 次のように置き換え UseAuthentication ます。

      app.UseAuthentication();
      
    • AddAuthenticationメソッドでメソッドとメソッドを呼び出し AddCookie ConfigureServices ます。

      // 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 ベアラー認証

スタートアップ で次の変更を行います。

  • メソッドの UseJwtBearerAuthentication メソッド呼び出しを Configure 次のように置き換え UseAuthentication ます。

    app.UseAuthentication();
    
  • AddJwtBearerメソッドでメソッドを呼び出し ConfigureServices ます。

    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
            {
                options.Audience = "http://localhost:5001/";
                options.Authority = "http://localhost:5000/";
            });
    

    このコードスニペットはを使用しない Identity ため、既定のスキームはメソッドに渡すことによって設定する必要があり JwtBearerDefaults.AuthenticationScheme AddAuthentication ます。

OpenID Connect (OIDC) 認証

スタートアップ で次の変更を行います。

  • メソッドの UseOpenIdConnectAuthentication メソッド呼び出しを Configure 次のように置き換え UseAuthentication ます。

    app.UseAuthentication();
    
  • AddOpenIdConnectメソッドでメソッドを呼び出し ConfigureServices ます。

    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"];
    });
    
  • アクションの PostLogoutRedirectUri プロパティを に置 OpenIdConnectOptions き換える SignedOutRedirectUri

    .AddOpenIdConnect(options =>
    {
        options.SignedOutRedirectUri = "https://contoso.com";
    });
    

Facebook での認証

Startup.cs で次の変更を行います

  • メソッドのメソッド UseFacebookAuthentication 呼び出しを に Configure 置き換える UseAuthentication

    app.UseAuthentication();
    
  • メソッドで AddFacebook メソッドを呼び ConfigureServices 出します。

    services.AddAuthentication()
            .AddFacebook(options =>
            {
                options.AppId = Configuration["auth:facebook:appid"];
                options.AppSecret = Configuration["auth:facebook:appsecret"];
            });
    

Google での認証

Startup.cs で次の変更を行います

  • メソッドのメソッド UseGoogleAuthentication 呼び出しを に Configure 置き換える UseAuthentication

    app.UseAuthentication();
    
  • メソッドで AddGoogle メソッドを呼び ConfigureServices 出します。

    services.AddAuthentication()
            .AddGoogle(options =>
            {
                options.ClientId = Configuration["auth:google:clientid"];
                options.ClientSecret = Configuration["auth:google:clientsecret"];
            });
    

Microsoft アカウント認証

認証の詳細についてはMicrosoft アカウント GitHub の問題を参照してください

Startup.cs で次の変更を行います

  • メソッドのメソッド UseMicrosoftAccountAuthentication 呼び出しを に Configure 置き換える UseAuthentication

    app.UseAuthentication();
    
  • メソッドで AddMicrosoftAccount メソッドを呼び ConfigureServices 出します。

    services.AddAuthentication()
            .AddMicrosoftAccount(options =>
            {
                options.ClientId = Configuration["auth:microsoft:clientid"];
                options.ClientSecret = Configuration["auth:microsoft:clientsecret"];
            });
    

Twitter での認証

Startup.cs で次の変更を行います

  • メソッドのメソッド UseTwitterAuthentication 呼び出しを に Configure 置き換える UseAuthentication

    app.UseAuthentication();
    
  • メソッドで AddTwitter メソッドを呼び ConfigureServices 出します。

    services.AddAuthentication()
            .AddTwitter(options =>
            {
                options.ConsumerKey = Configuration["auth:twitter:consumerkey"];
                options.ConsumerSecret = Configuration["auth:twitter:consumersecret"];
            });
    

既定の認証スキームの設定

1.x では、AuthenticationOptions 基本クラスの プロパティと プロパティは、単一の認証 AutomaticAuthenticate AutomaticChallenge スキームで設定することを目的としました。 これを強制する良い方法は何も見ていました。

2.0 では、これら 2 つのプロパティが個々のインスタンスのプロパティとして削除 AuthenticationOptions されました。 これらは AddAuthentication 、Startup.cs の メソッド内の メソッド呼 ConfigureServices び出し で構成できます

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme);

前のコード スニペットでは、既定のスキームは CookieAuthenticationDefaults.AuthenticationScheme (" Cookie s") に設定されています。

または、オーバーロードされたバージョンのメソッドを使用して、複数の AddAuthentication プロパティを設定します。 次のオーバーロードされたメソッドの例では、既定のスキームはに設定されて CookieAuthenticationDefaults.AuthenticationScheme います。 認証方式は、個々の [Authorize] 属性または承認ポリシー内で指定することもできます。

services.AddAuthentication(options =>
{
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
});

次のいずれかの条件に該当する場合は、2.0 で既定のスキームを定義します。

  • ユーザーが自動的にサインインするようにするには
  • [Authorize]スキーマを指定せずに属性または承認ポリシーを使用する

この規則の例外は AddIdentity メソッドです。 このメソッドは、を追加 cookie し、既定の認証およびチャレンジのスキームをアプリケーションに設定し cookie IdentityConstants.ApplicationScheme ます。 また、既定のサインインスキームが外部に設定され cookie IdentityConstants.ExternalScheme ます。

HttpContext 認証拡張機能の使用

IAuthenticationManagerインターフェイスは、1. x 認証システムへのメインエントリポイントです。 名前空間の新しい拡張メソッドのセットに置き換えられました HttpContext Microsoft.AspNetCore.Authentication

たとえば、1. x プロジェクトはプロパティを参照します。 Authentication

// Clear the existing external cookie to ensure a clean login process
await HttpContext.Authentication.SignOutAsync(_externalCookieScheme);

2.0 プロジェクトで、 Microsoft.AspNetCore.Authentication 名前空間をインポートし、プロパティ参照を削除し Authentication ます。

// Clear the existing external cookie to ensure a clean login process
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);

Windows 認証 (HTTP.sys/IISIntegration)

Windows 認証には、次の2つのバリエーションがあります。

  • ホストは、認証されたユーザーのみを許可します。 このバリエーションは、2.0 の変更の影響を受けません。

  • ホストは、匿名ユーザーと認証済みユーザーの両方を許可します。 このバリエーションは、2.0 の変更の影響を受けます。 たとえば、アプリでは、IISまたはユーザー レイヤーで匿名ユーザーを許可HTTP.sys、コントローラー レベルでユーザーを承認する必要があります。 このシナリオでは、 メソッドで既定のスキームを設定 Startup.ConfigureServices します。

    Microsoft.AspNetCore.Server.IISIntegration の場合、既定のスキームを に設定します IISDefaults.AuthenticationScheme

    using Microsoft.AspNetCore.Server.IISIntegration;
    
    services.AddAuthentication(IISDefaults.AuthenticationScheme);
    

    Microsoft.AspNetCore.Server.HttpSys の場合、既定のスキームを に設定します HttpSysDefaults.AuthenticationScheme

    using Microsoft.AspNetCore.Server.HttpSys;
    
    services.AddAuthentication(HttpSysDefaults.AuthenticationScheme);
    

    既定のスキームを設定しない場合、承認 (チャレンジ) 要求は次の例外で動作しません。

    System.InvalidOperationException: authenticationScheme が指定されていません。DefaultLengeScheme が見つかりませんでした。

詳細については、「ASP.NET Core で Windows 認証を構成する」を参照してください。

IdentityCookieオプション インスタンス

2.0 の変更の副作用は、オプション インスタンスではなく名前付きオプションを使用 cookie する切り替えです。 スキーム名をカスタマイズ Identity cookie する機能が削除されました。

たとえば、1.x プロジェクトでは 、コンストラクターの挿入を使用してパラメーターを IdentityCookieOptions AccountController.csManageController.cs に渡します。 外部認証 cookie スキームは、指定されたインスタンスからアクセスされます。

public AccountController(
    UserManager<ApplicationUser> userManager,
    SignInManager<ApplicationUser> signInManager,
    IOptions<IdentityCookieOptions> identityCookieOptions,
    IEmailSender emailSender,
    ISmsSender smsSender,
    ILoggerFactory loggerFactory)
{
    _userManager = userManager;
    _signInManager = signInManager;
    _externalCookieScheme = identityCookieOptions.Value.ExternalCookieAuthenticationScheme;
    _emailSender = emailSender;
    _smsSender = smsSender;
    _logger = loggerFactory.CreateLogger<AccountController>();
}

前述のコンストラクターの挿入は 2.0 プロジェクトでは不要になり、 フィールド _externalCookieScheme を削除できます。

public AccountController(
    UserManager<ApplicationUser> userManager,
    SignInManager<ApplicationUser> signInManager,
    IEmailSender emailSender,
    ISmsSender smsSender,
    ILoggerFactory loggerFactory)
{
    _userManager = userManager;
    _signInManager = signInManager;
    _emailSender = emailSender;
    _smsSender = smsSender;
    _logger = loggerFactory.CreateLogger<AccountController>();
}

1.x プロジェクトでは、次のように _externalCookieScheme フィールドを使用しました。

// Clear the existing external cookie to ensure a clean login process
await HttpContext.Authentication.SignOutAsync(_externalCookieScheme);

2.0 プロジェクトでは、前のコードを次のコードに置き換えます。 定数 IdentityConstants.ExternalScheme は直接使用できます。

// Clear the existing external cookie to ensure a clean login process
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);

次の名前空間をインポートして SignOutAsync 、新しく追加された呼び出しを解決します。

using Microsoft.AspNetCore.Authentication;

ユーザー Identity POCO ナビゲーション プロパティを追加する

基本 POCO (Plain old CLR Object) の Entity Framework (EF) Core ナビゲーション IdentityUser プロパティが削除されました。 1.x プロジェクトでこれらのプロパティが使用されている場合は、手動で 2.0 プロジェクトに追加します。

/// <summary>
/// Navigation property for the roles this user belongs to.
/// </summary>
public virtual ICollection<IdentityUserRole<int>> Roles { get; } = new List<IdentityUserRole<int>>();

/// <summary>
/// Navigation property for the claims this user possesses.
/// </summary>
public virtual ICollection<IdentityUserClaim<int>> Claims { get; } = new List<IdentityUserClaim<int>>();

/// <summary>
/// Navigation property for this users login accounts.
/// </summary>
public virtual ICollection<IdentityUserLogin<int>> Logins { get; } = new List<IdentityUserLogin<int>>();

移行の実行中に外部キーが重複EF Coreするには、(呼び出しの後に) クラスの メソッドに次 IdentityDbContext OnModelCreating のコードを追加 base.OnModelCreating(); します。

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<ApplicationUser>()
        .HasMany(e => e.Claims)
        .WithOne()
        .HasForeignKey(e => e.UserId)
        .IsRequired()
        .OnDelete(DeleteBehavior.Cascade);

    builder.Entity<ApplicationUser>()
        .HasMany(e => e.Logins)
        .WithOne()
        .HasForeignKey(e => e.UserId)
        .IsRequired()
        .OnDelete(DeleteBehavior.Cascade);

    builder.Entity<ApplicationUser>()
        .HasMany(e => e.Roles)
        .WithOne()
        .HasForeignKey(e => e.UserId)
        .IsRequired()
        .OnDelete(DeleteBehavior.Cascade);
}

GetExternalAuthenticationSchemes を置き換える

同期メソッドは GetExternalAuthenticationSchemes 、非同期バージョンを使用して削除されました。 1.x プロジェクトには 、Controllers/ManageController.cs の次のコードがあります。

var otherLogins = _signInManager.GetExternalAuthenticationSchemes().Where(auth => userLogins.All(ul => auth.AuthenticationScheme != ul.LoginProvider)).ToList();

このメソッドは Views/Account/Login.cshtml でも表示 されます。

@{
    var loginProviders = SignInManager.GetExternalAuthenticationSchemes().ToList();
    if (loginProviders.Count == 0)
    {
        <div>
            <p>
                There are no external authentication services configured. See <a href="https://go.microsoft.com/fwlink/?LinkID=532715">this article</a>
                for details on setting up this ASP.NET application to support logging in via external services.
            </p>
        </div>
    }
    else
    {
        <form asp-controller="Account" asp-action="ExternalLogin" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal">
            <div>
                <p>
                    @foreach (var provider in loginProviders)
                    {
                        <button type="submit" class="btn btn-default" name="provider" value="@provider.AuthenticationScheme" title="Log in using your @provider.DisplayName account">@provider.AuthenticationScheme</button>
                    }
                </p>
            </div>
        </form>
    }
}

2.0 プロジェクトでは、 メソッドを使用 GetExternalAuthenticationSchemesAsync します。 ManageController.cs の変更は、次のコードのようになります。

var schemes = await _signInManager.GetExternalAuthenticationSchemesAsync();
var otherLogins = schemes.Where(auth => userLogins.All(ul => auth.Name != ul.LoginProvider)).ToList();

Login.cshtml では、 ループ AuthenticationScheme でアクセスされるプロパティが foreach に変わります Name

@{
    var loginProviders = (await SignInManager.GetExternalAuthenticationSchemesAsync()).ToList();
    if (loginProviders.Count == 0)
    {
        <div>
            <p>
                There are no external authentication services configured. See <a href="https://go.microsoft.com/fwlink/?LinkID=532715">this article</a>
                for details on setting up this ASP.NET application to support logging in via external services.
            </p>
        </div>
    }
    else
    {
        <form asp-controller="Account" asp-action="ExternalLogin" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal">
            <div>
                <p>
                    @foreach (var provider in loginProviders)
                    {
                        <button type="submit" class="btn btn-default" name="provider" value="@provider.Name" title="Log in using your @provider.DisplayName account">@provider.DisplayName</button>
                    }
                </p>
            </div>
        </form>
    }
}

ManageLoginsViewModel プロパティの変更

オブジェクト ManageLoginsViewModelManageLogins 、ManageController.cs の アクションで使用されます。 1.x プロジェクトでは、オブジェクトのプロパティの戻り OtherLogins 値の型は です IList<AuthenticationDescription> 。 この戻り値の型には、 のインポートが必要です Microsoft.AspNetCore.Http.Authentication

using System.Collections.Generic;
using Microsoft.AspNetCore.Http.Authentication;
using Microsoft.AspNetCore.Identity;

namespace AspNetCoreDotNetCore1App.Models.ManageViewModels
{
    public class ManageLoginsViewModel
    {
        public IList<UserLoginInfo> CurrentLogins { get; set; }

        public IList<AuthenticationDescription> OtherLogins { get; set; }
    }
}

2.0 プロジェクトでは、戻り値の型は に変わります IList<AuthenticationScheme> 。 この新しい戻り値の型では、インポートを Microsoft.AspNetCore.Http.Authentication インポートに置き換える必要 Microsoft.AspNetCore.Authentication があります。

using System.Collections.Generic;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;

namespace AspNetCoreDotNetCore2App.Models.ManageViewModels
{
    public class ManageLoginsViewModel
    {
        public IList<UserLoginInfo> CurrentLogins { get; set; }

        public IList<AuthenticationScheme> OtherLogins { get; set; }
    }
}

その他のリソース

詳細については、GitHub の 「Auth 2.0 に関する ディスカッション」を参照してください。