Mengamankan aplikasi ASP.NET Core Blazor WebAssembly yang dihosting dengan Identity Server

Artikel ini menjelaskan cara membuat solusi yang dihosting Blazor WebAssembly yang menggunakan Duende Identity Server untuk mengautentikasi pengguna dan panggilan API.

Penting

Perangkat Lunak Duende mungkin mengharuskan Anda membayar biaya lisensi untuk penggunaan produksi Server Identity Duende. Untuk informasi lebih lanjut, lihat Bermigrasi dari ASP.NET Core 5.0 ke 6.0.

Catatan

Untuk mengonfigurasi aplikasi mandiri atau yang dihosting Blazor WebAssembly untuk menggunakan instans Server eksternal Identity yang sudah ada, ikuti panduan di Mengamankan aplikasi mandiri ASP.NET Core Blazor WebAssembly dengan pustaka Autentikasi.

Untuk cakupan skenario keamanan tambahan setelah membaca artikel ini, lihat skenario keamanan tambahan ASP.NET CoreBlazor WebAssembly.

Panduan

Sub bagian dari panduan menjelaskan cara:

  • Blazor Membuat aplikasi
  • Menjalankan aplikasi

Membuat Blazor aplikasi

Untuk membuat proyek baru Blazor WebAssembly dengan mekanisme autentikasi:

  1. Buat proyek baru.

  2. Blazor WebAssembly Pilih templat Aplikasi. Pilih Selanjutnya.

  3. Berikan Nama proyek tanpa menggunakan tanda hubung. Konfirmasikan bahwa Lokasi sudah benar. Pilih Selanjutnya.

    Hindari menggunakan tanda hubung (-) dalam nama proyek yang merusak pembentukan pengidentifikasi aplikasi OIDC. Logika dalam Blazor WebAssembly templat proyek menggunakan nama proyek untuk pengidentifikasi aplikasi OIDC dalam konfigurasi solusi, dan tanda hubung tidak diizinkan dalam pengidentifikasi aplikasi OIDC. Kasus Pascal (BlazorSample) atau garis bawah (Blazor_Sample) adalah alternatif yang dapat diterima.

  4. Dalam dialog Informasi tambahan, pilih Akun Individual sebagai jenis Autentikasi untuk menyimpan pengguna dalam aplikasi menggunakan sistem ASP.NET CoreIdentity.

  5. Pilih kotak centang ASP.NET Core Hosted .

  6. Pilih tombol Buat untuk membuat aplikasi.

Menjalankan aplikasi

Jalankan aplikasi dari Server proyek. Saat menggunakan Visual Studio, baik:

  • Pilih panah dropdown di samping tombol Jalankan . Buka Konfigurasikan Proyek Startup dari daftar dropdown. Pilih opsi Proyek startup tunggal. Konfirmasi atau ubah proyek untuk proyek startup ke Server proyek.

  • Konfirmasikan bahwa proyek disorot Server di Penjelajah Solusi sebelum Anda memulai aplikasi dengan salah satu pendekatan berikut:

    • Pilih tombol Jalankan.
    • Gunakan Debug>Mulai Debugging dari menu.
    • Tekan F5.
  • Dalam shell perintah, navigasikan ke Server folder proyek solusi. Jalankan perintah dotnet run.

Bagian dari solusi

Bagian ini menjelaskan bagian solusi yang dihasilkan dari Blazor WebAssembly templat proyek dan menjelaskan bagaimana solusi Client dan Server proyek dikonfigurasi untuk referensi. Tidak ada panduan khusus untuk diikuti di bagian ini untuk aplikasi kerja dasar jika Anda membuat aplikasi menggunakan panduan di bagian Penelusuran . Panduan di bagian ini berguna untuk memperbarui aplikasi untuk mengautentikasi dan mengotorisasi pengguna. Namun, pendekatan alternatif untuk memperbarui aplikasi adalah membuat aplikasi baru dari panduan di bagian Penelusuran dan memindahkan komponen, kelas, dan sumber daya aplikasi ke aplikasi baru.

Server layanan aplikasi

Bagian ini berkaitan dengan aplikasi solusi Server .

Layanan berikut terdaftar.

  • Dalam file Program:

    • Entity Framework Core dan ASP.NET Core Identity:

      builder.Services.AddDbContext<ApplicationDbContext>(options =>
          options.UseSqlite( ... ));
      builder.Services.AddDatabaseDeveloperPageExceptionFilter();
      
      builder.Services.AddDefaultIdentity<ApplicationUser>(options => 
              options.SignIn.RequireConfirmedAccount = true)
          .AddEntityFrameworkStores<ApplicationDbContext>();
      
    • IdentityServer dengan metode pembantu Identity tambahan AddApiAuthorization yang menyiapkan konvensi ASP.NET Core default di atas Server:

      builder.Services.AddIdentityServer()
          .AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
      
    • Autentikasi dengan metode pembantu tambahan AddIdentityServerJwt yang mengonfigurasi aplikasi untuk memvalidasi token JWT yang diproduksi oleh Identity Server:

      builder.Services.AddAuthentication()
          .AddIdentityServerJwt();
      
  • Dalam Startup.ConfigureServices dari Startup.cs:

    • Entity Framework Core dan ASP.NET Core Identity:

      services.AddDbContext<ApplicationDbContext>(options =>
          options.UseSqlite(
              Configuration.GetConnectionString("DefaultConnection")));
      
      services.AddDefaultIdentity<ApplicationUser>(options => 
              options.SignIn.RequireConfirmedAccount = true)
          .AddEntityFrameworkStores<ApplicationDbContext>();
      
    • IdentityServer dengan metode pembantu Identity tambahan AddApiAuthorization yang menyiapkan konvensi ASP.NET Core default di atas Server:

      services.AddIdentityServer()
          .AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
      
    • Autentikasi dengan metode pembantu tambahan AddIdentityServerJwt yang mengonfigurasi aplikasi untuk memvalidasi token JWT yang diproduksi oleh Identity Server:

      services.AddAuthentication()
          .AddIdentityServerJwt();
      

Catatan

