2025年10月6日月曜日

【開発】ASP.NET Core Identityを自分のユーザーマスタに組み込む:独自テーブルと連携するやさしい手順

最近、asp.net coreで開発をしていて、改めてその良さがわかったのでまとめたいと思います。

ASP.NET Core Identityは、ログイン機能を“ほぼ自動で”実装してくれる便利な仕組みです。ユーザー登録・パスワード管理・ロックアウト・2段階認証まで、すべて組み込み済みです。

ただし最初につまずくのがここです。

「うちのシステムには、すでに独自の社員マスタ(UserMaster)テーブルがある。
Identityのテーブルとはどうつなげばいいの?」

本記事では、レガシーな「社員マスタ」と、Identityの「認証管理」をきれいに統合する方法を解説します。

---

1. Identityの正体をざっくり理解する

Identityを使うと、自動的に次のようなテーブルが生成されます。

テーブル名役割
AspNetUsersユーザーの基本情報(ID、メール、パスワードハッシュなど)
AspNetRoles権限(Admin, Userなど)
AspNetUserRolesユーザーとロールの紐づけ
AspNetUserClaimsユーザーの属性(メール確認済みなど)

つまり、AspNetUsers が“認証の中心”です。 このテーブルに、あなたのシステム独自の情報(部署、社員番号、権限区分など)を追加すればOKです。

---

2. IdentityUserを継承してカラムを追加する(最も基本的な方法)

最もシンプルなやり方は、IdentityUserを継承したクラスに独自カラムを追加することです。

using Microsoft.AspNetCore.Identity;

public class ApplicationUser : IdentityUser
{
    public string EmployeeCode { get; set; }   // 社員コード
    public string Department { get; set; }     // 部署名
}

DbContextの拡張

using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;

public class AppDbContext : IdentityDbContext<ApplicationUser>
{
    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }

    public DbSet<Product> Products { get; set; }  // 他のテーブルも共存可能
}

Program.cs(またはStartup)で設定

builder.Services.AddIdentity<ApplicationUser, IdentityRole>()
    .AddEntityFrameworkStores<AppDbContext>()
    .AddDefaultTokenProviders();

Migrationで反映

dotnet ef migrations add AddIdentityTables
dotnet ef database update

これで、AspNetUsersに新しい列(EmployeeCode、Department)が追加されます。

---

3. 既存の「UserMaster」テーブルを残したまま、Identityと連携する

public class ApplicationUser : IdentityUser
{
    public int UserMasterId { get; set; }    // 既存テーブルの主キー
    public virtual UserMaster UserMaster { get; set; }
}

DbContextで関連付け

public class AppDbContext : IdentityDbContext<ApplicationUser>
{
    public DbSet<UserMaster> UserMasters { get; set; }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        builder.Entity<ApplicationUser>()
            .HasOne(u => u.UserMaster)
            .WithOne()
            .HasForeignKey<ApplicationUser>(u => u.UserMasterId);
    }
}
---

4. ログイン画面の実装例

public class AccountController : Controller
{
    private readonly SignInManager<ApplicationUser> _signInManager;

    public AccountController(SignInManager<ApplicationUser> signInManager)
    {
        _signInManager = signInManager;
    }

    [HttpPost]
    public async Task<IActionResult> Login(LoginViewModel model)
    {
        var result = await _signInManager.PasswordSignInAsync(
            model.UserName, model.Password, model.RememberMe, lockoutOnFailure: false);

        if (result.Succeeded)
        {
            return RedirectToAction("Index", "Home");
        }

        ModelState.AddModelError("", "ログインに失敗しました。");
        return View(model);
    }
}
---

5. Identity拡張のコツと注意点

項目内容
カラム追加時ApplicationUserに列を追加したら、必ずdotnet ef migrations addを実行
外部キー連携循環参照に注意し、Navigation Propertyを最小限に
既存データ活用IdentityのUserIdと社員コードのマッピング方針を決めておく
---

6. まとめ

ASP.NET Core Identityは「全部作り直し」ではなく、既存のユーザーマスタと共存できる認証エンジンです。

  • パスワードの暗号化・認証管理 → Identityに任せる
  • 社員情報・業務ロジック → 自社マスタで管理

一言で言うと:
Identityは「既存システムの認証エンジンとして使う」のが正解です。