Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Catatan
Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat versi .NET 9 dari artikel ini.
Peringatan
Versi ASP.NET Core ini tidak lagi didukung. Untuk informasi selengkapnya, lihat Kebijakan Dukungan .NET dan .NET Core. Untuk rilis saat ini, lihat versi .NET 9 dari artikel ini.
Penting
Informasi ini berkaitan dengan produk pra-rilis yang mungkin dimodifikasi secara substansial sebelum dirilis secara komersial. Microsoft tidak memberikan jaminan, tersirat maupun tersurat, sehubungan dengan informasi yang diberikan di sini.
Untuk rilis saat ini, lihat versi .NET 9 dari artikel ini.
ASP.NET Core Identity menyediakan API yang menangani autentikasi, otorisasi, dan manajemen identitas. API memungkinkan pengamanan titik akhir dari backend API Web dengan autentikasi berbasis cookie. Opsi berbasis token tersedia untuk klien yang tidak dapat menggunakan cookie, tetapi dalam menggunakan ini Anda bertanggung jawab untuk memastikan token tetap aman. Sebaiknya gunakan cookie untuk aplikasi berbasis browser, karena, secara default, browser secara otomatis menanganinya tanpa mengeksposnya ke JavaScript.
Artikel ini menunjukkan cara menggunakan Identity untuk mengamankan backend API Web untuk SPAs seperti aplikasi Angular, React, dan Vue. API backend yang sama dapat digunakan untuk mengamankan Blazor WebAssembly aplikasi.
Prasyarat
Langkah-langkah yang ditunjukkan dalam artikel ini menambahkan autentikasi dan otorisasi ke aplikasi ASP.NET Core Web API yang:
- Belum dikonfigurasi untuk autentikasi.
- Target
net8.0
atau yang lebih. - Dapat berupa API minimal atau API berbasis pengontrol.
Beberapa instruksi pengujian dalam artikel ini menggunakan antarmuka pengguna Swagger yang disertakan dengan templat proyek. Antarmuka pengguna Swagger tidak diperlukan untuk menggunakan Identity dengan backend API Web.
Menginstal paket NuGet
Instal paket NuGet berikut:
-
Microsoft.AspNetCore.Identity.EntityFrameworkCore
- Memungkinkan Identity untuk bekerja dengan Entity Framework Core (EF Core). - Salah satu yang memungkinkan EF Core untuk bekerja dengan database, seperti salah satu paket berikut:
Untuk cara tercepat untuk memulai, gunakan database dalam memori.
Ubah database nanti ke SQLite atau SQL Server untuk menyimpan data pengguna antar sesi saat menguji atau untuk penggunaan produksi. Ini memperkenalkan beberapa kompleksitas dibandingkan dengan penyimpanan dalam memori, sebab mengharuskan database dibuat melalui migrasi, seperti yang diperlihatkan dalam EF Core tutorial memulai.
Instal paket ini dengan menggunakan manajer paket NuGet di Visual Studio atau perintah CLI tambahkan paket dotnet.
Buat IdentityDbContext
Tambahkan kelas bernama ApplicationDbContext
yang mewarisi dari IdentityDbContext<TUser>:
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
public class ApplicationDbContext : IdentityDbContext<IdentityUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) :
base(options)
{ }
}
Kode yang ditampilkan menyediakan konstruktor khusus yang memungkinkan untuk mengonfigurasi database untuk lingkungan yang berbeda.
Tambahkan satu atau lebih arahan berikut ini using
sesuai kebutuhan saat menambahkan kode yang diperlihatkan dalam langkah-langkah ini.
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
Konfigurasi konteks EF Core
Seperti disebutkan sebelumnya, cara paling sederhana untuk memulai adalah dengan menggunakan database dalam memori. Dalam mode in-memory, setiap kali dijalankan menggunakan database baru, dan tidak perlu menggunakan migrasi. Setelah panggilan ke WebApplication.CreateBuilder(args)
, tambahkan kode berikut untuk dikonfigurasi Identity untuk menggunakan database dalam memori:
builder.Services.AddDbContext<ApplicationDbContext>(
options => options.UseInMemoryDatabase("AppDb"));
Untuk menyimpan data pengguna antar sesi saat menguji atau untuk penggunaan produksi, ubah database nanti ke SQLite atau SQL Server.
Menambahkan Identity layanan ke kontainer
Setelah panggilan ke WebApplication.CreateBuilder(args)
, panggil AddAuthorization untuk menambahkan layanan ke kontainer injeksi dependensi (DI):
builder.Services.AddAuthorization();
Mengaktifkan Identity API
Setelah panggilan ke WebApplication.CreateBuilder(args)
, panggil AddIdentityApiEndpoints<TUser>(IServiceCollection) dan AddEntityFrameworkStores<TContext>(IdentityBuilder).
builder.Services.AddIdentityApiEndpoints<IdentityUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
Secara default, cookie dan token kepemilikan diaktifkan. Cookies dan token diberikan saat login jika parameter string kueri useCookies
di titik akhir login adalah true
.
Peta rute Identity
Setelah memanggil builder.Build()
, panggil MapIdentityApi<TUser>(IEndpointRouteBuilder) untuk memetakan endpoint Identity:
app.MapIdentityApi<IdentityUser>();
Mengamankan titik akhir yang dipilih
Untuk mengamankan titik akhir, gunakan RequireAuthorization metode ekstensi pada Map{Method}
panggilan yang menentukan rute. Contohnya:
app.MapGet("/weatherforecast", (HttpContext httpContext) =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = summaries[Random.Shared.Next(summaries.Length)]
})
.ToArray();
return forecast;
})
.WithName("GetWeatherForecast")
.WithOpenApi()
.RequireAuthorization();
Metode ini RequireAuthorization
juga dapat digunakan untuk:
Amankan titik akhir UI Swagger, seperti yang ditunjukkan dalam contoh berikut:
app.MapSwagger().RequireAuthorization();
Amankan dengan klaim atau izin tertentu, seperti yang ditunjukkan dalam contoh berikut:
.RequireAuthorization("Admin");
Dalam proyek API web berbasis pengontrol, titik akhir aman dengan menerapkan atribut [Authorize
] ke pengontrol atau tindakan.
Menguji API
Cara cepat untuk menguji autentikasi adalah dengan menggunakan database dalam memori dan antarmuka pengguna Swagger yang disertakan dengan templat proyek. Langkah-langkah berikut menunjukkan cara menguji API dengan antarmuka pengguna Swagger. Pastikan bahwa titik akhir antarmuka pengguna Swagger tidak diamankan.
Mencoba mengakses titik akhir aman
- Jalankan aplikasi dan navigasikan ke antarmuka pengguna Swagger.
- Perluas titik akhir aman, seperti
/weatherforecast
dalam proyek yang dibuat oleh templat API web. - Pilih Coba.
- Pilih Jalankan. Responsnya adalah
401 - not authorized
.
Pendaftaran ujian
Perluas
/register
dan pilih Cobalah.Di bagian Parameter UI, isi permintaan sampel ditampilkan:
{ "email": "string", "password": "string" }
Ganti "string" dengan alamat email dan kata sandi yang valid, lalu pilih Jalankan.
Untuk mematuhi aturan validasi kata sandi default, panjang kata sandi harus setidaknya enam karakter dan berisi setidaknya satu dari masing-masing karakter berikut:
- Huruf besar
- Huruf kecil
- Angka
- Karakter non-alfanumerik
Jika Anda memasukkan alamat email yang tidak valid atau kata sandi yang buruk, hasilnya menyertakan kesalahan validasi. Berikut adalah contoh isi respons dengan kesalahan validasi:
{ "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1", "title": "One or more validation errors occurred.", "status": 400, "errors": { "PasswordTooShort": [ "Passwords must be at least 6 characters." ], "PasswordRequiresNonAlphanumeric": [ "Passwords must have at least one non alphanumeric character." ], "PasswordRequiresDigit": [ "Passwords must have at least one digit ('0'-'9')." ], "PasswordRequiresLower": [ "Passwords must have at least one lowercase ('a'-'z')." ] } }
Kesalahan dikembalikan dalam format ProblemDetails sehingga klien dapat mengurainya dan menampilkan kesalahan validasi sesuai kebutuhan.
Pendaftaran yang berhasil menghasilkan
200 - OK
respons.
Uji masuk
Perluas
/login
dan pilih Cobalah. Contoh isi permintaan menunjukkan dua parameter tambahan:{ "email": "string", "password": "string", "twoFactorCode": "string", "twoFactorRecoveryCode": "string" }
Properti JSON tambahan tidak diperlukan untuk contoh ini dan dapat dihapus. Atur
useCookies
ketrue
.Ganti "string" dengan alamat email dan kata sandi yang Anda gunakan untuk mendaftar, lalu pilih Jalankan.
Login yang berhasil menghasilkan
200 - OK
respons dengan cookie di header respons.
Coba lagi titik akhir aman
Setelah berhasil masuk, jalankan ulang titik akhir aman. Autentikasi cookie dikirim secara otomatis dengan permintaan, dan titik akhir diotorisasi. CookieAutentikasi berbasis aman bawaan ke browser dan "hanya berfungsi."
Pengujian dengan klien nonbrowser
Beberapa klien web mungkin tidak menyertakan cookie di header secara default:
Jika Anda menggunakan alat untuk menguji API, Anda mungkin perlu mengaktifkan cookie di pengaturan.
API JavaScript
fetch
tidak menyertakan cookie secara default. Aktifkan dengan mengaturcredentials
ke nilaiinclude
dalam opsi.HttpClient
yang berjalan dalam aplikasi Blazor WebAssembly perlu agarHttpRequestMessage
menyertakan kredensial, seperti contoh berikut:request.SetBrowserRequestCredential(BrowserRequestCredentials.Include);
Menggunakan autentikasi berbasis token
Sebaiknya gunakan cookie di aplikasi berbasis browser, karena, secara default, browser secara otomatis menanganinya tanpa mengeksposnya ke JavaScript.
Token kustom (yang merupakan milik platform identitas ASP.NET Core) dikeluarkan yang dapat digunakan untuk mengautentikasi permintaan berikutnya. Token diteruskan di Authorization
header sebagai token pembawa. Token refresh juga disediakan. Token ini memungkinkan aplikasi untuk meminta token baru ketika yang lama kedaluwarsa tanpa memaksa pengguna untuk masuk lagi.
Token bukan JSON Web Token standar (JWT). Penggunaan token kustom disengaja, karena API bawaan Identity dimaksudkan terutama untuk skenario sederhana. Opsi token tidak dimaksudkan untuk menjadi penyedia layanan identitas berfitur lengkap atau server token, tetapi sebagai alternatif untuk opsi cookie untuk klien yang tidak dapat menggunakan cookie.
Untuk menggunakan autentikasi berbasis token, atur useCookies
parameter string kueri ke false
saat memanggil /login
titik akhir. Token menggunakan skema autentikasi pembawa . Menggunakan token yang dikembalikan dari panggilan ke /login
, panggilan berikutnya ke titik akhir yang dilindungi harus menambahkan header Authorization: Bearer <token>
di mana <token>
adalah token akses. Untuk informasi selengkapnya, lihat gunakan POST /login
endpoint di artikel ini nanti.
Keluar Akun
Untuk menyediakan cara bagi pengguna untuk keluar, tentukan /logout
titik akhir seperti contoh berikut:
app.MapPost("/logout", async (SignInManager<IdentityUser> signInManager,
[FromBody] object empty) =>
{
if (empty != null)
{
await signInManager.SignOutAsync();
return Results.Ok();
}
return Results.Unauthorized();
})
.WithOpenApi()
.RequireAuthorization();
Berikan objek JSON kosong ({}
) di isi permintaan saat memanggil titik akhir ini. Kode berikut adalah contoh panggilan ke titik akhir keluar:
public signOut() {
return this.http.post('/logout', {}, {
withCredentials: true,
observe: 'response',
responseType: 'text'
Titik akhir MapIdentityApi<TUser>
Panggilan untuk MapIdentityApi<TUser>
menambahkan titik akhir berikut ke aplikasi:
POST /register
POST /login
POST /refresh
GET /confirmEmail
POST /resendConfirmationEmail
POST /forgotPassword
POST /resetPassword
POST /manage/2fa
GET /manage/info
POST /manage/info
Gunakan titik akhir POST /register
Isi permintaan harus memiliki properti Email dan Password
{
"email": "string",
"password": "string",
}
Untuk informasi selengkapnya, lihat:
- Pendaftaran uji sebelumnya dalam artikel ini.
- RegisterRequest.
Gunakan titik akhir POST /login
Dalam isi permintaan, Email dan Password diperlukan. Jika autentikasi dua faktor (2FA) diaktifkan, baik TwoFactorCode atau TwoFactorRecoveryCode diperlukan. Jika 2FA tidak diaktifkan, hilangkan keduanya twoFactorCode
dan twoFactorRecoveryCode
. Untuk informasi selengkapnya, lihat gunakan POST /manage/2fa
endpoint di artikel ini nanti.
Berikut adalah contoh isi permintaan dengan 2FA tidak diaktifkan:
{
"email": "string",
"password": "string"
}
Berikut adalah contoh isi permintaan dengan 2FA diaktifkan:
-
{ "email": "string", "password": "string", "twoFactorCode": "string", }
-
{ "email": "string", "password": "string", "twoFactorRecoveryCode": "string" }
Titik akhir menggunakan parameter string kueri:
-
useCookies
- Atur ketrue
untuk autentikasi berbasis cookie. Atur kefalse
atau hilangkan untuk autentikasi berbasis token.
Untuk informasi selengkapnya tentang autentikasi berbasis cookie, lihat pengujian login sebelumnya dalam artikel ini.
Autentikasi berbasis token
Jika useCookies
adalah false
atau dihilangkan, autentikasi berbasis token diaktifkan. Isi respons mencakup properti berikut:
{
"tokenType": "string",
"accessToken": "string",
"expiresIn": 0,
"refreshToken": "string"
}
Untuk informasi selengkapnya tentang properti ini, lihat AccessTokenResponse.
Letakkan token akses di header untuk membuat permintaan terautentikasi, seperti yang ditunjukkan dalam contoh berikut
Authorization: Bearer {access token}
Saat token akses hampir kedaluwarsa, panggil endpoint /refresh.
Gunakan titik akhir POST /refresh
Untuk digunakan hanya dengan autentikasi berbasis token. Mendapatkan token akses baru tanpa memaksa pengguna untuk masuk lagi. Panggil titik akhir ini saat token akses akan kedaluwarsa.
Isi permintaan hanya berisi RefreshToken. Berikut adalah contoh isi permintaan:
{
"refreshToken": "string"
}
Jika panggilan berhasil, isi respons adalah baru AccessTokenResponse, seperti yang ditunjukkan dalam contoh berikut:
{
"tokenType": "string",
"accessToken": "string",
"expiresIn": 0,
"refreshToken": "string"
}
Gunakan titik akhir GET /confirmEmail
Jika Identity disiapkan untuk konfirmasi email, panggilan yang berhasil ke /register
titik akhir akan mengirim email yang berisi tautan ke /confirmEmail
titik akhir. Tautan ini berisi parameter string kueri berikut.
userId
code
-
changedEmail
- Disertakan hanya jika pengguna mengubah alamat email selama pendaftaran.
Identity menyediakan teks default untuk email konfirmasi. Secara default, subjek email adalah "Konfirmasi email Anda" dan isi email terlihat seperti contoh berikut:
Please confirm your account by <a href='https://contoso.com/confirmEmail?userId={user ID}&code={generated code}&changedEmail={new email address}'>clicking here</a>.
RequireConfirmedEmail Jika properti diatur ke true
, pengguna tidak dapat masuk hingga alamat email dikonfirmasi dengan mengklik tautan dalam email. Titik /confirmEmail
akhir:
- Mengonfirmasi alamat email dan memungkinkan pengguna untuk masuk.
- Mengembalikan teks "Terima kasih telah mengonfirmasi email Anda." di isi respons.
Untuk menyiapkan Identity untuk konfirmasi email, tambahkan kode di Program.cs
untuk menyetel RequireConfirmedEmail
ke true
dan tambahkan kelas yang mengimplementasikan IEmailSender ke dalam kontainer DI. Contohnya:
builder.Services.Configure<IdentityOptions>(options =>
{
options.SignIn.RequireConfirmedEmail = true;
});
builder.Services.AddTransient<IEmailSender, EmailSender>();
Untuk informasi selengkapnya, lihat Konfirmasi akun dan pemulihan kata sandi di ASP.NET Core.
Identity menyediakan teks default untuk email lain yang perlu dikirim juga, seperti untuk 2FA dan pengaturan ulang kata sandi. Untuk menyesuaikan email ini, berikan implementasi antarmuka IEmailSender
kustom. Dalam contoh sebelumnya, EmailSender
adalah kelas yang mengimplementasikan IEmailSender
. Untuk informasi selengkapnya, termasuk contoh kelas yang menerapkan IEmailSender
, lihat Konfirmasi akun dan pemulihan kata sandi di ASP.NET Core.
Gunakan titik akhir POST /resendConfirmationEmail
Mengirim email hanya jika alamat tersebut valid untuk pengguna terdaftar.
Isi permintaan hanya berisi Email. Berikut adalah contoh isi permintaan:
{
"email": "string"
}
Untuk informasi selengkapnya, lihat Gunakan GET /confirmEmail
endpoint sebelumnya di artikel ini.
Gunakan titik akhir POST /forgotPassword
Menghasilkan email yang berisi kode reset kata sandi. Kirim kode tersebut ke /resetPassword
dengan kata sandi baru.
Isi permintaan hanya berisi Email. Berikut contohnya:
{
"email": "string"
}
Untuk informasi tentang cara mengaktifkan Identity untuk mengirim email, lihat Gunakan GET /confirmEmail
endpoint.
Gunakan titik akhir POST /resetPassword
Panggil titik akhir ini setelah mendapatkan kode reset dengan mengakses titik akhir /forgotPassword
.
Isi permintaan memerlukan Email, , ResetCodedan NewPassword. Berikut contohnya:
{
"email": "string",
"resetCode": "string",
"newPassword": "string"
}
Gunakan titik akhir POST /manage/2fa
Mengonfigurasi autentikasi dua faktor (2FA) untuk pengguna. Ketika 2FA diaktifkan, login yang berhasil memerlukan kode yang dihasilkan oleh aplikasi pengautentikasi selain alamat email dan kata sandi.
Aktifkan 2FA
Untuk mengaktifkan 2FA untuk pengguna yang saat ini diautentikasi:
/manage/2fa
Panggil titik akhir, kirim objek JSON kosong ({}
) di isi permintaan.Isi respons menyediakan SharedKey bersama dengan beberapa properti lain yang tidak diperlukan pada saat ini. Kunci bersama digunakan untuk menyiapkan aplikasi pengautentikasi. Contoh isi respons:
{ "sharedKey": "string", "recoveryCodesLeft": 0, "recoveryCodes": null, "isTwoFactorEnabled": false, "isMachineRemembered": false }
Gunakan kunci yang dibagikan untuk memperoleh kata sandi satu kali berbasis waktu (TOTP). Untuk informasi selengkapnya, lihat Mengaktifkan pembuatan kode QR untuk aplikasi pengautentikasi TOTP di ASP.NET Core.
/manage/2fa
Panggil titik akhir, kirim TOTP dan"enable": true
di isi permintaan. Contohnya:{ "enable": true, "twoFactorCode": "string" }
Isi respons mengonfirmasi bahwa IsTwoFactorEnabled itu benar dan menyediakan RecoveryCodes. Kode pemulihan digunakan untuk masuk saat aplikasi pengautentikasi tidak tersedia. Contoh isi respons setelah berhasil mengaktifkan 2FA:
{ "sharedKey": "string", "recoveryCodesLeft": 10, "recoveryCodes": [ "string", "string", "string", "string", "string", "string", "string", "string", "string", "string" ], "isTwoFactorEnabled": true, "isMachineRemembered": false }
Masuk dengan 2FA
/login
Panggil titik akhir, kirim alamat email, kata sandi, dan TOTP di isi permintaan. Contohnya:
{
"email": "string",
"password": "string",
"twoFactorCode": "string"
}
Jika pengguna tidak memiliki akses ke aplikasi pengautentikasi, login dengan memanggil endpoint /login
menggunakan salah satu kode pemulihan yang disediakan saat 2FA diaktifkan. Isi permintaan terlihat seperti contoh berikut:
{
"email": "string",
"password": "string",
"twoFactorRecoveryCode": "string"
}
Mengatur ulang kode pemulihan
Untuk mendapatkan kumpulan kode pemulihan baru, panggil titik akhir ini dengan ResetRecoveryCodes diatur ke true
. Berikut adalah contoh isi permintaan:
{
"resetRecoveryCodes": true
}
Mereset kunci bersama
Untuk memperoleh kunci bersama acak yang baru, panggil titik akhir ini dengan mengatur ResetSharedKey ke true
. Berikut adalah contoh isi permintaan:
{
"resetSharedKey": true
}
Mengatur ulang kunci secara otomatis menonaktifkan persyaratan masuk dua faktor untuk pengguna yang diautentikasi hingga diaktifkan kembali oleh permintaan selanjutnya.
Lupakan mesin
Untuk menghapus flag "ingat saya" jika ada, panggil endpoint ini dengan cookie diatur ke true. Berikut adalah contoh isi permintaan:
{
"forgetMachine": true
}
Titik akhir ini tidak berdampak pada autentikasi berbasis token.
Gunakan titik akhir GET /manage/info
Mendapatkan alamat email dan status konfirmasi email pengguna yang masuk. Klaim dihilangkan dari titik akhir ini karena alasan keamanan. Jika klaim diperlukan, gunakan API sisi server untuk menyiapkan titik akhir untuk klaim. Atau alih-alih membagikan semua klaim pengguna, berikan titik akhir validasi yang menerima klaim dan merespons apakah pengguna memilikinya.
Permintaan tidak memerlukan parameter apa pun. Isi respons mencakup properti Email dan IsEmailConfirmed, seperti dalam contoh berikut:
{
"email": "string",
"isEmailConfirmed": true
}
Gunakan titik akhir POST /manage/info
Memperbarui alamat email dan kata sandi pengguna yang masuk. Kirim NewEmail, NewPassword, dan OldPassword dalam isi permintaan, seperti yang ditunjukkan dalam contoh berikut:
{
"newEmail": "string",
"newPassword": "string",
"oldPassword": "string"
}
Berikut contoh isi responsnya:
{
"email": "string",
"isEmailConfirmed": false
}
Lihat juga
Untuk informasi selengkapnya, lihat sumber daya berikut:
- Memilih solusi manajemen identitas
- Identity solusi manajemen untuk aplikasi web .NET
- Otorisasi sederhana di ASP.NET Core
- Menambahkan, mengunduh, dan menghapus data pengguna ke Identity dalam proyek ASP.NET Core
- Membuat aplikasi ASP.NET Core dengan data pengguna yang dilindungi oleh otorisasi
- Konfirmasi akun dan pemulihan kata sandi di ASP.NET Core
- Mengaktifkan pembuatan Kode QR untuk aplikasi pengautentikasi TOTP di ASP.NET Core
-
Contoh backend API Web untuk SPAs File .http menunjukkan autentikasi berbasis token. Misalnya:
- Tidak diatur
useCookies
- Menggunakan header Otorisasi untuk meneruskan token
- Menampilkan refresh untuk memperpanjang sesi tanpa memaksa pengguna untuk masuk lagi
- Tidak diatur
- Sampel aplikasi Angular yang menggunakan Identity untuk mengamankan backend API Web
Templat ASP.NET Core menawarkan autentikasi di Aplikasi Halaman Tunggal (SPAs) menggunakan dukungan untuk otorisasi API. ASP.NET Core Identity untuk mengautentikasi dan menyimpan pengguna dikombinasikan dengan Duende Identity Server untuk menerapkan OpenID Connect.
Penting
Perangkat Lunak Duende mungkin mengharuskan Anda membayar biaya lisensi untuk penggunaan produksi Server Identity Duende. Untuk informasi selengkapnya, lihat Migrasi dari ASP.NET Core di .NET 5 ke .NET 6.
Parameter autentikasi ditambahkan ke templat proyek Angular dan React yang mirip dengan parameter autentikasi di templat proyek Aplikasi Web (Model-View-Controller) (MVC) dan Aplikasi Web (Razor Halaman). Nilai parameter yang diizinkan adalah Tidak Ada dan Individual. Templat proyek React.js dan Redux saat ini tidak mendukung parameter autentikasi.
Membuat aplikasi dengan dukungan otorisasi API
Autentikasi dan otorisasi pengguna dapat digunakan dengan Angular dan React SPAs. Buka shell perintah, dan jalankan perintah berikut:
Sudut:
dotnet new angular -au Individual
React:
dotnet new react -au Individual
Perintah sebelumnya membuat aplikasi ASP.NET Core dengan direktori ClientApp yang berisi SPA.
Deskripsi umum komponen ASP.NET Core aplikasi
Bagian berikut menjelaskan penambahan ke proyek saat dukungan autentikasi disertakan:
Program.cs
Contoh kode berikut mengandalkan paket NuGet Microsoft.AspNetCore.ApiAuthorization.IdentityServer . Contoh mengonfigurasi autentikasi dan otorisasi API menggunakan metode ekstensi AddApiAuthorization dan AddIdentityServerJwt. Proyek yang menggunakan templat proyek React atau Angular SPA dengan autentikasi menyertakan referensi ke paket ini.
dotnet new angular -au Individual
menghasilkan file berikut Program.cs
:
using Microsoft.AspNetCore.Authentication;
using Microsoft.EntityFrameworkCore;
using output_directory_name.Data;
using output_directory_name.Models;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlite(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
builder.Services.AddAuthentication()
.AddIdentityServerJwt();
builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseIdentityServer();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
app.MapRazorPages();
app.MapFallbackToFile("index.html");
app.Run();
Kode sebelumnya mengonfigurasi:
Identity dengan UI default:
builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlite(connectionString)); builder.Services.AddDatabaseDeveloperPageExceptionFilter(); builder.Services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores<ApplicationDbContext>();
IdentityServer dengan metode pembantu tambahan
AddApiAuthorization
yang menyiapkan beberapa konvensi ASP.NET Core default di atas IdentityServer:builder.Services.AddIdentityServer() .AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
Autentikasi dengan metode pembantu tambahan
AddIdentityServerJwt
yang mengonfigurasi aplikasi untuk memvalidasi token JWT yang diproduksi oleh IdentityServer:builder.Services.AddAuthentication() .AddIdentityServerJwt();
Middleware autentikasi yang bertanggung jawab untuk memvalidasi kredensial permintaan dan mengatur pengguna pada konteks permintaan:
app.UseAuthentication();
Middleware IdentityServer yang mengekspos titik akhir OpenID Connect:
app.UseIdentityServer();
Peringatan
Artikel ini memperlihatkan penggunaan string koneksi. Dengan database lokal, pengguna tidak perlu diautentikasi, tetapi dalam produksi, string koneksi terkadang menyertakan kata sandi untuk mengautentikasi. Kredensial kata sandi pemilik sumber daya (ROPC) adalah risiko keamanan yang harus dihindari dalam database produksi. Aplikasi produksi harus menggunakan alur autentikasi paling aman yang tersedia. Untuk informasi selengkapnya tentang autentikasi untuk aplikasi yang disebarkan untuk menguji atau lingkungan produksi, lihat Mengamankan alur autentikasi.
Azure App Service di Linux
Untuk penyebaran Azure App Service di Linux, tentukan penerbit secara eksplisit:
builder.Services.Configure<JwtBearerOptions>(
IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
options =>
{
options.Authority = "{AUTHORITY}";
});
Dalam kode sebelumnya, {AUTHORITY}
penanda adalah Authority yang dapat digunakan ketika melakukan panggilan OpenID Connect.
Contoh:
options.Authority = "https://contoso-service.azurewebsites.net";
AddApiAuthorization
Metode pembantu ini mengonfigurasi IdentityServer untuk menggunakan konfigurasi kami yang didukung. IdentityServer adalah kerangka kerja yang kuat dan dapat diperluas untuk menangani masalah keamanan aplikasi. Pada saat yang sama, ini menampilkan kompleksitas yang tidak perlu untuk skenario paling umum. Akibatnya, serangkaian konvensi dan opsi konfigurasi disediakan untuk Anda yang dianggap sebagai titik awal yang baik. Setelah autentikasi Anda perlu berubah, kekuatan penuh IdentityServer masih tersedia untuk menyesuaikan autentikasi agar sesuai dengan kebutuhan Anda.
AddIdentityServerJwt
Metode pembantu ini 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 "/Identity".
JwtBearerHandler
menangani semua permintaan lainnya. Selain itu, metode ini mendaftarkan <<ApplicationName>>API
sumber daya API dengan IdentityServer dengan cakupan <<ApplicationName>>API
default dan mengonfigurasi middleware token Pembawa JWT untuk memvalidasi token yang dikeluarkan oleh IdentityServer untuk aplikasi.
WeatherForecastController
Dalam file, perhatikan [Authorize]
atribut yang diterapkan ke kelas yang menunjukkan bahwa pengguna perlu diotorisasi berdasarkan kebijakan default untuk mengakses sumber daya. Kebijakan otorisasi default kebetulan dikonfigurasi untuk menggunakan skema autentikasi default, yang disiapkan oleh AddIdentityServerJwt
ke skema kebijakan yang disebutkan di atas, menjadikan JwtBearerHandler
dikonfigurasi oleh metode pembantu tersebut sebagai handler default untuk permintaan ke aplikasi.
ApplicationDbContext
Dalam file, perhatikan bahwa DbContext
yang sama digunakan dalam Identity, kecuali bahwa ia memperluas ApiAuthorizationDbContext
(kelas yang lebih diturunkan dari IdentityDbContext
) untuk menyertakan skema untuk IdentityServer.
Untuk mendapatkan kendali penuh atas skema database, warisi dari salah satu kelas yang tersedia IdentityDbContext
dan konfigurasikan konteks untuk menyertakan skema Identity dengan memanggil metode builder.ConfigurePersistedGrantContext(_operationalStoreOptions.Value)
pada OnModelCreating
.
OidcConfigurationController
Dalam file, perhatikan titik akhir yang disediakan untuk melayani parameter OIDC yang perlu digunakan klien.
appsettings.json
appsettings.json
Dalam file akar proyek, ada bagian baru IdentityServer
yang menjelaskan daftar klien yang dikonfigurasi. Dalam contoh berikut, ada satu klien. Nama klien sesuai dengan nama aplikasi dan dipetakan berdasarkan konvensi ke parameter OAuth ClientId
. Profil menunjukkan jenis aplikasi yang sedang dikonfigurasi. Ini digunakan secara internal untuk mendorong konvensi yang menyederhanakan proses konfigurasi untuk server. Ada beberapa profil yang tersedia, seperti yang dijelaskan di bagian Profil aplikasi.
"IdentityServer": {
"Clients": {
"angularindividualpreview3final": {
"Profile": "IdentityServerSPA"
}
}
}
appsettings.Development.json
appsettings.Development.json
Dalam file akar proyek, ada IdentityServer
bagian yang menjelaskan kunci yang digunakan untuk menandatangani token. Saat menyebarkan ke produksi, kunci perlu disediakan dan disebarkan bersama aplikasi, seperti yang dijelaskan di bagian Sebarkan ke produksi .
"IdentityServer": {
"Key": {
"Type": "Development"
}
}
Deskripsi umum aplikasi Angular
Dukungan autentikasi dan otorisasi API dalam templat Angular berada dalam modul Angularnya sendiri di direktori ClientApp/src/api-authorization . Modul ini terdiri dari elemen-elemen berikut:
- 3 komponen:
-
login.component.ts
: Menangani alur masuk aplikasi. -
logout.component.ts
: Menangani alur keluar aplikasi. -
login-menu.component.ts
: Widget yang menampilkan salah satu set tautan berikut:- Manajemen profil pengguna dan tautan keluar saat pengguna diautentikasi.
- Tautan pendaftaran dan masuk saat pengguna tidak diautentikasi.
-
- Perlindungan rute
AuthorizeGuard
yang dapat ditambahkan ke rute dan mengharuskan pengguna untuk diautentikasi sebelum mengunjungi rute. - Pencegat
AuthorizeInterceptor
HTTP yang melampirkan token akses ke permintaan HTTP keluar yang menargetkan API saat pengguna diautentikasi. - Layanan
AuthorizeService
yang menangani detail tingkat bawah proses autentikasi dan mengekspos informasi tentang pengguna yang diautentikasi ke aplikasi lainnya untuk dikonsumsi. - Modul Angular yang menentukan rute yang terkait dengan bagian autentikasi aplikasi. Ini mengekspos komponen menu login, interseptor, perlindungan, dan layanan untuk dikonsumsi dari seluruh aplikasi.
Deskripsi umum aplikasi React
Dukungan untuk autentikasi dan otorisasi API di templat React berada di direktori ClientApp/src/components/api-authorization . Ini terdiri dari elemen-elemen berikut:
- 4 komponen:
-
Login.js
: Menangani alur masuk aplikasi. -
Logout.js
: Menangani alur keluar aplikasi. -
LoginMenu.js
: Widget yang menampilkan salah satu set tautan berikut:- Manajemen profil pengguna dan tautan keluar saat pengguna diautentikasi.
- Tautan pendaftaran dan masuk saat pengguna tidak diautentikasi.
-
AuthorizeRoute.js
: Komponen rute yang mengharuskan pengguna diautentikasi sebelum merender komponen yang ditunjukkan dalamComponent
parameter .
-
- Instans
authService
dari kelasAuthorizeService
yang diekspor, menangani detail teknis proses autentikasi dan mengekspos informasi tentang pengguna yang telah diautentikasi untuk digunakan oleh bagian lain dari aplikasi.
Sekarang setelah Anda melihat komponen utama solusi, Anda dapat melihat skenario individual yang lebih dalam untuk aplikasi.
Memerlukan otorisasi pada API baru
Secara default, sistem dikonfigurasi untuk dengan mudah memerlukan otorisasi untuk API baru. Untuk melakukannya, buat pengontrol baru dan tambahkan [Authorize]
atribut ke kelas pengontrol atau ke tindakan apa pun dalam pengontrol.
Menyesuaikan pengelola autentikasi API
Untuk menyesuaikan konfigurasi handler JWT API, konfigurasikan instansnya JwtBearerOptions :
builder.Services.AddAuthentication()
.AddIdentityServerJwt();
builder.Services.Configure<JwtBearerOptions>(
IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
options =>
{
...
});
Handler JWT API memicu peristiwa yang memungkinkan kontrol atas proses otentikasi menggunakan JwtBearerEvents
. Untuk memberikan dukungan untuk otorisasi API, AddIdentityServerJwt
mendaftarkan pengendali acaranya sendiri.
Untuk menyesuaikan penanganan peristiwa, bungkus penanganan aktivitas yang ada dengan logika tambahan sesuai kebutuhan. Contohnya:
builder.Services.Configure<JwtBearerOptions>(
IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
options =>
{
var onTokenValidated = options.Events.OnTokenValidated;
options.Events.OnTokenValidated = async context =>
{
await onTokenValidated(context);
...
}
});
Dalam kode sebelumnya, pengendali acara OnTokenValidated
diganti dengan implementasi kustom. Implementasi ini:
- Memanggil implementasi asli yang disediakan oleh dukungan otorisasi API.
- Jalankan logika kustomnya sendiri.
Melindungi rute sisi klien (Angular)
Melindungi rute sisi klien dilakukan dengan menambahkan perlindungan otorisasi ke daftar perlindungan untuk dijalankan saat mengonfigurasi rute. Sebagai contoh, Anda dapat melihat bagaimana rute dikonfigurasi dalam modul utama aplikasi Angular: fetch-data
RouterModule.forRoot([
// ...
{ path: 'fetch-data', component: FetchDataComponent, canActivate: [AuthorizeGuard] },
])
Penting untuk disebutkan bahwa melindungi rute tidak melindungi titik akhir aktual (yang masih memerlukan atribut yang [Authorize]
diterapkan padanya) tetapi hanya mencegah pengguna menavigasi ke rute sisi klien yang diberikan saat tidak diautentikasi.
Mengautentikasi permintaan API (Angular)
Mengautentikasi permintaan ke API yang dihosting bersama aplikasi dilakukan secara otomatis melalui penggunaan pencegat klien HTTP yang ditentukan oleh aplikasi.
Melindungi rute sisi klien (React)
Lindungi rute sisi klien dengan menggunakan AuthorizeRoute
komponen alih-alih komponen biasa Route
. Misalnya, perhatikan bagaimana rute fetch-data
dikonfigurasi dalam komponen App
.
<AuthorizeRoute path='/fetch-data' component={FetchData} />
Melindungi rute:
- Tidak melindungi titik akhir aktual (yang masih memerlukan atribut
[Authorize]
diterapkan padanya). - Hanya mencegah pengguna menavigasi ke rute sisi klien yang diberikan saat tidak diautentikasi.
Mengautentikasi permintaan API (React)
Mengautentikasi permintaan dengan React dilakukan dengan terlebih dahulu mengimpor authService
instans dari AuthorizeService
. Token akses diambil dari authService
dan dilampirkan ke permintaan seperti yang ditunjukkan di bawah ini. Dalam komponen React, pekerjaan ini biasanya dilakukan dalam componentDidMount
metode siklus hidup atau sebagai hasil dari beberapa interaksi pengguna.
Mengimpor authService
ke dalam komponen
import authService from './api-authorization/AuthorizeService'
Mengambil dan melampirkan token akses ke respons
async populateWeatherData() {
const token = await authService.getAccessToken();
const response = await fetch('api/SampleData/WeatherForecasts', {
headers: !token ? {} : { 'Authorization': `Bearer ${token}` }
});
const data = await response.json();
this.setState({ forecasts: data, loading: false });
}
Menyebarkan ke lingkungan produksi
Untuk menyebarkan aplikasi ke produksi, sumber daya berikut perlu disediakan:
- Basis data untuk menyimpan Identity akun pengguna dan izin dari IdentityServer.
- Sertifikat produksi yang digunakan untuk menandatangani token.
- Tidak ada persyaratan khusus untuk sertifikat ini; dapat berupa sertifikat yang ditandatangani sendiri atau sertifikat yang disediakan melalui otoritas CA.
- Ini dapat dihasilkan melalui alat standar seperti PowerShell atau OpenSSL.
- Ini dapat diinstal ke penyimpanan sertifikat pada komputer target atau disebarkan sebagai file .pfx dengan kata sandi yang kuat.
Contoh: Menyebarkan ke penyedia hosting web non-Azure
Di panel hosting web Anda, buat atau muat sertifikat Anda. Kemudian dalam file aplikasi appsettings.json
, ubah bagian IdentityServer
untuk menyertakan detail utama. Contohnya:
"IdentityServer": {
"Key": {
"Type": "Store",
"StoreName": "WebHosting",
"StoreLocation": "CurrentUser",
"Name": "CN=MyApplication"
}
}
Dalam contoh sebelumnya:
-
StoreName
mewakili nama penyimpanan sertifikat tempat sertifikat disimpan. Dalam hal ini, menunjuk ke toko hosting web. -
StoreLocation
mewakili tempat memuat sertifikat dari (CurrentUser
dalam hal ini). -
Name
sesuai dengan subjek khusus untuk sertifikat.
Contoh: Menyebarkan ke Azure App Service
Bagian ini menjelaskan penyebaran aplikasi ke Azure App Service menggunakan sertifikat yang disimpan di penyimpanan sertifikat. Untuk memodifikasi aplikasi untuk memuat sertifikat dari penyimpanan sertifikat, paket layanan tingkat Standar atau lebih baik diperlukan saat Anda mengonfigurasi aplikasi di portal Azure di langkah selanjutnya.
Dalam file aplikasi appsettings.json
, ubah bagian IdentityServer
untuk menyertakan detail utama:
"IdentityServer": {
"Key": {
"Type": "Store",
"StoreName": "My",
"StoreLocation": "CurrentUser",
"Name": "CN=MyApplication"
}
}
- Nama toko mewakili nama penyimpanan sertifikat tempat sertifikat disimpan. Dalam hal ini, ini menunjuk ke penyimpanan pengguna pribadi.
- Lokasi penyimpanan mewakili tempat memuat sertifikat dari (
CurrentUser
atauLocalMachine
). - Properti nama pada sertifikat sesuai dengan subjek khusus untuk sertifikat.
Untuk menyebarkan ke Azure App Service, ikuti langkah-langkah dalam Menyebarkan aplikasi ke Azure, yang menjelaskan cara membuat sumber daya Azure yang diperlukan dan menyebarkan aplikasi ke produksi.
Setelah mengikuti instruksi sebelumnya, aplikasi disebarkan ke Azure tetapi belum berfungsi. Sertifikat yang digunakan oleh aplikasi harus dikonfigurasi di portal Azure. Temukan thumbprint untuk sertifikat dan ikuti langkah-langkah yang dijelaskan dalam Memuat sertifikat Anda.
Meskipun langkah-langkah ini menyebutkan SSL, ada bagian Sertifikat privat di portal Azure tempat Anda dapat mengunggah sertifikat yang disediakan untuk digunakan dengan aplikasi.
Setelah mengonfigurasi aplikasi dan pengaturan aplikasi di portal Azure, mulai ulang aplikasi di portal.
Opsi konfigurasi lainnya
Dukungan untuk otorisasi API dibangun di atas IdentityServer dengan serangkaian konvensi, nilai default, dan peningkatan untuk menyederhanakan pengalaman untuk SPAs. Tidak perlu dikatakan, kekuatan penuh IdentityServer tersedia di belakang layar jika integrasi ASP.NET Core tidak mencakup skenario Anda. Dukungan ASP.NET Core difokuskan pada aplikasi "pihak pertama", tempat semua aplikasi dibuat dan disebarkan oleh organisasi kami. Dengan demikian, dukungan tidak ditawarkan untuk hal-hal seperti persetujuan atau federasi. Untuk skenario tersebut, gunakan IdentityServer dan ikuti dokumentasinya.
Profil aplikasi
Profil aplikasi adalah konfigurasi yang telah ditentukan sebelumnya untuk aplikasi yang lebih menentukan parameternya. Saat ini, profil berikut didukung:
-
IdentityServerSPA
: Mewakili SPA yang dihosting bersama IdentityServer sebagai satu unit.- Secara default,
redirect_uri
diatur ulang ke/authentication/login-callback
. - Secara default,
post_logout_redirect_uri
diatur ulang ke/authentication/logout-callback
. - Kumpulan cakupan mencakup
openid
, ,profile
dan setiap cakupan yang ditentukan untuk API di aplikasi. - Kumpulan jenis respons OIDC yang diizinkan adalah
id_token token
atau masing-masing secara individual (id_token
,token
). - Mode respons yang diizinkan adalah
fragment
.
- Secara default,
-
SPA
: Mewakili SPA yang tidak dihosting dengan IdentityServer.- Kumpulan cakupan mencakup
openid
, ,profile
dan setiap cakupan yang ditentukan untuk API di aplikasi. - Kumpulan jenis respons OIDC yang diizinkan adalah
id_token token
atau masing-masing secara individual (id_token
,token
). - Mode respons yang diizinkan adalah
fragment
.
- Kumpulan cakupan mencakup
-
IdentityServerJwt
: Mewakili API yang dihosting bersama dengan IdentityServer.- Aplikasi ini dikonfigurasi untuk memiliki satu cakupan yang secara default mengarah ke nama aplikasi.
-
API
: Mewakili API yang tidak dihosting dengan IdentityServer.- Aplikasi ini dikonfigurasi untuk memiliki satu cakupan yang secara default mengarah ke nama aplikasi.
Konfigurasi melalui AppSettings
Konfigurasikan aplikasi melalui sistem konfigurasi dengan menambahkannya ke daftar Clients
atau Resources
.
Konfigurasikan properti redirect_uri
dan post_logout_redirect_uri
untuk setiap klien, seperti yang ditunjukkan dalam contoh berikut:
"IdentityServer": {
"Clients": {
"MySPA": {
"Profile": "SPA",
"RedirectUri": "https://www.example.com/authentication/login-callback",
"LogoutUri": "https://www.example.com/authentication/logout-callback"
}
}
}
Saat mengonfigurasi sumber daya, Anda dapat mengonfigurasi cakupan untuk sumber daya seperti yang ditunjukkan di bawah ini:
"IdentityServer": {
"Resources": {
"MyExternalApi": {
"Profile": "API",
"Scopes": "a b c"
}
}
}
Konfigurasi melalui kode
Anda juga dapat mengonfigurasi klien dan sumber daya melalui kode menggunakan kelebihan beban AddApiAuthorization
yang mengambil tindakan untuk mengonfigurasi opsi.
AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options =>
{
options.Clients.AddSPA(
"My SPA", spa =>
spa.WithRedirectUri("http://www.example.com/authentication/login-callback")
.WithLogoutRedirectUri(
"http://www.example.com/authentication/logout-callback"));
options.ApiResources.AddApiResource("MyExternalApi", resource =>
resource.WithScopes("a", "b", "c"));
});
Sumber Daya Tambahan:
Templat ASP.NET Core 3.1 atau yang lebih baru menawarkan autentikasi di Aplikasi Halaman Tunggal (SPAs) menggunakan dukungan untuk otorisasi API. ASP.NET Core Identity untuk mengautentikasi dan menyimpan pengguna dikombinasikan dengan IdentityServer untuk menerapkan OpenID Connect.
Parameter autentikasi ditambahkan ke templat proyek Angular dan React yang mirip dengan parameter autentikasi di templat proyek Aplikasi Web (Model-View-Controller) (MVC) dan Aplikasi Web (Razor Halaman). Nilai parameter yang diizinkan adalah Tidak Ada dan Individual. Templat proyek React.js dan Redux saat ini tidak mendukung parameter autentikasi.
Membuat aplikasi dengan dukungan otorisasi API
Autentikasi dan otorisasi pengguna dapat digunakan dengan Angular dan React SPAs. Buka shell perintah, dan jalankan perintah berikut:
Sudut:
dotnet new angular -o <output_directory_name>
React:
dotnet new react -o <output_directory_name> -au Individual
Perintah sebelumnya membuat aplikasi ASP.NET Core dengan direktori ClientApp yang berisi SPA.
Deskripsi umum komponen ASP.NET Core aplikasi
Bagian berikut menjelaskan penambahan ke proyek saat dukungan autentikasi disertakan:
Startup
kelas
Contoh kode berikut mengandalkan paket NuGet Microsoft.AspNetCore.ApiAuthorization.IdentityServer . Contoh mengonfigurasi autentikasi dan otorisasi API menggunakan metode ekstensi AddApiAuthorization dan AddIdentityServerJwt. Proyek yang menggunakan templat proyek React atau Angular SPA dengan autentikasi menyertakan referensi ke paket ini.
Kelas Startup
memiliki penambahan berikut:
Di dalam metode
Startup.ConfigureServices
:Identity dengan UI default:
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlite(Configuration.GetConnectionString("DefaultConnection"))); services.AddDefaultIdentity<ApplicationUser>() .AddEntityFrameworkStores<ApplicationDbContext>();
IdentityServer dengan metode pembantu tambahan
AddApiAuthorization
yang menyiapkan beberapa konvensi ASP.NET Core default di atas IdentityServer:services.AddIdentityServer() .AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
Autentikasi dengan metode pembantu tambahan
AddIdentityServerJwt
yang mengonfigurasi aplikasi untuk memvalidasi token JWT yang diproduksi oleh IdentityServer:services.AddAuthentication() .AddIdentityServerJwt();
Di dalam metode
Startup.Configure
:Middleware autentikasi yang bertanggung jawab untuk memvalidasi kredensial permintaan dan mengatur pengguna pada konteks permintaan:
app.UseAuthentication();
Middleware IdentityServer yang mengekspos titik akhir OpenID Connect:
app.UseIdentityServer();
Peringatan
Artikel ini memperlihatkan penggunaan string koneksi. Dengan database lokal, pengguna tidak perlu diautentikasi, tetapi dalam produksi, string koneksi terkadang menyertakan kata sandi untuk mengautentikasi. Kredensial kata sandi pemilik sumber daya (ROPC) adalah risiko keamanan yang harus dihindari dalam database produksi. Aplikasi produksi harus menggunakan alur autentikasi paling aman yang tersedia. Untuk informasi selengkapnya tentang autentikasi untuk aplikasi yang disebarkan untuk menguji atau lingkungan produksi, lihat Mengamankan alur autentikasi.
Azure App Service di Linux
Untuk penyebaran Azure App Service di Linux, tentukan penerbit secara eksplisit di Startup.ConfigureServices
:
services.Configure<JwtBearerOptions>(
IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
options =>
{
options.Authority = "{AUTHORITY}";
});
Dalam kode sebelumnya, {AUTHORITY}
penanda adalah Authority yang dapat digunakan ketika melakukan panggilan OpenID Connect.
Contoh:
options.Authority = "https://contoso-service.azurewebsites.net";
AddApiAuthorization
Metode pembantu ini mengonfigurasi IdentityServer untuk menggunakan konfigurasi kami yang didukung. IdentityServer adalah kerangka kerja yang kuat dan dapat diperluas untuk menangani masalah keamanan aplikasi. Pada saat yang sama, ini menampilkan kompleksitas yang tidak perlu untuk skenario paling umum. Akibatnya, serangkaian konvensi dan opsi konfigurasi disediakan untuk Anda yang dianggap sebagai titik awal yang baik. Setelah autentikasi Anda perlu berubah, kekuatan penuh IdentityServer masih tersedia untuk menyesuaikan autentikasi agar sesuai dengan kebutuhan Anda.
AddIdentityServerJwt
Metode pembantu ini 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 "/Identity".
JwtBearerHandler
menangani semua permintaan lainnya. Selain itu, metode ini mendaftarkan <<ApplicationName>>API
sumber daya API dengan IdentityServer dengan cakupan <<ApplicationName>>API
default dan mengonfigurasi middleware token Pembawa JWT untuk memvalidasi token yang dikeluarkan oleh IdentityServer untuk aplikasi.
WeatherForecastController
Dalam file, perhatikan [Authorize]
atribut yang diterapkan ke kelas yang menunjukkan bahwa pengguna perlu diotorisasi berdasarkan kebijakan default untuk mengakses sumber daya. Kebijakan otorisasi default kebetulan dikonfigurasi untuk menggunakan skema autentikasi default, yang disiapkan oleh AddIdentityServerJwt
ke skema kebijakan yang disebutkan di atas, menjadikan JwtBearerHandler
dikonfigurasi oleh metode pembantu tersebut sebagai handler default untuk permintaan ke aplikasi.
ApplicationDbContext
Dalam file, perhatikan bahwa DbContext
yang sama digunakan dalam Identity, kecuali bahwa ia memperluas ApiAuthorizationDbContext
(kelas yang lebih diturunkan dari IdentityDbContext
) untuk menyertakan skema untuk IdentityServer.
Untuk mendapatkan kendali penuh atas skema database, warisi dari salah satu kelas yang tersedia IdentityDbContext
dan konfigurasikan konteks untuk menyertakan skema Identity dengan memanggil metode builder.ConfigurePersistedGrantContext(_operationalStoreOptions.Value)
pada OnModelCreating
.
OidcConfigurationController
Dalam file, perhatikan titik akhir yang disediakan untuk melayani parameter OIDC yang perlu digunakan klien.
appsettings.json
appsettings.json
Dalam file akar proyek, ada bagian baru IdentityServer
yang menjelaskan daftar klien yang dikonfigurasi. Dalam contoh berikut, ada satu klien. Nama klien sesuai dengan nama aplikasi dan dipetakan berdasarkan konvensi ke parameter OAuth ClientId
. Profil menunjukkan jenis aplikasi yang sedang dikonfigurasi. Ini digunakan secara internal untuk mendorong konvensi yang menyederhanakan proses konfigurasi untuk server. Ada beberapa profil yang tersedia, seperti yang dijelaskan di bagian Profil aplikasi.
"IdentityServer": {
"Clients": {
"angularindividualpreview3final": {
"Profile": "IdentityServerSPA"
}
}
}
appsettings.Development.json
appsettings.Development.json
Dalam file akar proyek, ada IdentityServer
bagian yang menjelaskan kunci yang digunakan untuk menandatangani token. Saat menyebarkan ke produksi, kunci perlu disediakan dan disebarkan bersama aplikasi, seperti yang dijelaskan di bagian Sebarkan ke produksi .
"IdentityServer": {
"Key": {
"Type": "Development"
}
}
Deskripsi umum aplikasi Angular
Dukungan autentikasi dan otorisasi API dalam templat Angular berada dalam modul Angularnya sendiri di direktori ClientApp/src/api-authorization . Modul ini terdiri dari elemen-elemen berikut:
- 3 komponen:
-
login.component.ts
: Menangani alur masuk aplikasi. -
logout.component.ts
: Menangani alur keluar aplikasi. -
login-menu.component.ts
: Widget yang menampilkan salah satu set tautan berikut:- Manajemen profil pengguna dan tautan keluar saat pengguna diautentikasi.
- Tautan pendaftaran dan masuk saat pengguna tidak diautentikasi.
-
- Perlindungan rute
AuthorizeGuard
yang dapat ditambahkan ke rute dan mengharuskan pengguna untuk diautentikasi sebelum mengunjungi rute. - Pencegat
AuthorizeInterceptor
HTTP yang melampirkan token akses ke permintaan HTTP keluar yang menargetkan API saat pengguna diautentikasi. - Layanan
AuthorizeService
yang menangani detail tingkat bawah proses autentikasi dan mengekspos informasi tentang pengguna yang diautentikasi ke aplikasi lainnya untuk dikonsumsi. - Modul Angular yang menentukan rute yang terkait dengan bagian autentikasi aplikasi. Ini mengekspos komponen menu login, interseptor, perlindungan, dan layanan untuk dikonsumsi dari seluruh aplikasi.
Deskripsi umum aplikasi React
Dukungan untuk autentikasi dan otorisasi API di templat React berada di direktori ClientApp/src/components/api-authorization . Ini terdiri dari elemen-elemen berikut:
- 4 komponen:
-
Login.js
: Menangani alur masuk aplikasi. -
Logout.js
: Menangani alur keluar aplikasi. -
LoginMenu.js
: Widget yang menampilkan salah satu set tautan berikut:- Manajemen profil pengguna dan tautan keluar saat pengguna diautentikasi.
- Tautan pendaftaran dan masuk saat pengguna tidak diautentikasi.
-
AuthorizeRoute.js
: Komponen rute yang mengharuskan pengguna diautentikasi sebelum merender komponen yang ditunjukkan dalamComponent
parameter .
-
- Instans
authService
dari kelasAuthorizeService
yang diekspor, menangani detail teknis proses autentikasi dan mengekspos informasi tentang pengguna yang telah diautentikasi untuk digunakan oleh bagian lain dari aplikasi.
Sekarang setelah Anda melihat komponen utama solusi, Anda dapat melihat skenario individual yang lebih dalam untuk aplikasi.
Memerlukan otorisasi pada API baru
Secara default, sistem dikonfigurasi untuk dengan mudah memerlukan otorisasi untuk API baru. Untuk melakukannya, buat pengontrol baru dan tambahkan [Authorize]
atribut ke kelas pengontrol atau ke tindakan apa pun dalam pengontrol.
Menyesuaikan pengelola autentikasi API
Untuk menyesuaikan konfigurasi handler JWT API, konfigurasikan instansnya JwtBearerOptions :
services.AddAuthentication()
.AddIdentityServerJwt();
services.Configure<JwtBearerOptions>(
IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
options =>
{
...
});
Handler JWT API memicu peristiwa yang memungkinkan kontrol atas proses otentikasi menggunakan JwtBearerEvents
. Untuk memberikan dukungan untuk otorisasi API, AddIdentityServerJwt
mendaftarkan pengendali acaranya sendiri.
Untuk menyesuaikan penanganan peristiwa, bungkus penanganan aktivitas yang ada dengan logika tambahan sesuai kebutuhan. Contohnya:
services.Configure<JwtBearerOptions>(
IdentityServerJwtConstants.IdentityServerJwtBearerScheme,
options =>
{
var onTokenValidated = options.Events.OnTokenValidated;
options.Events.OnTokenValidated = async context =>
{
await onTokenValidated(context);
...
}
});
Dalam kode sebelumnya, pengendali acara OnTokenValidated
diganti dengan implementasi kustom. Implementasi ini:
- Memanggil implementasi asli yang disediakan oleh dukungan otorisasi API.
- Jalankan logika kustomnya sendiri.
Melindungi rute sisi klien (Angular)
Melindungi rute sisi klien dilakukan dengan menambahkan perlindungan otorisasi ke daftar perlindungan untuk dijalankan saat mengonfigurasi rute. Sebagai contoh, Anda dapat melihat bagaimana rute dikonfigurasi dalam modul utama aplikasi Angular: fetch-data
RouterModule.forRoot([
// ...
{ path: 'fetch-data', component: FetchDataComponent, canActivate: [AuthorizeGuard] },
])
Penting untuk disebutkan bahwa melindungi rute tidak melindungi titik akhir aktual (yang masih memerlukan atribut yang [Authorize]
diterapkan padanya) tetapi hanya mencegah pengguna menavigasi ke rute sisi klien yang diberikan saat tidak diautentikasi.
Mengautentikasi permintaan API (Angular)
Mengautentikasi permintaan ke API yang dihosting bersama aplikasi dilakukan secara otomatis melalui penggunaan pencegat klien HTTP yang ditentukan oleh aplikasi.
Melindungi rute sisi klien (React)
Lindungi rute sisi klien dengan menggunakan AuthorizeRoute
komponen alih-alih komponen biasa Route
. Misalnya, perhatikan bagaimana rute fetch-data
dikonfigurasi dalam komponen App
.
<AuthorizeRoute path='/fetch-data' component={FetchData} />
Melindungi rute:
- Tidak melindungi titik akhir aktual (yang masih memerlukan atribut
[Authorize]
diterapkan padanya). - Hanya mencegah pengguna menavigasi ke rute sisi klien yang diberikan saat tidak diautentikasi.
Mengautentikasi permintaan API (React)
Mengautentikasi permintaan dengan React dilakukan dengan terlebih dahulu mengimpor authService
instans dari AuthorizeService
. Token akses diambil dari authService
dan dilampirkan ke permintaan seperti yang ditunjukkan di bawah ini. Dalam komponen React, pekerjaan ini biasanya dilakukan dalam componentDidMount
metode siklus hidup atau sebagai hasil dari beberapa interaksi pengguna.
Mengimpor authService
ke dalam komponen
import authService from './api-authorization/AuthorizeService'
Mengambil dan melampirkan token akses ke respons
async populateWeatherData() {
const token = await authService.getAccessToken();
const response = await fetch('api/SampleData/WeatherForecasts', {
headers: !token ? {} : { 'Authorization': `Bearer ${token}` }
});
const data = await response.json();
this.setState({ forecasts: data, loading: false });
}
Menyebarkan ke lingkungan produksi
Untuk menyebarkan aplikasi ke produksi, sumber daya berikut perlu disediakan:
- Basis data untuk menyimpan Identity akun pengguna dan izin dari IdentityServer.
- Sertifikat produksi yang digunakan untuk menandatangani token.
- Tidak ada persyaratan khusus untuk sertifikat ini; dapat berupa sertifikat yang ditandatangani sendiri atau sertifikat yang disediakan melalui otoritas CA.
- Ini dapat dihasilkan melalui alat standar seperti PowerShell atau OpenSSL.
- Ini dapat diinstal ke penyimpanan sertifikat pada komputer target atau disebarkan sebagai file .pfx dengan kata sandi yang kuat.
Contoh: Menyebarkan ke penyedia hosting web non-Azure
Di panel hosting web Anda, buat atau muat sertifikat Anda. Kemudian dalam file aplikasi appsettings.json
, ubah bagian IdentityServer
untuk menyertakan detail utama. Contohnya:
"IdentityServer": {
"Key": {
"Type": "Store",
"StoreName": "WebHosting",
"StoreLocation": "CurrentUser",
"Name": "CN=MyApplication"
}
}
Dalam contoh sebelumnya:
-
StoreName
mewakili nama penyimpanan sertifikat tempat sertifikat disimpan. Dalam hal ini, menunjuk ke toko hosting web. -
StoreLocation
mewakili tempat memuat sertifikat dari (CurrentUser
dalam hal ini). -
Name
sesuai dengan subjek khusus untuk sertifikat.
Contoh: Menyebarkan ke Azure App Service
Bagian ini menjelaskan penyebaran aplikasi ke Azure App Service menggunakan sertifikat yang disimpan di penyimpanan sertifikat. Untuk memodifikasi aplikasi untuk memuat sertifikat dari penyimpanan sertifikat, paket layanan tingkat Standar atau lebih baik diperlukan saat Anda mengonfigurasi aplikasi di portal Azure di langkah selanjutnya.
Dalam file aplikasi appsettings.json
, ubah bagian IdentityServer
untuk menyertakan detail utama:
"IdentityServer": {
"Key": {
"Type": "Store",
"StoreName": "My",
"StoreLocation": "CurrentUser",
"Name": "CN=MyApplication"
}
}
- Nama toko mewakili nama penyimpanan sertifikat tempat sertifikat disimpan. Dalam hal ini, ini menunjuk ke penyimpanan pengguna pribadi.
- Lokasi penyimpanan mewakili tempat memuat sertifikat dari (
CurrentUser
atauLocalMachine
). - Properti nama pada sertifikat sesuai dengan subjek khusus untuk sertifikat.
Untuk menyebarkan ke Azure App Service, ikuti langkah-langkah dalam Menyebarkan aplikasi ke Azure, yang menjelaskan cara membuat sumber daya Azure yang diperlukan dan menyebarkan aplikasi ke produksi.
Setelah mengikuti instruksi sebelumnya, aplikasi disebarkan ke Azure tetapi belum berfungsi. Sertifikat yang digunakan oleh aplikasi harus dikonfigurasi di portal Azure. Temukan thumbprint untuk sertifikat dan ikuti langkah-langkah yang dijelaskan dalam Memuat sertifikat Anda.
Meskipun langkah-langkah ini menyebutkan SSL, ada bagian Sertifikat privat di portal Azure tempat Anda dapat mengunggah sertifikat yang disediakan untuk digunakan dengan aplikasi.
Setelah mengonfigurasi aplikasi dan pengaturan aplikasi di portal Azure, mulai ulang aplikasi di portal.
Opsi konfigurasi lainnya
Dukungan untuk otorisasi API dibangun di atas IdentityServer dengan serangkaian konvensi, nilai default, dan peningkatan untuk menyederhanakan pengalaman untuk SPAs. Tidak perlu dikatakan, kekuatan penuh IdentityServer tersedia di belakang layar jika integrasi ASP.NET Core tidak mencakup skenario Anda. Dukungan ASP.NET Core difokuskan pada aplikasi "pihak pertama", tempat semua aplikasi dibuat dan disebarkan oleh organisasi kami. Dengan demikian, dukungan tidak ditawarkan untuk hal-hal seperti persetujuan atau federasi. Untuk skenario tersebut, gunakan IdentityServer dan ikuti dokumentasinya.
Profil aplikasi
Profil aplikasi adalah konfigurasi yang telah ditentukan sebelumnya untuk aplikasi yang lebih menentukan parameternya. Saat ini, profil berikut didukung:
-
IdentityServerSPA
: Mewakili SPA yang dihosting bersama IdentityServer sebagai satu unit.- Secara default,
redirect_uri
diatur ulang ke/authentication/login-callback
. - Secara default,
post_logout_redirect_uri
diatur ulang ke/authentication/logout-callback
. - Kumpulan cakupan mencakup
openid
, ,profile
dan setiap cakupan yang ditentukan untuk API di aplikasi. - Kumpulan jenis respons OIDC yang diizinkan adalah
id_token token
atau masing-masing secara individual (id_token
,token
). - Mode respons yang diizinkan adalah
fragment
.
- Secara default,
-
SPA
: Mewakili SPA yang tidak dihosting dengan IdentityServer.- Kumpulan cakupan mencakup
openid
, ,profile
dan setiap cakupan yang ditentukan untuk API di aplikasi. - Kumpulan jenis respons OIDC yang diizinkan adalah
id_token token
atau masing-masing secara individual (id_token
,token
). - Mode respons yang diizinkan adalah
fragment
.
- Kumpulan cakupan mencakup
-
IdentityServerJwt
: Mewakili API yang dihosting bersama dengan IdentityServer.- Aplikasi ini dikonfigurasi untuk memiliki satu cakupan yang secara default mengarah ke nama aplikasi.
-
API
: Mewakili API yang tidak dihosting dengan IdentityServer.- Aplikasi ini dikonfigurasi untuk memiliki satu cakupan yang secara default mengarah ke nama aplikasi.
Konfigurasi melalui AppSettings
Konfigurasikan aplikasi melalui sistem konfigurasi dengan menambahkannya ke daftar Clients
atau Resources
.
Konfigurasikan properti redirect_uri
dan post_logout_redirect_uri
untuk setiap klien, seperti yang ditunjukkan dalam contoh berikut:
"IdentityServer": {
"Clients": {
"MySPA": {
"Profile": "SPA",
"RedirectUri": "https://www.example.com/authentication/login-callback",
"LogoutUri": "https://www.example.com/authentication/logout-callback"
}
}
}
Saat mengonfigurasi sumber daya, Anda dapat mengonfigurasi cakupan untuk sumber daya seperti yang ditunjukkan di bawah ini:
"IdentityServer": {
"Resources": {
"MyExternalApi": {
"Profile": "API",
"Scopes": "a b c"
}
}
}
Konfigurasi melalui kode
Anda juga dapat mengonfigurasi klien dan sumber daya melalui kode menggunakan kelebihan beban AddApiAuthorization
yang mengambil tindakan untuk mengonfigurasi opsi.
AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options =>
{
options.Clients.AddSPA(
"My SPA", spa =>
spa.WithRedirectUri("http://www.example.com/authentication/login-callback")
.WithLogoutRedirectUri(
"http://www.example.com/authentication/logout-callback"));
options.ApiResources.AddApiResource("MyExternalApi", resource =>
resource.WithScopes("a", "b", "c"));
});
Sumber Daya Tambahan:
ASP.NET Core