Ketika skema autentikasi tunggal terdaftar, skema autentikasi secara otomatis digunakan sebagai skema default aplikasi, dan tidak perlu menyatakan skema ke AddAuthentication atau melalui AuthenticationOptions. Untuk informasi selengkapnya, lihat Gambaran Umum Autentikasi Inti ASP.NET dan pengumuman ASP.NET Core (aspnet/Pengumuman #490).

  • Dalam file Program:
  • Dalam Startup.Configure dari Startup.cs:
  • Identity Middleware Server mengekspos titik akhir OpenID Koneksi (OIDC):

    app.UseIdentityServer();
    
  • Middleware Autentikasi bertanggung jawab untuk memvalidasi kredensial permintaan dan mengatur pengguna pada konteks permintaan:

    app.UseAuthentication();
    
  • Middleware otorisasi memungkinkan kemampuan otorisasi:

    app.UseAuthorization();
    

Otorisasi API

Bagian ini berkaitan dengan aplikasi solusi Server .

Metode AddApiAuthorization pembantu Identity mengonfigurasi Server untuk skenario ASP.NET Core. Identity Server adalah kerangka kerja yang kuat dan dapat diperluas untuk menangani masalah keamanan aplikasi. Identity Server mengekspos kompleksitas yang tidak perlu untuk skenario yang paling umum. Akibatnya, serangkaian konvensi dan opsi konfigurasi disediakan yang kami pertimbangkan sebagai titik awal yang baik. Setelah autentikasi Anda perlu berubah, kekuatan Identity penuh Server tersedia untuk menyesuaikan autentikasi agar sesuai dengan persyaratan aplikasi.

Menambahkan handler autentikasi untuk API yang berdampingan dengan Identity Server

Bagian ini berkaitan dengan aplikasi solusi Server .

Metode pembantu AddIdentityServerJwt mengonfigurasi skema kebijakan untuk aplikasi sebagai penangan autentikasi default. Kebijakan dikonfigurasi untuk memungkinkan Identity menangani semua permintaan yang dirutekan ke subpath apa pun di Identity ruang URL di bawah /Identity. Menangani JwtBearerHandler semua permintaan lainnya. Selain itu, metode ini:

  • Mendaftarkan sumber daya API dengan Identity Server dengan cakupan {PROJECT NAME}APIdefault , di mana {PROJECT NAME} tempat penampung adalah nama proyek pada pembuatan aplikasi.
  • Mengonfigurasi Middleware Token Pembawa JWT untuk memvalidasi token yang dikeluarkan oleh Identity Server untuk aplikasi.

Pengontrol prakiraan cuaca

Bagian ini berkaitan dengan aplikasi solusi Server .

WeatherForecastController Di (Controllers/WeatherForecastController.cs), [Authorize] atribut diterapkan ke kelas . Atribut menunjukkan bahwa pengguna harus diotorisasi berdasarkan kebijakan default untuk mengakses sumber daya. Kebijakan otorisasi default dikonfigurasi untuk menggunakan skema autentikasi default, yang disiapkan oleh AddIdentityServerJwt. Metode pembantu mengonfigurasi JwtBearerHandler sebagai handler default untuk permintaan ke aplikasi.

Konteks database aplikasi

Bagian ini berkaitan dengan aplikasi solusi Server .

ApplicationDbContext Dalam (Data/ApplicationDbContext.cs), DbContext meluas ApiAuthorizationDbContext<TUser> untuk menyertakan skema untuk Identity Server. ApiAuthorizationDbContext<TUser> berasal dari IdentityDbContext.

Untuk mendapatkan kontrol penuh atas skema database, warisi dari salah satu kelas yang tersedia IdentityDbContext dan konfigurasikan konteks untuk menyertakan Identity skema dengan memanggil builder.ConfigurePersistedGrantContext(_operationalStoreOptions.Value) dalam OnModelCreating metode .

Pengontrol konfigurasi OIDC

Bagian ini berkaitan dengan aplikasi solusi Server .

OidcConfigurationController Di (Controllers/OidcConfigurationController.cs), titik akhir klien disediakan untuk melayani parameter OIDC.

Pengaturan aplikasi

Bagian ini berkaitan dengan aplikasi solusi Server .

Dalam file pengaturan aplikasi (appsettings.json) di akar proyek, bagian menjelaskan IdentityServer daftar klien yang dikonfigurasi. Dalam contoh berikut, ada satu klien. Nama klien sesuai dengan Client nama rakitan aplikasi dan dipetakan berdasarkan konvensi ke parameter OAuth ClientId . Profil menunjukkan jenis aplikasi yang sedang dikonfigurasi. Profil digunakan secara internal untuk mendorong konvensi yang menyederhanakan proses konfigurasi untuk server.

"IdentityServer": {
  "Clients": {
    "{ASSEMBLY NAME}": {
      "Profile": "IdentityServerSPA"
    }
  }
}

Tempat penampung {ASSEMBLY NAME} adalah Client nama rakitan aplikasi (misalnya, BlazorSample.Client).

Paket autentikasi

Bagian ini berkaitan dengan aplikasi solusi Client .

Saat aplikasi dibuat untuk menggunakan Akun Pengguna Individual (Individual), aplikasi secara otomatis menerima referensi paket untuk paket tersebut Microsoft.AspNetCore.Components.WebAssembly.Authentication . Paket ini menyediakan sekumpulan primitif yang membantu aplikasi mengautentikasi pengguna dan mendapatkan token untuk memanggil API yang dilindungi.

Jika menambahkan autentikasi ke aplikasi, tambahkan Microsoft.AspNetCore.Components.WebAssembly.Authentication paket secara manual ke aplikasi.

Catatan

Untuk panduan tentang menambahkan paket ke aplikasi .NET, lihat artikel di bagian Menginstal dan mengelola paket di Alur kerja konsumsi paket (dokumentasi NuGet). Konfirmasikan versi paket yang benar di NuGet.org.

HttpClient konfigurasi

Bagian ini berkaitan dengan aplikasi solusi Client .

Program Dalam file, nama HttpClient dikonfigurasi untuk menyediakan HttpClient instans yang menyertakan token akses saat membuat permintaan ke API server. Secara default pada pembuatan solusi, yang bernama HttpClient adalah {PROJECT NAME}.ServerAPI, di mana {PROJECT NAME} tempat penampung adalah nama proyek.

builder.Services.AddHttpClient("{PROJECT NAME}.ServerAPI", 
        client => client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress))
    .AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();

builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>()
    .CreateClient("{PROJECT NAME}.ServerAPI"));

Tempat penampung {PROJECT NAME} adalah nama proyek pada pembuatan solusi. Misalnya, memberikan nama BlazorSample proyek menghasilkan nama HttpClientBlazorSample.ServerAPI.

Catatan

Jika Anda mengonfigurasi aplikasi untuk menggunakan instans Server yang ada yang bukan bagian dari solusi yang dihosting Blazor WebAssemblyIdentityBlazor , ubah HttpClient pendaftaran alamat dasar dari IWebAssemblyHostEnvironment.BaseAddress (builder.HostEnvironment.BaseAddress) ke URL titik akhir otorisasi API aplikasi server.

Dukungan otorisasi API

Bagian ini berkaitan dengan aplikasi solusi Client .

Dukungan untuk mengautentikasi pengguna dicolokkan ke kontainer layanan dengan metode ekstensi yang disediakan di dalam Microsoft.AspNetCore.Components.WebAssembly.Authentication paket. Metode ini menyiapkan layanan yang diperlukan oleh aplikasi untuk berinteraksi dengan sistem otorisasi yang ada.

builder.Services.AddApiAuthorization();

Secara default, konfigurasi untuk aplikasi dimuat berdasarkan konvensi dari _configuration/{client-id}. Menurut konvensi, ID klien diatur ke nama rakitan aplikasi. URL ini dapat diubah untuk menunjuk ke titik akhir terpisah dengan memanggil kelebihan beban dengan opsi.

File Imports

Bagian ini berkaitan dengan aplikasi solusi Client .

Namespace Microsoft.AspNetCore.Components.Authorization tersedia di seluruh aplikasi melalui _Imports.razor file:

@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.JSInterop
@using {APPLICATION ASSEMBLY}
@using {APPLICATION ASSEMBLY}.Shared

Index Halaman

Bagian ini berkaitan dengan aplikasi solusi Client .

Halaman Indeks (wwwroot/index.html) menyertakan skrip yang menentukan AuthenticationService di JavaScript. AuthenticationService menangani detail tingkat rendah protokol OIDC. Aplikasi secara internal memanggil metode yang ditentukan dalam skrip untuk melakukan operasi autentikasi.

<script src="_content/Microsoft.AspNetCore.Components.WebAssembly.Authentication/AuthenticationService.js"></script>

App komponen

Bagian ini berkaitan dengan aplikasi solusi Client .

Komponen App (App.razor) mirip dengan komponen yang App ditemukan di Blazor Server aplikasi:

  • Komponen CascadingAuthenticationState mengelola mengekspos AuthenticationState ke aplikasi lainnya.
  • Komponen AuthorizeRouteView memastikan bahwa pengguna saat ini berwenang untuk mengakses halaman tertentu atau merender RedirectToLogin komponen.
  • Komponen RedirectToLogin mengelola pengalihan pengguna yang tidak sah ke halaman masuk.

Karena perubahan dalam kerangka kerja di seluruh rilis ASP.NET Core, Razor markup untuk App komponen (App.razor) tidak ditampilkan di bagian ini. Untuk memeriksa markup komponen untuk rilis tertentu, gunakan salah satu pendekatan berikut:

  • Buat aplikasi yang disediakan untuk autentikasi dari templat proyek default Blazor WebAssembly untuk versi ASP.NET Core yang ingin Anda gunakan. App Periksa komponen (App.razor) di aplikasi yang dihasilkan.

  • App Periksa komponen (App.razor) di sumber referensi. Pilih versi dari pemilih cabang, dan cari komponen di ProjectTemplates folder repositori karena telah dipindahkan selama bertahun-tahun.

    Catatan

    Tautan dokumentasi ke sumber referensi .NET biasanya memuat cabang default repositori, yang mewakili pengembangan saat ini untuk rilis .NET berikutnya. Untuk memilih tag rilis tertentu, gunakan daftar dropdown Beralih cabang atau tag. Untuk informasi lebih lanjut, lihat Cara memilih tag versi kode sumber ASP.NET Core (dotnet/AspNetCore.Docs #26205).

RedirectToLogin komponen

Bagian ini berkaitan dengan aplikasi solusi Client .

Komponen RedirectToLogin (RedirectToLogin.razor):

  • Mengelola pengalihan pengguna yang tidak sah ke halaman masuk.
  • URL saat ini yang coba diakses pengguna dipertahankan oleh sehingga mereka dapat dikembalikan ke halaman tersebut jika autentikasi berhasil menggunakan:
    • Status riwayat navigasi di ASP.NET Core di .NET 7 atau yang lebih baru.
    • String kueri di ASP.NET Core di .NET 6 atau yang lebih lama.

RedirectToLogin Periksa komponen dalam sumber referensi. Lokasi komponen berubah dari waktu ke waktu, jadi gunakan alat pencarian GitHub untuk menemukan komponen.

Catatan

Tautan dokumentasi ke sumber referensi .NET biasanya memuat cabang default repositori, yang mewakili pengembangan saat ini untuk rilis .NET berikutnya. Untuk memilih tag rilis tertentu, gunakan daftar dropdown Beralih cabang atau tag. Untuk informasi lebih lanjut, lihat Cara memilih tag versi kode sumber ASP.NET Core (dotnet/AspNetCore.Docs #26205).

LoginDisplay komponen

Bagian ini berkaitan dengan aplikasi solusi Client .

Komponen LoginDisplay (LoginDisplay.razor) dirender dalam MainLayout komponen (MainLayout.razor) dan mengelola perilaku berikut:

  • Untuk pengguna terautentikasi:
    • Menampilkan nama pengguna saat ini.
    • Menawarkan tautan ke halaman profil pengguna di ASP.NET Core Identity.
    • Menawarkan tombol untuk keluar dari aplikasi.
  • Untuk pengguna anonim:
    • Menawarkan opsi untuk mendaftar.
    • Menawarkan opsi untuk masuk.

Karena perubahan dalam kerangka kerja di seluruh rilis ASP.NET Core, Razor markup untuk LoginDisplay komponen tidak ditampilkan di bagian ini. Untuk memeriksa markup komponen untuk rilis tertentu, gunakan salah satu pendekatan berikut:

  • Buat aplikasi yang disediakan untuk autentikasi dari templat proyek default Blazor WebAssembly untuk versi ASP.NET Core yang ingin Anda gunakan. LoginDisplay Periksa komponen di aplikasi yang dihasilkan.

  • LoginDisplay Periksa komponen dalam sumber referensi. Lokasi komponen berubah dari waktu ke waktu, jadi gunakan alat pencarian GitHub untuk menemukan komponen. Konten templat untuk Hosted sama dengan true yang digunakan.

    Catatan

    Tautan dokumentasi ke sumber referensi .NET biasanya memuat cabang default repositori, yang mewakili pengembangan saat ini untuk rilis .NET berikutnya. Untuk memilih tag rilis tertentu, gunakan daftar dropdown Beralih cabang atau tag. Untuk informasi lebih lanjut, lihat Cara memilih tag versi kode sumber ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Authentication komponen

Bagian ini berkaitan dengan aplikasi solusi Client .

Halaman yang dihasilkan oleh Authentication komponen (Pages/Authentication.razor) menentukan rute yang diperlukan untuk menangani tahap autentikasi yang berbeda.

Komponen RemoteAuthenticatorView :

@page "/authentication/{action}"
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication

<RemoteAuthenticatorView Action="Action" />

@code {
    [Parameter]
    public string? Action { get; set; }
}

Catatan

Jenis referensi nullable (NRTs) dan .NET compiler null-state static analysis didukung di ASP.NET Core di .NET 6 atau yang lebih baru. Sebelum rilis ASP.NET Core di .NET 6, string jenis muncul tanpa penunjukan jenis null (?).

FetchData komponen

Bagian ini berkaitan dengan aplikasi solusi Client .

Komponen FetchData menunjukkan cara:

  • Menyediakan token akses.
  • Gunakan token akses untuk memanggil API sumber daya yang dilindungi di aplikasi Server .

Arahan @attribute [Authorize] menunjukkan sistem Blazor WebAssembly otorisasi bahwa pengguna harus diotorisasi untuk mengunjungi komponen ini. Kehadiran atribut di Client aplikasi tidak mencegah API di server dipanggil tanpa kredensial yang tepat. Aplikasi ini Server juga harus digunakan [Authorize] pada titik akhir yang sesuai untuk melindunginya dengan benar.

IAccessTokenProvider.RequestAccessToken mengurus permintaan token akses yang dapat ditambahkan ke permintaan untuk memanggil API. Jika token di-cache atau layanan dapat menyediakan token akses baru tanpa interaksi pengguna, permintaan token berhasil. Jika tidak, permintaan token gagal dengan AccessTokenNotAvailableException, yang tertangkap dalam try-catch pernyataan.

Untuk mendapatkan token aktual untuk disertakan dalam permintaan, aplikasi harus memeriksa apakah permintaan berhasil dengan memanggil tokenResult.TryGetToken(out var token).

Jika permintaan berhasil, variabel token diisi dengan token akses. Properti AccessToken.Value token mengekspos string harfiah untuk disertakan Authorization dalam header permintaan.

Jika permintaan gagal karena token tidak dapat disediakan tanpa interaksi pengguna:

  • ASP.NET Core di .NET 7 atau yang lebih baru: Aplikasi menavigasi untuk AccessTokenResult.InteractiveRequestUrl menggunakan yang diberikan AccessTokenResult.InteractionOptions untuk memungkinkan refresh token akses.
  • ASP.NET Core di .NET 6 atau yang lebih lama: Hasil token berisi URL pengalihan. Menavigasi ke URL ini membawa pengguna ke halaman masuk dan kembali ke halaman saat ini setelah autentikasi berhasil.
@page "/fetchdata"
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using {APP NAMESPACE}.Shared
@attribute [Authorize]
@inject HttpClient Http

...

@code {
    private WeatherForecast[] forecasts;

    protected override async Task OnInitializedAsync()
    {
        try
        {
            forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast");
        }
        catch (AccessTokenNotAvailableException exception)
        {
            exception.Redirect();
        }
    }
}

Azure App Service di Linux

Tentukan pengeluar sertifikat secara eksplisit saat menyebarkan ke Azure App Service di Linux. Untuk informasi selengkapnya, lihat Menggunakan Identity untuk mengamankan backend API Web untuk SPAs.

Klaim nama dan peran dengan otorisasi API

Pabrik pengguna kustom

Client Di aplikasi, buat pabrik pengguna kustom. Identity Server mengirim beberapa peran sebagai JSarray ON dalam satu role klaim. Satu peran dikirim sebagai nilai string dalam klaim. Pabrik membuat klaim individual role untuk setiap peran pengguna.

CustomUserFactory.cs:

using System.Security.Claims;
using System.Text.Json;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication.Internal;

public class CustomUserFactory
    : AccountClaimsPrincipalFactory<RemoteUserAccount>
{
    public CustomUserFactory(IAccessTokenProviderAccessor accessor)
        : base(accessor)
    {
    }

    public override async ValueTask<ClaimsPrincipal> CreateUserAsync(
        RemoteUserAccount account,
        RemoteAuthenticationUserOptions options)
    {
        var user = await base.CreateUserAsync(account, options);

        if (user.Identity is not null && user.Identity.IsAuthenticated)
        {
            var identity = (ClaimsIdentity)user.Identity;
            var roleClaims = identity.FindAll(identity.RoleClaimType).ToArray();

            if (roleClaims.Any())
            {
                foreach (var existingClaim in roleClaims)
                {
                    identity.RemoveClaim(existingClaim);
                }

                var rolesElem = 
                    account.AdditionalProperties[identity.RoleClaimType];

                if (options.RoleClaim is not null && rolesElem is JsonElement roles)
                {
                    if (roles.ValueKind == JsonValueKind.Array)
                    {
                        foreach (var role in roles.EnumerateArray())
                        {
                            var roleValue = role.GetString();

                            if (!string.IsNullOrEmpty(roleValue))
                            {
                                identity.AddClaim(
                                  new Claim(options.RoleClaim, roleValue));
                            }

                        }
                    }
                    else
                    {
                        var roleValue = roles.GetString();

                        if (!string.IsNullOrEmpty(roleValue))
                        {
                            identity.AddClaim(
                              new Claim(options.RoleClaim, roleValue));
                        }
                    }
                }
            }
        }

        return user;
    }
}
using System.Linq;
using System.Security.Claims;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication.Internal;

public class CustomUserFactory
    : AccountClaimsPrincipalFactory<RemoteUserAccount>
{
    public CustomUserFactory(IAccessTokenProviderAccessor accessor)
        : base(accessor)
    {
    }

    public override async ValueTask<ClaimsPrincipal> CreateUserAsync(
        RemoteUserAccount account,
        RemoteAuthenticationUserOptions options)
    {
        var user = await base.CreateUserAsync(account, options);

        if (user.Identity.IsAuthenticated)
        {
            var identity = (ClaimsIdentity)user.Identity;
            var roleClaims = identity.FindAll(identity.RoleClaimType).ToArray();

            if (roleClaims.Any())
            {
                foreach (var existingClaim in roleClaims)
                {
                    identity.RemoveClaim(existingClaim);
                }

                var rolesElem = account.AdditionalProperties[identity.RoleClaimType];

                if (rolesElem is JsonElement roles)
                {
                    if (roles.ValueKind == JsonValueKind.Array)
                    {
                        foreach (var role in roles.EnumerateArray())
                        {
                            identity.AddClaim(new Claim(options.RoleClaim, role.GetString()));
                        }
                    }
                    else
                    {
                        identity.AddClaim(new Claim(options.RoleClaim, roles.GetString()));
                    }
                }
            }
        }

        return user;
    }
}

Client Di aplikasi, daftarkan pabrik dalam Program file:

builder.Services.AddApiAuthorization()
    .AddAccountClaimsPrincipalFactory<CustomUserFactory>();

Server Di aplikasi, panggil AddRoles penyusunIdentity, yang menambahkan layanan terkait peran.

Dalam file Program:

using Microsoft.AspNetCore.Identity;

...

builder.Services.AddDefaultIdentity<ApplicationUser>(options => 
    options.SignIn.RequireConfirmedAccount = true)
    .AddRoles<IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>();

Di Startup.cs:

using Microsoft.AspNetCore.Identity;

...

services.AddDefaultIdentity<ApplicationUser>(options => 
    options.SignIn.RequireConfirmedAccount = true)
    .AddRoles<IdentityRole>()
    .AddEntityFrameworkStores<ApplicationDbContext>();

Mengonfigurasi Identity Server

Gunakan salah satu pendekatan berikut:

Opsi otorisasi API

Server Di aplikasi:

  • Konfigurasikan Identity Server untuk memasukkan name klaim dan role ke dalam token ID dan token akses.
  • Cegah pemetaan default untuk peran di handler token JWT.

Dalam file Program:

using System.IdentityModel.Tokens.Jwt;

...

builder.Services.AddIdentityServer()
    .AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options => {
        options.IdentityResources["openid"].UserClaims.Add("name");
        options.ApiResources.Single().UserClaims.Add("name");
        options.IdentityResources["openid"].UserClaims.Add("role");
        options.ApiResources.Single().UserClaims.Add("role");
    });

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("role");

Di Startup.cs:

using System.IdentityModel.Tokens.Jwt;
using System.Linq;

...

services.AddIdentityServer()
    .AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options => {
        options.IdentityResources["openid"].UserClaims.Add("name");
        options.ApiResources.Single().UserClaims.Add("name");
        options.IdentityResources["openid"].UserClaims.Add("role");
        options.ApiResources.Single().UserClaims.Add("role");
    });

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("role");

Layanan Profil

Server Di aplikasi, buat ProfileService implementasi.

ProfileService.cs:

using IdentityModel;
using Duende.IdentityServer.Models;
using Duende.IdentityServer.Services;

public class ProfileService : IProfileService
{
    public ProfileService()
    {
    }

    public async Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        var nameClaim = context.Subject.FindAll(JwtClaimTypes.Name);
        context.IssuedClaims.AddRange(nameClaim);

        var roleClaims = context.Subject.FindAll(JwtClaimTypes.Role);
        context.IssuedClaims.AddRange(roleClaims);

        await Task.CompletedTask;
    }

    public async Task IsActiveAsync(IsActiveContext context)
    {
        await Task.CompletedTask;
    }
}
using IdentityModel;
using Duende.IdentityServer.Models;
using Duende.IdentityServer.Services;
using System.Threading.Tasks;

public class ProfileService : IProfileService
{
    public ProfileService()
    {
    }

    public async Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        var nameClaim = context.Subject.FindAll(JwtClaimTypes.Name);
        context.IssuedClaims.AddRange(nameClaim);

        var roleClaims = context.Subject.FindAll(JwtClaimTypes.Role);
        context.IssuedClaims.AddRange(roleClaims);

        await Task.CompletedTask;
    }

    public async Task IsActiveAsync(IsActiveContext context)
    {
        await Task.CompletedTask;
    }
}

Server Di aplikasi, daftarkan Layanan Profil dalam Program file:

using Duende.IdentityServer.Services;

...

builder.Services.AddTransient<IProfileService, ProfileService>();

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("role");

Server Di aplikasi, daftarkan Layanan Profil di Startup.ConfigureServices dari Startup.cs:

using IdentityServer4.Services;

...

services.AddTransient<IProfileService, ProfileService>();

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("role");

Menggunakan mekanisme otorisasi

Client Di aplikasi, pendekatan otorisasi komponen berfungsi pada saat ini. Salah satu mekanisme otorisasi dalam komponen dapat menggunakan peran untuk mengotorisasi pengguna:

User.Identity.Name diisi di Client aplikasi dengan nama pengguna pengguna, yang biasanya merupakan alamat email masuk mereka.

UserManager dan SignInManager

Atur jenis klaim pengidentifikasi pengguna saat aplikasi Server memerlukan:

In Program.cs untuk ASP.NET Core di .NET 6 atau yang lebih baru:

using System.Security.Claims;

...

builder.Services.Configure<IdentityOptions>(options => 
    options.ClaimsIdentity.UserIdClaimType = ClaimTypes.NameIdentifier);

Di Startup.ConfigureServices untuk versi ASP.NET Core yang lebih lama dari 6.0:

using System.Security.Claims;

...

services.Configure<IdentityOptions>(options => 
    options.ClaimsIdentity.UserIdClaimType = ClaimTypes.NameIdentifier);

Berikut ini WeatherForecastController mencatat UserName kapan metode dipanggil Get .

Catatan

Contoh berikut menggunakan namespace cakupan file, yang merupakan fitur C# 10 atau yang lebih baru (.NET 6 atau yang lebih baru).

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Logging;
using BlazorSample.Server.Models;
using BlazorSample.Shared;

namespace BlazorSample.Server.Controllers;

[Authorize]
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    private readonly UserManager<ApplicationUser> userManager;

    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", 
        "Balmy", "Hot", "Sweltering", "Scorching"
    };

    private readonly ILogger<WeatherForecastController> logger;

    public WeatherForecastController(ILogger<WeatherForecastController> logger, 
        UserManager<ApplicationUser> userManager)
    {
        this.logger = logger;
        this.userManager = userManager;
    }

    [HttpGet]
    public async Task<IEnumerable<WeatherForecast>> Get()
    {
        var rng = new Random();

        var user = await userManager.GetUserAsync(User);

        if (user != null)
        {
            logger.LogInformation("User.Identity.Name: {UserIdentityName}", user.UserName);
        }

        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = rng.Next(-20, 55),
            Summary = Summaries[rng.Next(Summaries.Length)]
        })
        .ToArray();
    }
}

Dalam contoh sebelumnya:

  • Namespace Server proyek adalah BlazorSample.Server.
  • Namespace Shared proyek adalah BlazorSample.Shared.

Host di Azure App Service dengan domain dan sertifikat kustom

Panduan berikut menjelaskan:

  • Cara menyebarkan aplikasi yang dihosting Blazor WebAssembly dengan Server ke Azure App ServiceIdentity dengan domain kustom.
  • Cara membuat dan menggunakan sertifikat TLS untuk komunikasi protokol HTTPS dengan browser. Meskipun panduan berfokus pada penggunaan sertifikat dengan domain kustom, panduan ini sama-sama berlaku untuk menggunakan domain Azure Apps default, misalnya contoso.azurewebsites.net.

Untuk skenario hosting ini, jangan gunakan sertifikat yang sama untuk Identity kunci penandatanganan token Server dan komunikasi aman HTTPS situs dengan browser:

  • Menggunakan sertifikat yang berbeda untuk kedua persyaratan ini adalah praktik keamanan yang baik karena mengisolasi kunci privat untuk setiap tujuan.
  • Sertifikat TLS untuk komunikasi dengan browser dikelola secara independen tanpa memengaruhi penandatanganan Identity token Server.
  • Saat Azure Key Vault menyediakan sertifikat ke aplikasi App Service untuk pengikatan domain kustom, Identity Server tidak dapat memperoleh sertifikat yang sama dari Azure Key Vault untuk penandatanganan token. Meskipun mengonfigurasi Identity Server untuk menggunakan sertifikat TLS yang sama dari jalur fisik dimungkinkan, menempatkan sertifikat keamanan ke dalam kontrol sumber adalah praktik yang buruk dan harus dihindari dalam sebagian besar skenario.

Dalam panduan berikut, sertifikat yang ditandatangani sendiri dibuat di Azure Key Vault hanya untuk Identity penandatanganan token Server. Konfigurasi Identity Server menggunakan sertifikat brankas kunci melalui penyimpanan sertifikat aplikasi>CurrentUserMy. Sertifikat lain yang digunakan untuk lalu lintas HTTPS dengan domain kustom dibuat dan dikonfigurasi secara terpisah dari Identity sertifikat penandatanganan Server.

Untuk mengonfigurasi aplikasi, Azure App Service, dan Azure Key Vault untuk dihosting dengan domain kustom dan HTTPS:

  1. Buat paket App Service dengan tingkat Basic B1 paket atau yang lebih tinggi. App Service memerlukan Basic B1 tingkat layanan atau lebih tinggi untuk menggunakan domain kustom.

  2. Buat sertifikat PFX untuk komunikasi browser aman situs (protokol HTTPS) dengan nama umum nama domain situs yang sepenuhnya memenuhi syarat (FQDN) yang dikontrol organisasi Anda (misalnya, www.contoso.com). Buat sertifikat dengan:

    • Penggunaan kunci
      • Validasi tanda tangan digital (digitalSignature)
      • Encipherment kunci (keyEncipherment)
    • Penggunaan kunci yang ditingkatkan/diperluas
      • Autentikasi Klien (1.3.6.1.5.5.7.3.2)
      • Autentikasi Server (1.3.6.1.5.5.7.3.1)

    Untuk membuat sertifikat, gunakan salah satu pendekatan berikut atau alat atau layanan online lain yang sesuai:

    Catat kata sandi, yang digunakan nanti untuk mengimpor sertifikat ke Azure Key Vault.

    Untuk informasi selengkapnya tentang sertifikat Azure Key Vault, lihat Azure Key Vault: Sertifikat.

  3. Buat Azure Key Vault baru atau gunakan brankas kunci yang sudah ada di langganan Azure Anda.

  4. Di area Sertifikat brankas kunci, impor sertifikat situs PFX. Rekam thumbprint sertifikat, yang digunakan dalam konfigurasi aplikasi nanti.

  5. Di Azure Key Vault, buat sertifikat baru yang ditandatangani sendiri untuk Identity penandatanganan token Server. Beri sertifikat Nama Sertifikat dan Subjek. Subjek ditentukan sebagai CN={COMMON NAME}, di mana {COMMON NAME} tempat penampung adalah nama umum sertifikat. Nama umum dapat berupa string alfanumerik apa pun. Misalnya, CN=IdentityServerSigning adalah Subjek sertifikat yang valid. Dalam Konfigurasi Kebijakan>Penerbitan Kebijakan Lanjutan, gunakan pengaturan default. Rekam thumbprint sertifikat, yang digunakan dalam konfigurasi aplikasi nanti.

  6. Navigasi ke Azure App Service di portal Azure dan buat App Service baru dengan konfigurasi berikut:

    • Terbitkan diatur ke Code.
    • Tumpukan runtime diatur ke runtime aplikasi.
    • Untuk Sku dan ukuran, konfirmasikan bahwa tingkat App Service atau Basic B1 lebih tinggi. App Service memerlukan Basic B1 tingkat layanan atau lebih tinggi untuk menggunakan domain kustom.
  7. Setelah Azure membuat App Service, buka Konfigurasi aplikasi dan tambahkan pengaturan aplikasi baru yang menentukan thumbprint sertifikat yang direkam sebelumnya. Kunci pengaturan aplikasi adalah WEBSITE_LOAD_CERTIFICATES. Pisahkan thumbprint sertifikat dalam nilai pengaturan aplikasi dengan koma, seperti yang ditunjukkan contoh berikut:

    • Kunci: WEBSITE_LOAD_CERTIFICATES
    • Nilai: 57443A552A46DB...D55E28D412B943565,29F43A772CB6AF...1D04F0C67F85FB0B1

    Di portal Azure, menyimpan pengaturan aplikasi adalah proses dua langkah: Simpan WEBSITE_LOAD_CERTIFICATES pengaturan kunci-nilai, lalu pilih tombol Simpan di bagian atas bilah.

  8. Pilih pengaturan TLS/SSL aplikasi. Pilih Sertifikat Kunci Privat (.pfx). Gunakan proses Impor Sertifikat Key Vault. Gunakan proses dua kali untuk mengimpor sertifikat situs untuk komunikasi HTTPS dan sertifikat penandatanganan token Server yang ditandatangani Identity sendiri.

  9. Navigasikan ke bilah Domain kustom. Di situs web pencatat domain Anda, gunakan alamat IP dan ID Verifikasi Domain Kustom untuk mengonfigurasi domain. Konfigurasi domain umum meliputi:

    • Rekaman A dengan Host@ dan nilai alamat IP dari portal Azure.
    • Catatan TXT dengan Host dan asuid nilai ID verifikasi yang dihasilkan oleh Azure dan disediakan oleh portal Azure.

    Pastikan Anda menyimpan perubahan di situs web pencatat domain Anda dengan benar. Beberapa situs web pencatat memerlukan proses dua langkah untuk menyimpan rekaman domain: Satu atau beberapa rekaman disimpan satu per satu diikuti dengan memperbarui pendaftaran domain dengan tombol terpisah.

  10. Kembali ke bilah Domain kustom di portal Azure. Pilih Tambahkan domain kustom. Pilih opsi Rekaman A. Berikan domain dan pilih Validasi. Jika rekaman domain sudah benar dan disebarluaskan di internet, portal memungkinkan Anda memilih tombol Tambahkan domain kustom.

    Diperlukan waktu beberapa hari agar perubahan pendaftaran domain disebarluaskan di seluruh server nama domain Internet (DNS) setelah diproses oleh pencatat domain Anda. Jika catatan domain tidak diperbarui dalam waktu tiga hari kerja, konfirmasikan catatan diatur dengan benar dengan pencatat domain dan hubungi dukungan pelanggan mereka.

  11. Di bilah Domain kustom, STATUS SSL untuk domain ditandai Not Secure. Pilih tautan Tambahkan pengikatan . Pilih sertifikat HTTPS situs dari brankas kunci untuk pengikatan domain kustom.

  12. Di Visual Studio, buka file pengaturan aplikasi proyek Server (appsettings.json atau appsettings.Production.json). Identity Di konfigurasi Server, tambahkan bagian berikutKey. Tentukan Subjek sertifikat yang ditandatangani sendiri untuk kunci.Name Dalam contoh berikut, nama umum sertifikat yang ditetapkan dalam brankas kunci adalah IdentityServerSigning, yang menghasilkan Subjek :CN=IdentityServerSigning

    "IdentityServer": {
    
      ...
    
      "Key": {
        "Type": "Store",
        "StoreName": "My",
        "StoreLocation": "CurrentUser",
        "Name": "CN=IdentityServerSigning"
      }
    },
    
  13. Di Visual Studio, buat profil penerbitan Azure App Service untuk proyek Server. Dari bilah menu, pilih: Bangun>Terbitkan>Azure>App Service Baru>(Windows atau Linux). Saat Visual Studio tersambung ke langganan Azure, Anda dapat mengatur Tampilan sumber daya Azure menurut jenis Sumber Daya. Navigasikan dalam daftar Aplikasi Web untuk menemukan App Service untuk aplikasi dan memilihnya. Pilih Selesai.

  14. Saat Visual Studio kembali ke jendela Terbitkan , dependensi layanan database brankas kunci dan SQL Server terdeteksi secara otomatis.

    Tidak ada perubahan konfigurasi pada pengaturan default yang diperlukan untuk layanan brankas kunci.

    Untuk tujuan pengujian, database SQLite lokal aplikasi, yang dikonfigurasi secara default oleh Blazor templat, dapat disebarkan dengan aplikasi tanpa konfigurasi tambahan. Mengonfigurasi database yang berbeda untuk Identity Server dalam produksi berada di luar cakupan artikel ini. Untuk informasi selengkapnya, lihat sumber daya database dalam kumpulan dokumentasi berikut ini:

  15. Pilih tautan Edit di bawah nama profil penyebaran di bagian atas jendela. Ubah URL tujuan ke URL domain kustom situs (misalnya, https://www.contoso.com). Simpan pengaturan.

  16. Memublikasikan aplikasi. Visual Studio membuka jendela browser dan meminta situs di domain kustomnya.

Dokumentasi Azure berisi detail tambahan tentang menggunakan layanan Azure dan domain kustom dengan pengikatan TLS di App Service, termasuk informasi tentang menggunakan catatan CNAME alih-alih catatan A. Untuk informasi selengkapnya, lihat sumber daya berikut:

Sebaiknya gunakan jendela browser mode privat baru (misalnya, mode Microsoft Edge InPrivate atau mode Google Chrome Incognito) untuk setiap pengujian aplikasi yang dijalankan setelah perubahan pada aplikasi, konfigurasi aplikasi, atau layanan Azure di portal Azure. Bertahan cookiedari eksekusi pengujian sebelumnya dapat mengakibatkan autentikasi atau otorisasi yang gagal saat menguji situs bahkan ketika konfigurasi situs sudah benar. Untuk informasi selengkapnya tentang cara mengonfigurasi Visual Studio untuk membuka jendela browser privat baru untuk setiap eksekusi pengujian, lihat Cookiebagian data situs dan s.

Saat konfigurasi App Service diubah dalam portal Azure, pembaruan umumnya berlaku dengan cepat tetapi tidak instan. Terkadang, Anda harus menunggu beberapa saat agar App Service dimulai ulang agar perubahan konfigurasi berlaku.

Jika memecahkan masalah Identity pemuatan sertifikat penandatanganan kunci Server, jalankan perintah berikut dalam shell perintah Kudu PowerShell portal Azure. Perintah ini menyediakan daftar sertifikat yang dapat diakses aplikasi dari penyimpanan CurrentUser>My sertifikat. Output mencakup subjek sertifikat dan thumbprint yang berguna saat men-debug aplikasi:

Get-ChildItem -path Cert:\CurrentUser\My -Recurse | Format-List DnsNameList, Subject, Thumbprint, EnhancedKeyUsageList

Pemecahan masalah

Pencatatan

Untuk mengaktifkan pencatatan log debug atau pelacakan untuk Blazor WebAssembly autentikasi, lihat bagian Pengelogan autentikasi sisi klien ASP.NET Pengelogan core Blazor dengan pemilih versi artikel diatur ke ASP.NET Core 7.0 atau yang lebih baru.

Kesalahan umum

  • Kesalahan konfigurasi aplikasi atau Identity Penyedia (IP)

    Kesalahan yang paling umum disebabkan oleh konfigurasi yang salah. Berikut ini adalah beberapa contohnya:

    • Bergantung pada persyaratan skenario, Otoritas, Instans, ID Penyewa, DOMAIN Penyewa, ID Klien, atau URI Pengalihan yang hilang atau salah mencegah aplikasi mengautentikasi klien.
    • Cakupan permintaan yang salah mencegah klien mengakses titik akhir API web server.
    • Izin API server yang salah atau hilang mencegah klien mengakses titik akhir API web server.
    • Menjalankan aplikasi di port yang berbeda dari yang dikonfigurasi di URI Pengalihan pendaftaran aplikasi IP. Perhatikan bahwa port tidak diperlukan untuk ID Microsoft Entra dan aplikasi yang berjalan di localhost alamat pengujian pengembangan, tetapi konfigurasi port aplikasi dan port tempat aplikasi berjalan harus cocok untuk non-alamatlocalhost .

    Bagian konfigurasi dari panduan artikel ini menunjukkan contoh konfigurasi yang benar. Periksa dengan cermat setiap bagian artikel yang mencari kesalahan konfigurasi aplikasi dan IP.

    Jika konfigurasi muncul dengan benar:

    • Menganalisis log aplikasi.

    • Periksa lalu lintas jaringan antara aplikasi klien dan IP atau aplikasi server dengan alat pengembang browser. Seringkali, pesan kesalahan yang tepat atau pesan dengan petunjuk tentang apa yang menyebabkan masalah dikembalikan ke klien oleh IP atau aplikasi server setelah membuat permintaan. Alat pengembang panduan ditemukan dalam artikel berikut:

    • Untuk rilis Blazor tempat JSON Web Token (JWT) digunakan, dekode konten token yang digunakan untuk mengautentikasi klien atau mengakses API web server, tergantung di mana masalah terjadi. Untuk informasi selengkapnya, lihat Memeriksa konten JSON Web Token (JWT).

    Tim dokumentasi menanggapi umpan balik dokumen dan bug dalam artikel (buka masalah dari bagian Umpan balik halaman ini) tetapi tidak dapat memberikan dukungan produk. Beberapa forum dukungan publik tersedia untuk membantu memecahkan masalah aplikasi. Kami merekomendasikan hal-hal berikut:

    Forum sebelumnya tidak dimiliki atau dikendalikan oleh Microsoft.

    Untuk laporan bug kerangka kerja non-keamanan, non-sensitif, dan non-rahasia yang dapat direproduksi, buka masalah dengan unit produk ASP.NET Core. Jangan buka masalah dengan unit produk sampai Anda menyelidiki penyebab masalah secara menyeluruh dan tidak dapat menyelesaikannya sendiri dan dengan bantuan komunitas di forum dukungan publik. Unit produk tidak dapat memecahkan masalah aplikasi individual yang rusak karena kesalahan konfigurasi sederhana atau kasus penggunaan yang melibatkan layanan pihak ketiga. Jika laporan bersifat sensitif atau rahasia atau menggambarkan potensi kelemahan keamanan dalam produk yang dapat dieksploitasi penyerang, lihat Melaporkan masalah keamanan dan bug (dotnet/aspnetcore repositori GitHub).

  • Klien yang tidak sah untuk ME-ID

    info: Otorisasi Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2] gagal. Persyaratan ini tidak terpenuhi: DenyAnonymousAuthorizationRequirement: Memerlukan pengguna yang diautentikasi.

    Kesalahan panggilan balik masuk dari ME-ID:

    • Kesalahan: unauthorized_client
    • Deskripsi: AADB2C90058: The provided application is not configured to allow public clients.

    Untuk mengatasi masalah ini:

    1. Di portal Azure, akses manifes aplikasi.
    2. Atur atribut ke nullallowPublicClient atau true.

