自訂.NET Core Identity身份驗證和授權教學:Identity Server With ASP.NET Core Identity 自訂.NET Core Identity身份驗證和授權教學:Identity Server With ASP.NET Core Identity

Published on Tuesday, May 9, 2023

Identity Server With ASP.NET Core Identity

到目前為止 Identity Server 基礎部份都學習過了最後只剩下會員的添加與管理方式,不過要處理這部份需要對 ASP.NET Core Identity 有相當程度的了解, 本系列一開始就有討論過了有需要的可以回去看看

要在 IdentityServer 使用 ASP.NET Core Identity 可以使用預設的範本 isaspid 來建立專案

範本名稱                                                    簡短名稱  語言  標記
----------------------------------------------------------  --------  ----  ------------------
Duende BFF with JavaScript                                  bffjs     [C#]  Web/IdentityServer
Duende IdentityServer Empty                                 isempty   [C#]  Web/IdentityServer
Duende IdentityServer Quickstart UI (UI assets only)        isui      [C#]  Web/IdentityServer
Duende IdentityServer with ASP.NET Core Identity            isaspid   [C#]  Web/IdentityServer
Duende IdentityServer with Entity Framework Stores          isef      [C#]  Web/IdentityServer
Duende IdentityServer with In-Memory Stores and Test Users  isinmem   [C#]  Web/IdentityServer

先建立一個新專案來看看跟我們目前的專案有什麼區別

dotnet new isaspid -n IdentityServerAspNetIdentity
cd ..
dotnet sln add ./src/IdentityServerAspNetIdentity/IdentityServerAspNetIdentity.csproj
  1. 安裝 Package Duende.IdentityServer.AspNetIdentity, Microsoft.AspNetCore.Identity.EntityFrameworkCore, Microsoft.AspNetCore.Identity.UI
  2. wwwroot 與 Pages 資料夾都是 isui 這個範本提供的會幫你在專案添加一些預設頁面
  3. Models 資料夾新建立一個自定義的 IdentityUser 叫做 ApplicationUser
  4. 專案使用 SQLite 並建立了相關檔案
  5. Data 資料夾新建立一個自定義的 IdentityDbContext 叫做 ApplicationDbContext
  6. buildschema.bat 會自動建立遷移腳本並輸出到 Data/Migrations 資料夾
  7. SeedData 內部會使用 UserManager 提供的方法來新增預設會員數據
  8. HostingExtensions 注入並使用 ApplicationDbContext
  9. 額外呼叫 AddAspNetIdentity 方法設定 Identity 相關功能並且呼叫 AddResourceOwnerValidatorAddProfileService

了解後回到原本的 IdentityServer 專案我們來進行實做

首先添加需要用到的 Package

dotnet add package Duende.IdentityServer.AspNetIdentity
dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore
dotnet add package Microsoft.AspNetCore.Identity.UI

建立 DbContext

namespace IdentityServer.Data;

public class AppIdentityDbContext : IdentityDbContext<IdentityUser>
{
    public AppIdentityDbContext(DbContextOptions<AppIdentityDbContext> options) : base(options)
    {
        
    }
}

將 AppIdentityDbContext 註冊到系統內,並且將 AddTestUsers 替換成 AddAspNetIdentity

builder.Services.AddDbContext<AppIdentityDbContext>(options =>
    options.UseNpgsql(connectionIdentity));

builder.Services.AddIdentity<IdentityUser, IdentityRole>()
    .AddDefaultUI()
    .AddDefaultTokenProviders()
    .AddEntityFrameworkStores<AppIdentityDbContext>();
    
builder.Services.AddIdentityServer(options =>
    {
        // https://docs.duendesoftware.com/identityserver/v6/fundamentals/resources/api_scopes#authorization-based-on-scopes
        options.EmitStaticAudienceClaim = true;
    })
    .AddConfigurationStore(options =>
    {
        options.ConfigureDbContext = b => b.UseNpgsql(connectionStringConfigure,
            sql => sql.MigrationsAssembly(migrationsAssembly));
    })
    .AddOperationalStore(options =>
    {
        options.ConfigureDbContext = b => b.UseNpgsql(connectionStringOperational,
            sql => sql.MigrationsAssembly(migrationsAssembly));
    })
    .AddClientStore<ClientStore>()
    .AddAspNetIdentity<IdentityUser>();

因為要使用 Identity UI 我們需要在專案添加 /Views/Shared/_LoginPartial.cshtml 用來顯示右上角 根據登入狀態顯示 Login 或者 Log out,

dotnet new page -np -n _LoginPartial
@if (User.Identity.IsAuthenticated)
{
    <form asp-controller="Account" asp-action="Logout" asp-route-returnUrl="@Url.Action("Index", "Home", new { area = "" })" method="post" id="logoutForm" class="navbar-right">
        <ul class="nav navbar-nav navbar-right">
            <li class="navbar-text">Hello @User.Identity.Name!</li>
            <li>
                <button type="submit" class="btn btn-link navbar-btn navbar-link">Log out</button>
            </li>
        </ul>
    </form>
}
else
{
    <ul class="nav navbar-nav navbar-right">
        <li><a asp-controller="Account" asp-action="Login">Login</a></li>
    </ul>
}

最後建立遷移腳本並且更新資料庫

dotnet ef migrations add InitialIdentityDbMigration -c AppIdentityDbContext -o Data/Migrations/IdentityServer/IdentityDb

dotnet ef database update -c AppIdentityDbContext

完成後運行 Identity Server 與 WebClient 專案進行測試

在瀏覽器打開 https://localhost:5001/identity/account/register 這個是 identity 預設的註冊路徑 註冊完成後打開 https://localhost:5002 會直接透過 Oidc 轉跳到 https://localhost:5001 要求登入, 這時輸入剛剛註冊的帳號可以正常登入並且跳回到 5002 並顯示目前 User 身上擁有的 Claim


Summary

今天成功將 Identity Server 與 ASP.NET Core Identity 兩個技術結合在一起, 至此我們的功能已經可以做到類似 Google 的 Oidc 伺服器的提供的功能了,不過 Identity Server 還有許多設定可以調整 可以按照自己的需求來做設定