Bagikan melalui


Mengamankan ASP.NET Core Blazor Web App dengan OpenID Connect (OIDC)

Artikel ini menjelaskan cara mengamankan Blazor Web App dengan OpenID Connect (OIDC) menggunakan aplikasi sampel di dotnet/blazor-samples repositori GitHub (.NET 8 atau yang lebih baru) (cara mengunduh).

Versi artikel ini mencakup penerapan OIDC tanpa mengadopsi pola Backend for Frontend (BFF). Pola BFF berguna untuk membuat permintaan terautentikasi ke layanan eksternal. Ubah pemilih versi artikel ke OIDC dengan pola BFF jika spesifikasi aplikasi memanggil untuk mengadopsi pola BFF.

Spesifikasi berikut tercakup:

  • Blazor Web App menggunakan mode Render otomatis dengan interaktivitas global.
  • Layanan penyedia status autentikasi kustom digunakan oleh server dan aplikasi klien untuk menangkap status autentikasi pengguna dan mengalirkannya antara server dan klien.
  • Aplikasi ini adalah titik awal untuk alur autentikasi OIDC apa pun. OIDC dikonfigurasi secara manual di aplikasi dan tidak mengandalkan ID Microsoft Entra atau paket Web MicrosoftIdentity, aplikasi sampel juga tidak memerlukan hosting Microsoft Azure. Namun, aplikasi sampel dapat digunakan dengan Entra, Microsoft Identity Web, dan dihosting di Azure.
  • Refresh token non-interaktif otomatis.
  • Memanggil API (web) dengan aman di proyek server untuk data.

Aplikasi sampel

Aplikasi sampel terdiri dari dua proyek:

  • BlazorWebAppOidc: Proyek sisi server dari Blazor Web App, yang berisi contoh titik akhir API Minimal untuk data cuaca.
  • BlazorWebAppOidc.Client: Proyek sisi klien dari Blazor Web App.

Akses aplikasi sampel melalui folder versi terbaru dari akar repositori dengan tautan berikut. Proyek berada di BlazorWebAppOidc folder untuk .NET 8 atau yang lebih baru.

Melihat atau mengunduh kode sampel (cara mengunduh)

Proyek sisi Blazor Web App server (BlazorWebAppOidc)

Proyek BlazorWebAppOidc ini adalah proyek sisi server dari Blazor Web App.

File BlazorWebAppOidc.http dapat digunakan untuk menguji permintaan data cuaca. Perhatikan bahwa BlazorWebAppOidc proyek harus berjalan untuk menguji titik akhir, dan titik akhir dikodekan secara permanen ke dalam file. Untuk informasi selengkapnya, lihat Menggunakan file .http di Visual Studio 2022.

Catatan

Proyek server menggunakan IHttpContextAccessor/HttpContext, tetapi tidak pernah untuk komponen yang dirender secara interaktif. Untuk informasi selengkapnya, lihat Panduan mitigasi ancaman untuk penyajian sisi server interaktif ASP.NET CoreBlazor.

Konfigurasi

Bagian ini menjelaskan cara mengonfigurasi aplikasi sampel.

Catatan

Untuk MICROSOFT Entra ID atau Azure AD B2C, Anda dapat menggunakan AddMicrosoftIdentityWebApp dari Microsoft Identity Web (Microsoft.Identity.Web paket NuGet, dokumentasi API), yang menambahkan penangan OIDC dan Cookie autentikasi dengan default yang sesuai. Aplikasi sampel dan panduan di bagian ini tidak menggunakan Microsoft Identity Web. Panduan ini menunjukkan cara mengonfigurasi handler OIDC secara manual untuk penyedia OIDC apa pun. Untuk informasi selengkapnya tentang menerapkan Microsoft Identity Web, lihat sumber daya tertaut.

Menetapkan rahasia klien

Peringatan

Jangan menyimpan rahasia aplikasi, string koneksi, kredensial, kata sandi, nomor identifikasi pribadi (PIN), kode C#/.NET privat, atau kunci/token privat dalam kode sisi klien, yang selalu tidak aman. Di lingkungan pengujian/penahapan dan produksi, kode sisi Blazor server dan API web harus menggunakan alur autentikasi aman yang menghindari mempertahankan kredensial dalam kode proyek atau file konfigurasi. Di luar pengujian pengembangan lokal, sebaiknya hindari penggunaan variabel lingkungan untuk menyimpan data sensitif, karena variabel lingkungan bukanlah pendekatan yang paling aman. Untuk pengujian pengembangan lokal, alat Secret Manager direkomendasikan untuk mengamankan data sensitif. Untuk informasi selengkapnya, lihat Mempertahankan data dan kredensial sensitif dengan aman.

Untuk pengujian pengembangan lokal, gunakan alat Secret Manager untuk menyimpan rahasia klien aplikasi server di bawah kunci Authentication:Schemes:MicrosoftOidc:ClientSecretkonfigurasi .

Catatan

Jika aplikasi menggunakan MICROSOFT Entra ID atau Azure AD B2C, buat rahasia klien di pendaftaran aplikasi di Entra atau portal Azure (Kelola>Sertifikat & rahasia>Rahasia klien baru). Gunakan Nilai rahasia baru dalam panduan berikut.

Aplikasi sampel belum diinisialisasi untuk alat Secret Manager. Gunakan shell perintah, seperti shell perintah Developer PowerShell di Visual Studio, untuk menjalankan perintah berikut. Sebelum menjalankan perintah, ubah direktori dengan cd perintah ke direktori proyek server. Perintah menetapkan pengidentifikasi rahasia pengguna (<UserSecretsId> dalam file proyek aplikasi server):

dotnet user-secrets init

Jalankan perintah berikut untuk mengatur rahasia klien. Tempat {SECRET} penampung adalah rahasia klien yang diperoleh dari pendaftaran aplikasi:

dotnet user-secrets set "Authentication:Schemes:MicrosoftOidc:ClientSecret" "{SECRET}"

Jika menggunakan Visual Studio, Anda dapat mengonfirmasi rahasia diatur dengan mengklik kanan proyek server di Penjelajah Solusi dan memilih Kelola Rahasia Pengguna.

Mengonfigurasikan aplikasi