Cookies dan data situs

Cookiedata s dan situs dapat bertahan di seluruh pembaruan aplikasi dan mengganggu pengujian dan pemecahan masalah. Hapus hal berikut saat membuat perubahan kode aplikasi, perubahan akun pengguna dengan penyedia, atau perubahan konfigurasi aplikasi penyedia:

  • Rincian masuk cookiepengguna
  • Aplikasi cookies
  • Data situs yang di-cache dan disimpan

Salah satu pendekatan untuk mencegah cookiedata situs dan yang masih ada mengganggu pengujian dan pemecahan masalah adalah dengan:

  • Mengonfigurasi browser
    • Gunakan browser untuk pengujian yang dapat Anda konfigurasi untuk menghapus semua cookie dan data situs setiap kali browser ditutup.
    • Pastikan browser ditutup secara manual atau oleh IDE untuk setiap perubahan pada aplikasi, pengguna uji, atau konfigurasi penyedia.
  • Gunakan perintah kustom untuk membuka browser dalam mode InPrivate atau Penyamaran di Visual Studio:
    • Buka kotak dialog Telusuri Dengan dari tombol Jalankan Visual Studio.
    • Pilih tombol Tambahkan.
    • Berikan jalur ke browser Anda di bidang Program . Jalur yang dapat dieksekusi berikut adalah lokasi penginstalan umum untuk Windows 10. Jika browser Anda diinstal di lokasi yang berbeda atau Anda tidak menggunakan Windows 10, berikan jalur ke browser yang dapat dieksekusi.
      • Microsoft Edge: C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe
      • Google Chrome: C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
      • Mozilla Firefox: C:\Program Files\Mozilla Firefox\firefox.exe
    • Di bidang Argumen, berikan opsi baris perintah yang digunakan browser untuk membuka dalam mode InPrivate atau Penyamaran. Beberapa browser memerlukan URL aplikasi.
      • Microsoft Edge: Gunakan -inprivate.
      • Google Chrome: Gunakan --incognito --new-window {URL}, di mana tempat penampung {URL} adalah URL untuk dibuka (misalnya, https://localhost:5001).
      • Mozilla Firefox: Gunakan -private -url {URL}, di mana tempat penampung {URL} adalah URL untuk dibuka (misalnya, https://localhost:5001).
    • Berikan nama di bidang Nama yang mudah diingat. Contohnya, Firefox Auth Testing.
    • Pilih tombol OK.
    • Untuk menghindari harus memilih profil browser untuk setiap iterasi pengujian dengan aplikasi, atur profil sebagai default dengan tombol Atur sebagai Default .
    • Pastikan bahwa browser ditutup oleh IDE untuk setiap perubahan pada aplikasi, pengguna uji, atau konfigurasi penyedia.

Peningkatan aplikasi

Aplikasi yang berfungsi mungkin gagal segera setelah meningkatkan .NET Core SDK pada komputer pengembangan atau mengubah versi paket dalam aplikasi. Dalam beberapa kasus, paket yang tidak melekat dapat merusak aplikasi saat melakukan peningkatan besar. Sebagian besar masalah ini dapat diperbaiki dengan mengikuti instruksi berikut:

  1. Hapus cache paket NuGet sistem lokal dengan mengeksekusi dotnet nuget locals all --clear dari shell perintah.
  2. Hapus folder dan obj proyekbin.
  3. Pulihkan dan bangun ulang proyek.
  4. Hapus semua file di folder penyebaran di server sebelum menyebarkan ulang aplikasi.

Catatan

Penggunaan versi paket yang tidak kompatibel dengan kerangka kerja target aplikasi tidak didukung. Untuk informasi tentang paket, gunakan Galeri NuGet atau Penjelajah Paket FuGet.

Server Menjalankan aplikasi

Saat menguji dan memecahkan masalah solusi yang dihostingBlazor WebAssembly, pastikan Anda menjalankan aplikasi dari Server proyek.

Memeriksa pengguna

Komponen berikut User dapat digunakan langsung di aplikasi atau berfungsi sebagai dasar untuk penyesuaian lebih lanjut.

User.razor:

@page "/user"
@attribute [Authorize]
@using System.Text.Json
@using System.Security.Claims
@inject IAccessTokenProvider AuthorizationService

<h1>@AuthenticatedUser?.Identity?.Name</h1>

<h2>Claims</h2>

@foreach (var claim in AuthenticatedUser?.Claims ?? Array.Empty<Claim>())
{
    <p class="claim">@(claim.Type): @claim.Value</p>
}

<h2>Access token</h2>

<p id="access-token">@AccessToken?.Value</p>

<h2>Access token claims</h2>

@foreach (var claim in GetAccessTokenClaims())
{
    <p>@(claim.Key): @claim.Value.ToString()</p>
}

@if (AccessToken != null)
{
    <h2>Access token expires</h2>

    <p>Current time: <span id="current-time">@DateTimeOffset.Now</span></p>
    <p id="access-token-expires">@AccessToken.Expires</p>

    <h2>Access token granted scopes (as reported by the API)</h2>

    @foreach (var scope in AccessToken.GrantedScopes)
    {
        <p>Scope: @scope</p>
    }
}

@code {
    [CascadingParameter]
    private Task<AuthenticationState> AuthenticationState { get; set; }

    public ClaimsPrincipal AuthenticatedUser { get; set; }
    public AccessToken AccessToken { get; set; }

    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();
        var state = await AuthenticationState;
        var accessTokenResult = await AuthorizationService.RequestAccessToken();

        if (!accessTokenResult.TryGetToken(out var token))
        {
            throw new InvalidOperationException(
                "Failed to provision the access token.");
        }

        AccessToken = token;

        AuthenticatedUser = state.User;
    }

    protected IDictionary<string, object> GetAccessTokenClaims()
    {
        if (AccessToken == null)
        {
            return new Dictionary<string, object>();
        }

        // header.payload.signature
        var payload = AccessToken.Value.Split(".")[1];
        var base64Payload = payload.Replace('-', '+').Replace('_', '/')
            .PadRight(payload.Length + (4 - payload.Length % 4) % 4, '=');

        return JsonSerializer.Deserialize<IDictionary<string, object>>(
            Convert.FromBase64String(base64Payload));
    }
}

Memeriksa konten JSON Web Token (JWT)

Untuk mendekode JSON Web Token (JWT), gunakan alat jwt.ms Microsoft. Nilai di UI tidak pernah meninggalkan browser Anda.

Contoh JWT yang dikodekan (disingkat untuk tampilan):

eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ilg1ZVhrNHh5b2pORnVtMWtsMll0djhkbE5QNC1j ... bQdHBHGcQQRbW7Wmo6SWYG4V_bU55Ug_PW4pLPr20tTS8Ct7_uwy9DWrzCMzpD-EiwT5IjXwlGX3IXVjHIlX50IVIydBoPQtadvT7saKo1G5Jmutgq41o-dmz6-yBMKV2_nXA25Q

Contoh JWT yang didekodekan oleh alat untuk aplikasi yang mengautentikasi terhadap Azure AAD B2C:

{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "X5eXk4xyojNFum1kl2Ytv8dlNP4-c57dO6QGTVBwaNk"
}.{
  "exp": 1610059429,
  "nbf": 1610055829,
  "ver": "1.0",
  "iss": "https://mysiteb2c.b2clogin.com/5cc15ea8-a296-4aa3-97e4-226dcc9ad298/v2.0/",
  "sub": "5ee963fb-24d6-4d72-a1b6-889c6e2c7438",
  "aud": "70bde375-fce3-4b82-984a-b247d823a03f",
  "nonce": "b2641f54-8dc4-42ca-97ea-7f12ff4af871",
  "iat": 1610055829,
  "auth_time": 1610055822,
  "idp": "idp.com",
  "tfp": "B2C_1_signupsignin"
}.[Signature]

Sumber daya tambahan