Konfigurasi berikut OpenIdConnectOptions ditemukan dalam file proyek Program pada panggilan ke AddOpenIdConnect:

  • SignInScheme: Mengatur skema autentikasi yang sesuai dengan middleware yang bertanggung jawab untuk mempertahankan pengguna identity setelah autentikasi berhasil. Handler OIDC perlu menggunakan skema masuk yang mampu mempertahankan kredensial pengguna di seluruh permintaan. Baris berikut hadir hanya untuk tujuan demonstrasi. Jika dihilangkan, DefaultSignInScheme digunakan sebagai nilai fallback.

    oidcOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    
  • Cakupan untuk openid dan profile (Scope) (Opsional): Cakupan openid dan profile juga dikonfigurasi secara default karena diperlukan agar handler OIDC berfungsi, tetapi ini mungkin perlu ditambahkan kembali jika cakupan disertakan dalam Authentication:Schemes:MicrosoftOidc:Scope konfigurasi. Untuk panduan konfigurasi umum, lihat Konfigurasi dalam konfigurasi ASP.NET Core dan ASP.NET CoreBlazor.

    oidcOptions.Scope.Add(OpenIdConnectScope.OpenIdProfile);
    
  • SaveTokens: Menentukan apakah akses dan token refresh harus disimpan setelah AuthenticationProperties otorisasi berhasil. Properti ini diatur ke false untuk mengurangi ukuran autentikasi cookieakhir .

    oidcOptions.SaveTokens = false;
    
  • Cakupan untuk akses offline (Scope): Cakupan offline_access diperlukan untuk token refresh.

    oidcOptions.Scope.Add(OpenIdConnectScope.OfflineAccess);
    
  • Authority dan ClientId: Mengatur Otoritas dan ID Klien untuk panggilan OIDC.

    oidcOptions.Authority = "{AUTHORITY}";
    oidcOptions.ClientId = "{CLIENT ID}";
    

    Contoh:

    • Otoritas ({AUTHORITY}): https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/ (menggunakan ID aaaabbbb-0000-cccc-1111-dddd2222eeeePenyewa )
    • Id Klien ({CLIENT ID}): 00001111-aaaa-2222-bbbb-3333cccc4444
    oidcOptions.Authority = "https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/";
    oidcOptions.ClientId = "00001111-aaaa-2222-bbbb-3333cccc4444";
    

    Contoh untuk otoritas "umum" Microsoft Azure:

    Otoritas "umum" harus digunakan untuk aplikasi multi-penyewa. Anda juga dapat menggunakan otoritas "umum" untuk aplikasi penyewa tunggal, tetapi kustom IssuerValidator diperlukan, seperti yang ditunjukkan nanti di bagian ini.

    oidcOptions.Authority = "https://login.microsoftonline.com/common/v2.0/";
    
  • ResponseType: Mengonfigurasi handler OIDC untuk hanya melakukan alur kode otorisasi. Pemberian implisit dan aliran hibrid tidak perlu dalam mode ini.

    Dalam konfigurasi pendaftaran aplikasi pemberian implisit dan alur hibrid Entra atau portal Azure, jangan pilih kotak centang untuk titik akhir otorisasi untuk mengembalikan token Akses atau token ID. Handler OIDC secara otomatis meminta token yang sesuai menggunakan kode yang dikembalikan dari titik akhir otorisasi.

    oidcOptions.ResponseType = OpenIdConnectResponseType.Code;
    
  • MapInboundClaims dan konfigurasi dan NameClaimType RoleClaimType: Banyak server OIDC menggunakan "name" dan "role" daripada default SOAP/WS-Fed di ClaimTypes. Ketika MapInboundClaims diatur ke false, handler tidak melakukan pemetaan klaim, dan nama klaim dari JWT digunakan langsung oleh aplikasi. Contoh berikut mengatur jenis klaim peran menjadi "roles," yang sesuai untuk ID Microsoft Entra (ME-ID). Lihat dokumentasi penyedia Anda identity untuk informasi selengkapnya.

    Catatan

    MapInboundClaims harus diatur ke false untuk sebagian besar penyedia OIDC, yang mencegah penggantian nama klaim.

    oidcOptions.MapInboundClaims = false;
    oidcOptions.TokenValidationParameters.NameClaimType = "name";
    oidcOptions.TokenValidationParameters.RoleClaimType = "roles";
    
  • Konfigurasi jalur: Jalur harus cocok dengan jalur URI pengalihan (jalur panggilan balik masuk) dan pengalihan pasca keluar (jalur panggilan balik keluar) yang dikonfigurasi saat mendaftarkan aplikasi dengan penyedia OIDC. Di portal Azure, jalur dikonfigurasi di bilah Autentikasi pendaftaran aplikasi. Jalur masuk dan keluar harus didaftarkan sebagai URI pengalihan. Nilai defaultnya adalah /signin-oidc dan /signout-callback-oidc.

    • CallbackPath: Jalur permintaan dalam jalur dasar aplikasi tempat agen pengguna dikembalikan.

      Di Entra atau portal Azure, atur jalur di URI Pengalihan konfigurasi platform Web:

      https://localhost/signin-oidc

      Catatan

      Port tidak diperlukan untuk localhost alamat saat menggunakan ID Microsoft Entra. Sebagian besar penyedia OIDC lainnya memerlukan port yang benar.

    • SignedOutCallbackPath: Jalur permintaan dalam jalur dasar aplikasi tempat agen pengguna dikembalikan setelah keluar dari identity penyedia.

      Di Entra atau portal Azure, atur jalur di URI Pengalihan konfigurasi platform Web:

      https://localhost/signout-callback-oidc

      Catatan

      Port tidak diperlukan untuk localhost alamat saat menggunakan ID Microsoft Entra. Sebagian besar penyedia OIDC lainnya memerlukan port yang benar.

      Catatan

      Jika menggunakan Microsoft Identity Web, penyedia saat ini hanya mengalihkan kembali ke SignedOutCallbackPath jika microsoftonline.com Otoritas (https://login.microsoftonline.com/{TENANT ID}/v2.0/) digunakan. Batasan ini tidak ada jika Anda dapat menggunakan Otoritas "umum" dengan Microsoft Identity Web. Untuk informasi selengkapnya, lihat postLogoutRedirectUri tidak berfungsi saat url otoritas berisi ID penyewa (AzureAD/microsoft-authentication-library-for-js #5783).

    • RemoteSignOutPath: Permintaan yang diterima pada jalur ini menyebabkan handler memanggil keluar menggunakan skema keluar.

      Di Entra atau portal Azure, atur URL keluar saluran Depan:

      https://localhost/signout-oidc

      Catatan

      Port tidak diperlukan untuk localhost alamat saat menggunakan ID Microsoft Entra. Sebagian besar penyedia OIDC lainnya memerlukan port yang benar.

      oidcOptions.CallbackPath = new PathString("{PATH}");
      oidcOptions.SignedOutCallbackPath = new PathString("{PATH}");
      oidcOptions.RemoteSignOutPath = new PathString("{PATH}");
      

      Contoh (nilai default):

      oidcOptions.CallbackPath = new PathString("/signin-oidc");
      oidcOptions.SignedOutCallbackPath = new PathString("/signout-callback-oidc");
      oidcOptions.RemoteSignOutPath = new PathString("/signout-oidc");
      
  • (Microsoft Azure hanya dengan titik akhir "umum") TokenValidationParameters.IssuerValidator: Banyak penyedia OIDC bekerja dengan validator penerbit default, tetapi kita perlu memperhitungkan pengeluar sertifikat yang diparameterkan dengan ID Penyewa ({TENANT ID}) yang dikembalikan oleh https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration. Untuk informasi selengkapnya, lihat SecurityTokenInvalidIssuerException dengan OpenID Connect dan titik akhir "umum" Microsoft Azure AD (AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet #1731).

    Hanya untuk aplikasi yang menggunakan ID Microsoft Entra atau Azure AD B2C dengan titik akhir "umum":

    var microsoftIssuerValidator = AadIssuerValidator.GetAadIssuerValidator(oidcOptions.Authority);
    oidcOptions.TokenValidationParameters.IssuerValidator = microsoftIssuerValidator.Validate;
    

Contoh kode aplikasi

Periksa aplikasi sampel untuk fitur berikut:

  • Refresh token non-interaktif otomatis dengan bantuan penyegaran kustom cookie (CookieOidcRefresher.cs).
  • Proyek server memanggil AddAuthenticationStateSerialization untuk menambahkan penyedia status autentikasi sisi server yang menggunakan PersistentComponentState untuk mengalirkan status autentikasi ke klien. Klien memanggil AddAuthenticationStateDeserialization untuk mendeserialisasi dan menggunakan status autentikasi yang diteruskan oleh server. Status autentikasi diperbaiki untuk masa pakai aplikasi WebAssembly.
  • Contoh permintaan ke data untuk cuaca ditangani Blazor Web App oleh titik akhir API Minimal (/weather-forecast) dalam Program file (Program.cs). Titik akhir memerlukan otorisasi dengan memanggil RequireAuthorization. Untuk pengontrol apa pun yang Anda tambahkan ke proyek, tambahkan [Authorize] atribut ke pengontrol atau tindakan.
  • Aplikasi ini dengan aman memanggil API (web) di proyek server untuk data cuaca:
    • Saat merender Weather komponen di server, komponen menggunakan ServerWeatherForecaster di server untuk mendapatkan data cuaca secara langsung (bukan melalui panggilan API web).
    • Ketika komponen dirender pada klien, komponen menggunakan ClientWeatherForecaster implementasi layanan, yang menggunakan yang telah dikonfigurasi HttpClient sebelumnya (dalam file proyek Program klien) untuk melakukan panggilan API web ke proyek server. Titik akhir API Minimal (/weather-forecast) yang ditentukan dalam file proyek Program server mendapatkan data cuaca dari ServerWeatherForecaster dan mengembalikan data ke klien.
  • Refresh token non-interaktif otomatis dengan bantuan penyegaran kustom cookie (CookieOidcRefresher.cs).
  • Kelas PersistingAuthenticationStateProvider (PersistingAuthenticationStateProvider.cs) adalah sisi AuthenticationStateProvider server yang menggunakan PersistentComponentState untuk mengalirkan status autentikasi ke klien, yang kemudian diperbaiki selama masa pakai aplikasi WebAssembly.
  • Contoh permintaan ke data untuk cuaca ditangani Blazor Web App oleh titik akhir API Minimal (/weather-forecast) dalam Program file (Program.cs). Titik akhir memerlukan otorisasi dengan memanggil RequireAuthorization. Untuk pengontrol apa pun yang Anda tambahkan ke proyek, tambahkan [Authorize] atribut ke pengontrol atau tindakan.
  • Aplikasi ini dengan aman memanggil API (web) di proyek server untuk data cuaca:
    • Saat merender Weather komponen di server, komponen menggunakan ServerWeatherForecaster di server untuk mendapatkan data cuaca secara langsung (bukan melalui panggilan API web).
    • Ketika komponen dirender pada klien, komponen menggunakan ClientWeatherForecaster implementasi layanan, yang menggunakan yang telah dikonfigurasi HttpClient sebelumnya (dalam file proyek Program klien) untuk melakukan panggilan API web ke proyek server. Titik akhir API Minimal (/weather-forecast) yang ditentukan dalam file proyek Program server mendapatkan data cuaca dari ServerWeatherForecaster dan mengembalikan data ke klien.

Untuk informasi selengkapnya tentang panggilan API (web) menggunakan abstraksi layanan, Blazor Web Applihat Memanggil API web dari aplikasi ASP.NET CoreBlazor.

Proyek sisi Blazor Web App klien (BlazorWebAppOidc.Client)

Proyek BlazorWebAppOidc.Client ini adalah proyek sisi klien dari Blazor Web App.

Klien memanggil AddAuthenticationStateDeserialization untuk mendeserialisasi dan menggunakan status autentikasi yang diteruskan oleh server. Status autentikasi diperbaiki untuk masa pakai aplikasi WebAssembly.

Kelas PersistentAuthenticationStateProvider (PersistentAuthenticationStateProvider.cs) adalah sisi AuthenticationStateProvider klien yang menentukan status autentikasi pengguna dengan mencari data yang bertahan di halaman ketika dirender di server. Status autentikasi diperbaiki untuk masa pakai aplikasi WebAssembly.

Jika pengguna perlu masuk atau keluar, diperlukan pemuatan ulang halaman lengkap.

Aplikasi sampel hanya menyediakan nama pengguna dan email untuk tujuan tampilan. Ini tidak termasuk token yang mengautentikasi ke server saat membuat permintaan berikutnya, yang berfungsi secara terpisah menggunakan cookie yang disertakan pada HttpClient permintaan ke server.

Versi artikel ini mencakup penerapan OIDC dengan pola Backend for Frontend (BFF). Ubah pemilih versi artikel ke OIDC tanpa pola BFF jika spesifikasi aplikasi tidak memanggil untuk mengadopsi pola BFF.

Spesifikasi berikut tercakup:

  • Blazor Web App menggunakan mode Render otomatis dengan interaktivitas global.
  • Layanan penyedia status autentikasi kustom digunakan oleh server dan aplikasi klien untuk menangkap status autentikasi pengguna dan mengalirkannya antara server dan klien.
  • Aplikasi ini adalah titik awal untuk alur autentikasi OIDC apa pun. OIDC dikonfigurasi secara manual di aplikasi dan tidak mengandalkan ID Microsoft Entra atau paket Web MicrosoftIdentity, aplikasi sampel juga tidak memerlukan hosting Microsoft Azure. Namun, aplikasi sampel dapat digunakan dengan Entra, Microsoft Identity Web, dan dihosting di Azure.
  • Refresh token non-interaktif otomatis.
  • Pola Backend for Frontend (BFF) diadopsi menggunakan .NET Aspire untuk penemuan layanan dan YARP untuk mem-proksi permintaan ke titik akhir prakiraan cuaca pada aplikasi backend.
    • API web backend menggunakan autentikasi pembawa JWT untuk memvalidasi token JWT yang Blazor Web App disimpan oleh dalam rincian masuk cookie.
    • Aspire meningkatkan pengalaman membangun aplikasi cloud-native .NET. Ini menyediakan serangkaian alat dan pola yang konsisten dan berpendapat untuk membangun dan menjalankan aplikasi terdistribusi.
    • YARP (Namun Proksi Terbalik Lainnya) adalah pustaka yang digunakan untuk membuat server proksi terbalik.

Untuk informasi selengkapnya tentang .NET Aspire, lihat Ketersediaan .NET AspireUmum : Menyederhanakan .NET Cloud-Native Development (Mei 2024).

Prasyarat

.NET Aspirememerlukan Visual Studio versi 17.10 atau yang lebih baru.

Aplikasi sampel

Aplikasi sampel terdiri dari lima proyek:

  • .NET Aspire:
    • Aspire.AppHost: Digunakan untuk mengelola masalah orkestrasi tingkat tinggi aplikasi.
    • Aspire.ServiceDefaults: Berisi konfigurasi aplikasi default .NET Aspire yang dapat diperluas dan disesuaikan sesuai kebutuhan.
  • MinimalApiJwt: API web backend, berisi contoh titik akhir API Minimal untuk data cuaca.
  • BlazorWebAppOidc: Proyek sisi server Blazor Web Appdari .
  • BlazorWebAppOidc.Client: Proyek sisi klien dari Blazor Web App.

Akses aplikasi sampel melalui folder versi terbaru dari akar repositori dengan tautan berikut. Proyek berada di BlazorWebAppOidcBff folder untuk .NET 8 atau yang lebih baru.

Melihat atau mengunduh kode sampel (cara mengunduh)

.NET Aspire Proyek

Untuk informasi selengkapnya tentang penggunaan .NET Aspire dan detail tentang .AppHost proyek dan .ServiceDefaults aplikasi sampel, lihat .NET Aspire dokumentasi.

Konfirmasikan bahwa Anda telah memenuhi prasyarat untuk .NET Aspire. Untuk informasi selengkapnya, lihat bagian Prasyarat mulai cepat: Membangun aplikasi pertama .NET Aspire Anda.

Aplikasi sampel hanya mengonfigurasi profil peluncuran HTTP yang tidak aman (http) untuk digunakan selama pengujian pengembangan. Untuk informasi selengkapnya, termasuk contoh profil pengaturan peluncuran yang tidak aman dan aman, lihat Mengizinkan transportasi yang tidak aman dalam .NET Aspire (.NET Aspire dokumentasi).

Proyek sisi Blazor Web App server (BlazorWebAppOidc)

Proyek BlazorWebAppOidc ini adalah proyek sisi server dari Blazor Web App. Proyek ini menggunakan YARP untuk memproksi permintaan ke titik akhir prakiraan cuaca di proyek API web backend (MinimalApiJwt) dengan access_token yang disimpan dalam autentikasi cookie.

File BlazorWebAppOidc.http dapat digunakan untuk menguji permintaan data cuaca. Perhatikan bahwa BlazorWebAppOidc proyek harus berjalan untuk menguji titik akhir, dan titik akhir dikodekan secara permanen ke dalam file. Untuk informasi selengkapnya, lihat Menggunakan file .http di Visual Studio 2022.

Catatan

Proyek server menggunakan IHttpContextAccessor/HttpContext, tetapi tidak pernah untuk komponen yang dirender secara interaktif. Untuk informasi selengkapnya, lihat Panduan mitigasi ancaman untuk penyajian sisi server interaktif ASP.NET CoreBlazor.

Konfigurasi

Bagian ini menjelaskan cara mengonfigurasi aplikasi sampel.

Catatan

Untuk MICROSOFT Entra ID atau Azure AD B2C, Anda dapat menggunakan AddMicrosoftIdentityWebApp dari Microsoft Identity Web (Microsoft.Identity.Web paket NuGet, dokumentasi API), yang menambahkan penangan OIDC dan Cookie autentikasi dengan default yang sesuai. Aplikasi sampel dan panduan di bagian ini tidak menggunakan Microsoft Identity Web. Panduan ini menunjukkan cara mengonfigurasi handler OIDC secara manual untuk penyedia OIDC apa pun. Untuk informasi selengkapnya tentang menerapkan Microsoft Identity Web, lihat sumber daya tertaut.

Menetapkan rahasia klien

Peringatan

Jangan menyimpan rahasia aplikasi, string koneksi, kredensial, kata sandi, nomor identifikasi pribadi (PIN), kode C#/.NET privat, atau kunci/token privat dalam kode sisi klien, yang selalu tidak aman. Di lingkungan pengujian/penahapan dan produksi, kode sisi Blazor server dan API web harus menggunakan alur autentikasi aman yang menghindari mempertahankan kredensial dalam kode proyek atau file konfigurasi. Di luar pengujian pengembangan lokal, sebaiknya hindari penggunaan variabel lingkungan untuk menyimpan data sensitif, karena variabel lingkungan bukanlah pendekatan yang paling aman. Untuk pengujian pengembangan lokal, alat Secret Manager direkomendasikan untuk mengamankan data sensitif. Untuk informasi selengkapnya, lihat Mempertahankan data dan kredensial sensitif dengan aman.

Untuk pengujian pengembangan lokal, gunakan alat Secret Manager untuk menyimpan rahasia klien aplikasi server di bawah kunci Authentication:Schemes:MicrosoftOidc:ClientSecretkonfigurasi .

Catatan

Jika aplikasi menggunakan MICROSOFT Entra ID atau Azure AD B2C, buat rahasia klien di pendaftaran aplikasi di Entra atau portal Azure (Kelola>Sertifikat & rahasia>Rahasia klien baru). Gunakan Nilai rahasia baru dalam panduan berikut.

Aplikasi sampel belum diinisialisasi untuk alat Secret Manager. Gunakan shell perintah, seperti shell perintah Developer PowerShell di Visual Studio, untuk menjalankan perintah berikut. Sebelum menjalankan perintah, ubah direktori dengan cd perintah ke direktori proyek server. Perintah menetapkan pengidentifikasi rahasia pengguna (<UserSecretsId> dalam file proyek aplikasi server):

dotnet user-secrets init

Jalankan perintah berikut untuk mengatur rahasia klien. Tempat {SECRET} penampung adalah rahasia klien yang diperoleh dari pendaftaran aplikasi:

dotnet user-secrets set "Authentication:Schemes:MicrosoftOidc:ClientSecret" "{SECRET}"

Jika menggunakan Visual Studio, Anda dapat mengonfirmasi rahasia diatur dengan mengklik kanan proyek server di Penjelajah Solusi dan memilih Kelola Rahasia Pengguna.

Mengonfigurasikan aplikasi

Konfigurasi berikut OpenIdConnectOptions ditemukan dalam file proyek Program pada panggilan ke AddOpenIdConnect:

  • SignInScheme: Mengatur skema autentikasi yang sesuai dengan middleware yang bertanggung jawab untuk mempertahankan pengguna identity setelah autentikasi berhasil. Handler OIDC perlu menggunakan skema masuk yang mampu mempertahankan kredensial pengguna di seluruh permintaan. Baris berikut hadir hanya untuk tujuan demonstrasi. Jika dihilangkan, DefaultSignInScheme digunakan sebagai nilai fallback.

    oidcOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    
  • Cakupan untuk openid dan profile (Scope) (Opsional): Cakupan openid dan profile juga dikonfigurasi secara default karena diperlukan agar handler OIDC berfungsi, tetapi ini mungkin perlu ditambahkan kembali jika cakupan disertakan dalam Authentication:Schemes:MicrosoftOidc:Scope konfigurasi. Untuk panduan konfigurasi umum, lihat Konfigurasi dalam konfigurasi ASP.NET Core dan ASP.NET CoreBlazor.

    oidcOptions.Scope.Add(OpenIdConnectScope.OpenIdProfile);
    
  • SaveTokens: Menentukan apakah akses dan token refresh harus disimpan setelah AuthenticationProperties otorisasi berhasil. Nilai diatur ke true untuk mengautentikasi permintaan data cuaca dari proyek API web backend (MinimalApiJwt).

    oidcOptions.SaveTokens = true;
    
  • Cakupan untuk akses offline (Scope): Cakupan offline_access diperlukan untuk token refresh.

    oidcOptions.Scope.Add(OpenIdConnectScope.OfflineAccess);
    
  • Cakupan untuk mendapatkan data cuaca dari API web (Scope): Cakupan Weather.Get dikonfigurasi di portal Azure atau Entra di bawah Mengekspos API. Ini diperlukan untuk proyek API web backend (MinimalApiJwt) untuk memvalidasi token akses dengan pembawa JWT.

    oidcOptions.Scope.Add("{APP ID URI}/{API NAME}");
    

    Contoh:

    • URI ID Aplikasi ({APP ID URI}): https://{DIRECTORY NAME}.onmicrosoft.com/{CLIENT ID}
      • Nama Direktori ({DIRECTORY NAME}): contoso
      • Id Aplikasi (Klien) ({CLIENT ID}): 00001111-aaaa-2222-bbbb-3333cccc4444
    • Cakupan yang dikonfigurasi untuk data cuaca dari MinimalApiJwt ({API NAME}): Weather.Get
    oidcOptions.Scope.Add("https://contoso.onmicrosoft.com/00001111-aaaa-2222-bbbb-3333cccc4444/Weather.Get");
    

    Contoh sebelumnya berkaitan dengan aplikasi yang terdaftar di penyewa dengan jenis penyewa AAD B2C. Jika aplikasi terdaftar di penyewa ME-ID, URI ID Aplikasi berbeda, sehingga cakupannya berbeda.

    Contoh:

    • URI ID Aplikasi ({APP ID URI}): api://{CLIENT ID} dengan Id Aplikasi (Klien) ({CLIENT ID}): 00001111-aaaa-2222-bbbb-3333cccc4444
    • Cakupan yang dikonfigurasi untuk data cuaca dari MinimalApiJwt ({API NAME}): Weather.Get
    oidcOptions.Scope.Add("api://00001111-aaaa-2222-bbbb-3333cccc4444/Weather.Get");
    
  • Authority dan ClientId: Mengatur Otoritas dan ID Klien untuk panggilan OIDC.

    oidcOptions.Authority = "{AUTHORITY}";
    oidcOptions.ClientId = "{CLIENT ID}";
    

    Contoh:

    • Otoritas ({AUTHORITY}): https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/ (menggunakan ID aaaabbbb-0000-cccc-1111-dddd2222eeeePenyewa )
    • Id Klien ({CLIENT ID}): 00001111-aaaa-2222-bbbb-3333cccc4444
    oidcOptions.Authority = "https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/";
    oidcOptions.ClientId = "00001111-aaaa-2222-bbbb-3333cccc4444";
    

    Contoh untuk otoritas "umum" Microsoft Azure:

    Otoritas "umum" harus digunakan untuk aplikasi multi-penyewa. Anda juga dapat menggunakan otoritas "umum" untuk aplikasi penyewa tunggal, tetapi kustom IssuerValidator diperlukan, seperti yang ditunjukkan nanti di bagian ini.

    oidcOptions.Authority = "https://login.microsoftonline.com/common/v2.0/";
    
  • ResponseType: Mengonfigurasi handler OIDC untuk hanya melakukan alur kode otorisasi. Pemberian implisit dan aliran hibrid tidak perlu dalam mode ini.

    Dalam konfigurasi pendaftaran aplikasi pemberian implisit dan alur hibrid Entra atau portal Azure, jangan pilih kotak centang untuk titik akhir otorisasi untuk mengembalikan token Akses atau token ID. Handler OIDC secara otomatis meminta token yang sesuai menggunakan kode yang dikembalikan dari titik akhir otorisasi.

    oidcOptions.ResponseType = OpenIdConnectResponseType.Code;
    
  • MapInboundClaims dan konfigurasi dan NameClaimType RoleClaimType: Banyak server OIDC menggunakan "name" dan "role" daripada default SOAP/WS-Fed di ClaimTypes. Ketika MapInboundClaims diatur ke false, handler tidak melakukan pemetaan klaim dan nama klaim dari JWT digunakan langsung oleh aplikasi. Contoh berikut mengatur jenis klaim peran menjadi "roles," yang sesuai untuk ID Microsoft Entra (ME-ID). Lihat dokumentasi penyedia Anda identity untuk informasi selengkapnya.

    Catatan

    MapInboundClaims harus diatur ke false untuk sebagian besar penyedia OIDC, yang mencegah penggantian nama klaim.

    oidcOptions.MapInboundClaims = false;
    oidcOptions.TokenValidationParameters.NameClaimType = "name";
    oidcOptions.TokenValidationParameters.RoleClaimType = "roles";
    
  • Konfigurasi jalur: Jalur harus cocok dengan jalur URI pengalihan (jalur panggilan balik masuk) dan pengalihan pasca keluar (jalur panggilan balik keluar) yang dikonfigurasi saat mendaftarkan aplikasi dengan penyedia OIDC. Di portal Azure, jalur dikonfigurasi di bilah Autentikasi pendaftaran aplikasi. Jalur masuk dan keluar harus didaftarkan sebagai URI pengalihan. Nilai defaultnya adalah /signin-oidc dan /signout-callback-oidc.

    • CallbackPath: Jalur permintaan dalam jalur dasar aplikasi tempat agen pengguna dikembalikan.

      Di Entra atau portal Azure, atur jalur di URI Pengalihan konfigurasi platform Web:

      https://localhost/signin-oidc

      Catatan

      Port tidak diperlukan untuk localhost alamat.

    • SignedOutCallbackPath: Jalur permintaan dalam jalur dasar aplikasi tempat agen pengguna dikembalikan setelah keluar dari identity penyedia.

      Di Entra atau portal Azure, atur jalur di URI Pengalihan konfigurasi platform Web:

      https://localhost/signout-callback-oidc

      Catatan

      Port tidak diperlukan untuk localhost alamat.

      Catatan

      Jika menggunakan Microsoft Identity Web, penyedia saat ini hanya mengalihkan kembali ke SignedOutCallbackPath jika microsoftonline.com Otoritas (https://login.microsoftonline.com/{TENANT ID}/v2.0/) digunakan. Batasan ini tidak ada jika Anda dapat menggunakan Otoritas "umum" dengan Microsoft Identity Web. Untuk informasi selengkapnya, lihat postLogoutRedirectUri tidak berfungsi saat url otoritas berisi ID penyewa (AzureAD/microsoft-authentication-library-for-js #5783).

    • RemoteSignOutPath: Permintaan yang diterima pada jalur ini menyebabkan handler memanggil keluar menggunakan skema keluar.

      Di Entra atau portal Azure, atur URL keluar saluran Depan:

      https://localhost/signout-oidc

      Catatan

      Port tidak diperlukan untuk localhost alamat.

      oidcOptions.CallbackPath = new PathString("{PATH}");
      oidcOptions.SignedOutCallbackPath = new PathString("{PATH}");
      oidcOptions.RemoteSignOutPath = new PathString("{PATH}");
      

      Contoh (nilai default):

      oidcOptions.CallbackPath = new PathString("/signin-oidc");
      oidcOptions.SignedOutCallbackPath = new PathString("/signout-callback-oidc");
      oidcOptions.RemoteSignOutPath = new PathString("/signout-oidc");
      
  • (Microsoft Azure hanya dengan titik akhir "umum") TokenValidationParameters.IssuerValidator: Banyak penyedia OIDC bekerja dengan validator penerbit default, tetapi kita perlu memperhitungkan pengeluar sertifikat yang diparameterkan dengan ID Penyewa ({TENANT ID}) yang dikembalikan oleh https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration. Untuk informasi selengkapnya, lihat SecurityTokenInvalidIssuerException dengan OpenID Connect dan titik akhir "umum" Microsoft Azure AD (AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet #1731).

    Hanya untuk aplikasi yang menggunakan ID Microsoft Entra atau Azure AD B2C dengan titik akhir "umum":

    var microsoftIssuerValidator = AadIssuerValidator.GetAadIssuerValidator(oidcOptions.Authority);
    oidcOptions.TokenValidationParameters.IssuerValidator = microsoftIssuerValidator.Validate;
    

Contoh kode aplikasi

Periksa aplikasi sampel untuk fitur berikut:

  • Refresh token non-interaktif otomatis dengan bantuan penyegaran kustom cookie (CookieOidcRefresher.cs).
  • Proyek server memanggil AddAuthenticationStateSerialization untuk menambahkan penyedia status autentikasi sisi server yang menggunakan PersistentComponentState untuk mengalirkan status autentikasi ke klien. Klien memanggil AddAuthenticationStateDeserialization untuk mendeserialisasi dan menggunakan status autentikasi yang diteruskan oleh server. Status autentikasi diperbaiki untuk masa pakai aplikasi WebAssembly.
  • Permintaan ke Blazor Web App diproksikan ke proyek API web backend (MinimalApiJwt). MapForwarderProgram dalam file menambahkan penerusan langsung permintaan HTTP yang cocok dengan pola yang ditentukan ke tujuan tertentu menggunakan konfigurasi default untuk permintaan keluar, transformasi yang disesuaikan, dan klien HTTP default:
    • Saat merender Weather komponen di server, komponen menggunakan ServerWeatherForecaster untuk mem-proksi permintaan data cuaca dengan token akses pengguna.
    • Ketika komponen dirender pada klien, komponen menggunakan ClientWeatherForecaster implementasi layanan, yang menggunakan yang telah dikonfigurasi HttpClient sebelumnya (dalam file proyek Program klien) untuk melakukan panggilan API web ke proyek server. Titik akhir API Minimal (/weather-forecast) yang ditentukan dalam file proyek Program server mengubah permintaan dengan token akses pengguna untuk mendapatkan data cuaca.
  • Refresh token non-interaktif otomatis dengan bantuan penyegaran kustom cookie (CookieOidcRefresher.cs).
  • Kelas PersistingAuthenticationStateProvider (PersistingAuthenticationStateProvider.cs) adalah sisi AuthenticationStateProvider server yang menggunakan PersistentComponentState untuk mengalirkan status autentikasi ke klien, yang kemudian diperbaiki selama masa pakai aplikasi WebAssembly.
  • Permintaan ke Blazor Web App diproksikan ke proyek API web backend (MinimalApiJwt). MapForwarderProgram dalam file menambahkan penerusan langsung permintaan HTTP yang cocok dengan pola yang ditentukan ke tujuan tertentu menggunakan konfigurasi default untuk permintaan keluar, transformasi yang disesuaikan, dan klien HTTP default:
    • Saat merender Weather komponen di server, komponen menggunakan ServerWeatherForecaster untuk mem-proksi permintaan data cuaca dengan token akses pengguna.
    • Ketika komponen dirender pada klien, komponen menggunakan ClientWeatherForecaster implementasi layanan, yang menggunakan yang telah dikonfigurasi HttpClient sebelumnya (dalam file proyek Program klien) untuk melakukan panggilan API web ke proyek server. Titik akhir API Minimal (/weather-forecast) yang ditentukan dalam file proyek Program server mengubah permintaan dengan token akses pengguna untuk mendapatkan data cuaca.

Untuk informasi selengkapnya tentang panggilan API (web) menggunakan abstraksi layanan, Blazor Web Applihat Memanggil API web dari aplikasi ASP.NET CoreBlazor.

Proyek sisi Blazor Web App klien (BlazorWebAppOidc.Client)

Proyek BlazorWebAppOidc.Client ini adalah proyek sisi klien dari Blazor Web App.

Klien memanggil AddAuthenticationStateDeserialization untuk mendeserialisasi dan menggunakan status autentikasi yang diteruskan oleh server. Status autentikasi diperbaiki untuk masa pakai aplikasi WebAssembly.

Kelas PersistentAuthenticationStateProvider (PersistentAuthenticationStateProvider.cs) adalah sisi AuthenticationStateProvider klien yang menentukan status autentikasi pengguna dengan mencari data yang bertahan di halaman ketika dirender di server. Status autentikasi diperbaiki untuk masa pakai aplikasi WebAssembly.

Jika pengguna perlu masuk atau keluar, diperlukan pemuatan ulang halaman lengkap.

Aplikasi sampel hanya menyediakan nama pengguna dan email untuk tujuan tampilan. Ini tidak termasuk token yang mengautentikasi ke server saat membuat permintaan berikutnya, yang berfungsi secara terpisah menggunakan cookie yang disertakan pada HttpClient permintaan ke server.

Proyek API web backend (MinimalApiJwt)

Proyek MinimalApiJwt ini adalah API web backend untuk beberapa proyek frontend. Proyek mengonfigurasi titik akhir API Minimal untuk data cuaca. Permintaan dari Blazor Web App proyek sisi server (BlazorWebAppOidc) diproksikan ke MinimalApiJwt proyek.

Konfigurasi

Konfigurasikan proyek dalam JwtBearerOptions AddJwtBearer panggilan dalam file proyek Program :

  • Audience: Mengatur Audiens untuk setiap token OpenID Connect yang diterima.

    Di portal Azure atau Entra: Cocokkan nilai hanya dengan jalur URI ID Aplikasi yang dikonfigurasi saat menambahkan Weather.Get cakupan di bawah Ekspos API:

    jwtOptions.Audience = "{APP ID URI}";
    

    Contoh:

    URI ID Aplikasi ({APP ID URI}): https://{DIRECTORY NAME}.onmicrosoft.com/{CLIENT ID}:

    • Nama Direktori ({DIRECTORY NAME}): contoso
    • Id Aplikasi (Klien) ({CLIENT ID}): 00001111-aaaa-2222-bbbb-3333cccc4444
    jwtOptions.Audience = "https://contoso.onmicrosoft.com/00001111-aaaa-2222-bbbb-3333cccc4444";
    

    Contoh sebelumnya berkaitan dengan aplikasi yang terdaftar di penyewa dengan jenis penyewa AAD B2C. Jika aplikasi terdaftar di penyewa ME-ID, URI ID Aplikasi berbeda, sehingga audiens berbeda.

    Contoh:

    URI ID Aplikasi ({APP ID URI}): api://{CLIENT ID} dengan Id Aplikasi (Klien) ({CLIENT ID}): 00001111-aaaa-2222-bbbb-3333cccc4444

    jwtOptions.Audience = "api://00001111-aaaa-2222-bbbb-3333cccc4444";
    
  • Authority: Mengatur Otoritas untuk melakukan panggilan OpenID Connect. Cocokkan nilai dengan Otoritas yang dikonfigurasi untuk handler OIDC di BlazorWebAppOidc/Program.cs:

    jwtOptions.Authority = "{AUTHORITY}";
    

    Contoh:

    Otoritas ({AUTHORITY}): https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/ (menggunakan ID aaaabbbb-0000-cccc-1111-dddd2222eeeePenyewa )

    jwtOptions.Authority = "https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0/";
    

    Contoh sebelumnya berkaitan dengan aplikasi yang terdaftar di penyewa dengan jenis penyewa AAD B2C. Jika aplikasi terdaftar di penyewa ME-ID, otoritas harus cocok dengan issurer (iss) JWT yang dikembalikan oleh identity penyedia:

    jwtOptions.Authority = "https://sts.windows.net/aaaabbbb-0000-cccc-1111-dddd2222eeee/";
    

API minimal untuk data cuaca

Titik akhir data prakiraan cuaca yang aman dalam file proyek Program :

app.MapGet("/weather-forecast", () =>
{
    var forecast = Enumerable.Range(1, 5).Select(index =>
        new WeatherForecast
        (
            DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
            Random.Shared.Next(-20, 55),
            summaries[Random.Shared.Next(summaries.Length)]
        ))
        .ToArray();
    return forecast;
}).RequireAuthorization();

Metode RequireAuthorization ekstensi memerlukan otorisasi untuk definisi rute. Untuk pengontrol apa pun yang Anda tambahkan ke proyek, tambahkan [Authorize] atribut ke pengontrol atau tindakan.

Mengalihkan ke home halaman saat keluar

Saat pengguna menavigasi di sekitar aplikasi, LogInOrOut komponen (Layout/LogInOrOut.razor) mengatur bidang tersembunyi untuk URL pengembalian (ReturnUrl) ke nilai URL saat ini (currentURL). Saat pengguna keluar dari aplikasi, identity penyedia mengembalikannya ke halaman tempat mereka keluar.

Jika pengguna keluar dari halaman aman, mereka dikembalikan ke halaman aman yang sama setelah keluar hanya untuk dikirim kembali melalui proses autentikasi. Perilaku ini baik-baik saja ketika pengguna perlu sering beralih akun. Namun, spesifikasi aplikasi alternatif dapat meminta pengguna untuk dikembalikan ke halaman aplikasi home atau beberapa halaman lain setelah keluar. Contoh berikut menunjukkan cara mengatur halaman aplikasi home sebagai URL pengembalian untuk operasi signout.

Perubahan penting pada LogInOrOut komponen ditunjukkan dalam contoh berikut. Tidak perlu menyediakan bidang tersembunyi untuk diatur ReturnUrl ke home halaman di / karena itu adalah jalur default. IDisposable tidak lagi diimplementasikan. NavigationManager tidak lagi disuntikkan. Seluruh @code blok dihapus.

Layout/LogInOrOut.razor:

@using Microsoft.AspNetCore.Authorization

<div class="nav-item px-3">
    <AuthorizeView>
        <Authorized>
            <form action="authentication/logout" method="post">
                <AntiforgeryToken />
                <button type="submit" class="nav-link">
                    <span class="bi bi-arrow-bar-left-nav-menu" aria-hidden="true">
                    </span> Logout @context.User.Identity?.Name
                </button>
            </form>
        </Authorized>
        <NotAuthorized>
            <a class="nav-link" href="authentication/login">
                <span class="bi bi-person-badge-nav-menu" aria-hidden="true"></span> 
                Login
            </a>
        </NotAuthorized>
    </AuthorizeView>
</div>

Nonce kriptografi

Nonce adalah nilai string yang mengaitkan sesi klien dengan token ID untuk mengurangi serangan pemutaran ulang.

Jika Anda menerima kesalahan nonce selama pengembangan dan pengujian autentikasi, gunakan sesi browser InPrivate/incognito baru untuk setiap eksekusi pengujian, tidak peduli seberapa kecil perubahan yang dilakukan pada aplikasi atau pengguna uji karena data kedaluarsa cookie dapat menyebabkan kesalahan nonce. Untuk informasi selengkapnya, lihat bagian Cookie dan data situs.

Nonce tidak diperlukan atau digunakan saat token refresh ditukar dengan token akses baru. Di aplikasi sampel, CookieOidcRefresher (CookieOidcRefresher.cs) sengaja diatur OpenIdConnectProtocolValidator.RequireNonce ke false.

Peran aplikasi untuk aplikasi yang tidak terdaftar di Microsoft Entra (ME-ID)

Bagian ini berkaitan dengan aplikasi yang tidak menggunakan MICROSOFT Entra ID (ME-ID) sebagai identity penyedia. Untuk aplikasi yang terdaftar dengan ME-ID, lihat bagian Peran aplikasi untuk aplikasi yang terdaftar di Microsoft Entra (ME-ID).

Konfigurasikan jenis klaim peran (TokenValidationParameters.RoleClaimType) di OpenIdConnectOptions dari Program.cs:

oidcOptions.TokenValidationParameters.RoleClaimType = "{ROLE CLAIM TYPE}";

Untuk banyak penyedia OIDC identity , jenis klaim peran adalah role. Periksa dokumentasi penyedia Anda identity untuk nilai yang benar.

UserInfo Ganti kelas dalam BlazorWebAppOidc.Client proyek dengan kelas berikut.

UserInfo.cs:

using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using System.Security.Claims;

namespace BlazorWebAppOidc.Client;

// Add properties to this class and update the server and client 
// AuthenticationStateProviders to expose more information about 
// the authenticated user to the client.
public sealed class UserInfo
{
    public required string UserId { get; init; }
    public required string Name { get; init; }
    public required string[] Roles { get; init; }

    public const string UserIdClaimType = "sub";
    public const string NameClaimType = "name";
    private const string RoleClaimType = "role";

    public static UserInfo FromClaimsPrincipal(ClaimsPrincipal principal) =>
        new()
        {
            UserId = GetRequiredClaim(principal, UserIdClaimType),
            Name = GetRequiredClaim(principal, NameClaimType),
            Roles = principal.FindAll(RoleClaimType).Select(c => c.Value)
                .ToArray(),
        };

    public ClaimsPrincipal ToClaimsPrincipal() =>
        new(new ClaimsIdentity(
            Roles.Select(role => new Claim(RoleClaimType, role))
                .Concat([
                    new Claim(UserIdClaimType, UserId),
                    new Claim(NameClaimType, Name),
                ]),
            authenticationType: nameof(UserInfo),
            nameType: NameClaimType,
            roleType: RoleClaimType));

    private static string GetRequiredClaim(ClaimsPrincipal principal,
        string claimType) =>
            principal.FindFirst(claimType)?.Value ??
            throw new InvalidOperationException(
                $"Could not find required '{claimType}' claim.");
}

Pada titik ini, Razor komponen dapat mengadopsi otorisasi berbasis peran dan berbasis kebijakan. Peran aplikasi muncul dalam role klaim, satu klaim per peran.

Peran aplikasi untuk aplikasi yang terdaftar di Microsoft Entra (ME-ID)

Gunakan panduan di bagian ini untuk menerapkan peran aplikasi, grup keamanan ME-ID, dan peran administrator bawaan ME-ID untuk aplikasi menggunakan ID Microsoft Entra (ME-ID).

Pendekatan yang dijelaskan di bagian ini mengonfigurasi ME-ID untuk mengirim grup dan peran di header autentikasi cookie . Ketika pengguna hanya anggota dari beberapa grup dan peran keamanan, pendekatan berikut harus berfungsi untuk sebagian besar platform hosting tanpa mengalami masalah di mana header terlalu panjang, misalnya dengan hosting IIS yang memiliki batas panjang header default 16 KB (MaxRequestBytes). Jika panjang header adalah masalah karena keanggotaan grup atau peran yang tinggi, kami sarankan untuk tidak mengikuti panduan di bagian ini demi menerapkan Microsoft Graph untuk mendapatkan grup dan peran pengguna dari ME-ID secara terpisah, pendekatan yang tidak mengembang ukuran autentikasi cookie. Untuk informasi selengkapnya, lihat Permintaan Buruk - Permintaan Terlalu Panjang - Server IIS (dotnet/aspnetcore #57545).

Konfigurasikan jenis klaim peran (TokenValidationParameters.RoleClaimType) di OpenIdConnectOptions .Program.cs Atur nilai ke roles:

oidcOptions.TokenValidationParameters.RoleClaimType = "roles";

Meskipun Anda tidak dapat menetapkan peran ke grup tanpa akun ME-ID Premium, Anda dapat menetapkan peran kepada pengguna dan menerima klaim peran untuk pengguna dengan akun Azure standar. Panduan di bagian ini tidak memerlukan akun ME-ID Premium.

Saat bekerja dengan direktori default, ikuti panduan di Menambahkan peran aplikasi ke aplikasi Anda dan menerimanya dalam token (dokumentasi ME-ID) untuk mengonfigurasi dan menetapkan peran. Jika Anda tidak bekerja dengan direktori default, edit manifes aplikasi di portal Azure untuk membuat peran aplikasi secara manual dalam appRoles entri file manifes. Untuk informasi selengkapnya, lihat Mengonfigurasi klaim peran (dokumentasi ME-ID).

Grup keamanan Azure pengguna tiba dalam groups klaim, dan penetapan peran administrator ME-ID bawaan pengguna tiba dalam klaim ID (wids) terkenal. Nilai untuk kedua jenis klaim adalah GUID. Saat diterima oleh aplikasi, klaim ini dapat digunakan untuk menetapkan peran dan otorisasi kebijakan dalam Razor komponen.

Dalam manifes aplikasi di portal Azure, atur groupMembershipClaims atribut ke All. Nilai All hasil dalam ME-ID yang mengirim semua grup keamanan/distribusi (groups klaim) dan peran (wids klaim) pengguna yang masuk. Untuk mengatur groupMembershipClaims atribut:

  1. Buka pendaftaran aplikasi di portal Azure.
  2. Pilih Kelola>Manifes di bar samping.
  3. groupMembershipClaims Temukan atribut .
  4. Atur nilai ke All ("groupMembershipClaims": "All").
  5. Pilih tombol Simpan.

UserInfo Ganti kelas dalam BlazorWebAppOidc.Client proyek dengan kelas berikut.

UserInfo.cs:

using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using System.Security.Claims;

namespace BlazorWebAppOidc.Client;

// Add properties to this class and update the server and client 
// AuthenticationStateProviders to expose more information about 
// the authenticated user to the client.
public sealed class UserInfo
{
    public required string UserId { get; init; }
    public required string Name { get; init; }
    public required string[] Roles { get; init; }
    public required string[] Groups { get; init; }
    public required string[] Wids { get; init; }

    public const string UserIdClaimType = "sub";
    public const string NameClaimType = "name";
    private const string RoleClaimType = "roles";
    private const string GroupsClaimType = "groups";
    private const string WidsClaimType = "wids";

    public static UserInfo FromClaimsPrincipal(ClaimsPrincipal principal) =>
        new()
        {
            UserId = GetRequiredClaim(principal, UserIdClaimType),
            Name = GetRequiredClaim(principal, NameClaimType),
            Roles = principal.FindAll(RoleClaimType).Select(c => c.Value)
                .ToArray(),
            Groups = principal.FindAll(GroupsClaimType).Select(c => c.Value)
                .ToArray(),
            Wids = principal.FindAll(WidsClaimType).Select(c => c.Value)
                .ToArray(),
        };

    public ClaimsPrincipal ToClaimsPrincipal() =>
        new(new ClaimsIdentity(
            Roles.Select(role => new Claim(RoleClaimType, role))
                .Concat(Groups.Select(role => new Claim(GroupsClaimType, role)))
                .Concat(Wids.Select(role => new Claim(WidsClaimType, role)))
                .Concat([
                    new Claim(UserIdClaimType, UserId),
                    new Claim(NameClaimType, Name),
                ]),
            authenticationType: nameof(UserInfo),
            nameType: NameClaimType,
            roleType: RoleClaimType));

    private static string GetRequiredClaim(ClaimsPrincipal principal,
        string claimType) =>
            principal.FindFirst(claimType)?.Value ??
            throw new InvalidOperationException(
                $"Could not find required '{claimType}' claim.");
}

Pada titik ini, Razor komponen dapat mengadopsi otorisasi berbasis peran dan berbasis kebijakan:

  • Peran aplikasi muncul dalam roles klaim, satu klaim per peran.
  • Grup keamanan muncul dalam groups klaim, satu klaim per grup. GUID grup keamanan muncul di portal Azure saat Anda membuat grup keamanan dan dicantumkan saat memilih Identity>Tampilan Grup>Gambaran Umum.>
  • Peran administrator ME-ID bawaan muncul dalam wids klaim, satu klaim per peran. wids Klaim dengan nilai b79fbf4d-3ef9-4689-8143-76b194e85509 selalu dikirim oleh ME-ID untuk akun non-tamu penyewa dan tidak merujuk ke peran administrator. GUID peran administrator (ID templat peran) muncul di portal Azure saat memilih Peran & admin, diikuti oleh elipsis (...) >Deskripsi untuk peran yang tercantum. ID templat peran juga tercantum dalam peran bawaan Microsoft Entra (dokumentasi Entra).

Pecahkan masalah

Pencatatan

Aplikasi server adalah aplikasi ASP.NET Core standar. Lihat panduan pengelogan ASP.NET Core untuk mengaktifkan tingkat pengelogan yang lebih rendah di aplikasi server.

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 .

    Cakupan konfigurasi dalam artikel ini menunjukkan contoh konfigurasi yang benar. Periksa konfigurasi dengan hati-hati 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:

    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 oleh penyidik cyber, 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 null allowPublicClient atau true.

Cookie dan data situs

Cookie dan data 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:

  • Cookie masuk pengguna
  • Cookie aplikasi
  • Data situs yang di-cache dan disimpan

Salah satu pendekatan untuk mencegah cookie dan data situs 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 {URL} tempat penampung adalah URL untuk dibuka (misalnya, https://localhost:5001).
      • Mozilla Firefox: Gunakan -private -url {URL}, di mana {URL} tempat penampung 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.

Menjalankan aplikasi server

Saat menguji dan memecahkan masalah Blazor Web App, pastikan Anda menjalankan aplikasi dari proyek server.

Memeriksa pengguna

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

UserClaims.razor:

@page "/user-claims"
@using System.Security.Claims
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize]

<PageTitle>User Claims</PageTitle>

<h1>User Claims</h1>

@if (claims.Any())
{
    <ul>
        @foreach (var claim in claims)
        {
            <li><b>@claim.Type:</b> @claim.Value</li>
        }
    </ul>
}

@code {
    private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();

    [CascadingParameter]
    private Task<AuthenticationState>? AuthState { get; set; }

    protected override async Task OnInitializedAsync()
    {
        if (AuthState == null)
        {
            return;
        }

        var authState = await AuthState;
        claims = authState.User.Claims;
    }
}

Sumber Daya Tambahan: