Bagikan melalui


Membuat Layanan Mikro .NET dan Aplikasi Web yang aman

Tip

Konten ini adalah kutipan dari eBook berjudul Arsitektur Layanan Mikro .NET untuk Aplikasi .NET Dalam Kontainer yang tersedia di .NET Docs atau sebagai PDF gratis yang dapat diunduh yang dapat dibaca secara luring.

.NET Microservices Architecture for Containerized .NET Applications eBook cover thumbnail.

Ada sangat banyak aspek tentang keamanan dalam layanan mikro dan aplikasi web sehingga topik dapat dengan mudah mengambil beberapa buku seperti ini. Jadi, pada bagian ini, kita akan fokus pada autentikasi, otorisasi, dan rahasia aplikasi.

Menerapkan autentikasi pada layanan mikro .NET dan aplikasi web

Sering kali, sumber daya dan API yang diterbitkan oleh layanan harus dibatasi untuk pengguna atau klien tepercaya tertentu. Langkah pertama untuk membuat keputusan kepercayaan tingkat API seperti ini adalah autentikasi. Autentikasi adalah proses memastikan identitas pengguna dengan andal.

Dalam skenario layanan mikro, autentikasi biasanya ditangani secara terpusat. Jika Anda menggunakan API Gateway, gateway adalah tempat yang baik untuk mengautentikasi, seperti yang ditampilkan pada Gambar 9-1. Jika Anda menggunakan pendekatan ini, pastikan masing-masing layanan mikro tidak dapat dijangkau secara langsung (tanpa API Gateway) kecuali keamanan tambahan diterapkan untuk mengautentikasi pesan, terlepas berasal dari gateway atau tidak.

Diagram showing how the client mobile app interacts with the backend.

Gambar 9-1. Autentikasi terpusat dengan API Gateway

Saat API Gateway memusatkan autentikasi, API Gateway menambahkan informasi pengguna saat meneruskan permintaan ke layanan mikro. Jika layanan dapat diakses secara langsung, layanan autentikasi seperti Azure Active Directory atau layanan mikro autentikasi khusus yang bertindak sebagai layanan token keamanan (STS) dapat digunakan untuk mengautentikasi pengguna. Keputusan kepercayaan dibagikan antara layanan dengan token keamanan atau cookie. (Token ini dapat dibagi antara aplikasi ASP.NET Core, jika diperlukan, dengan menerapkan berbagi cookie.) Pola ini digambarkan dalam Gambar 9-2.

Diagram showing authentication through backend microservices.

Gambar 9-2. Autentikasi berdasarkan layanan mikro identitas; kepercayaan dibagikan menggunakan sebuah token otorisasi

Saat layanan mikro diakses secara langsung, kepercayaan, yang mencakup autentikasi dan otorisasi, ditangani oleh token keamanan yang dikeluarkan oleh layanan mikro khusus, yang dibagikan antara layanan mikro.

Mengautentikasi dengan ASP.NET Core Identity

Mekanisme utama di ASP.NET Core untuk mengidentifikasi pengguna aplikasi adalah sistem keanggotaan ASP.NET Core Identity. ASP.NET Core Identity menyimpan informasi pengguna (termasuk informasi masuk, peran, dan klaim) di penyimpanan data yang dikonfigurasi oleh developer. Biasanya, penyimpanan data ASP.NET Core Identity adalah penyimpanan Entity Framework yang disediakan dalam paket Microsoft.AspNetCore.Identity.EntityFrameworkCore. Namun, penyimpanan kustom atau paket pihak ketiga lainnya bisa digunakan untuk menyimpan informasi identitas di Azure Table Storage, CosmosDB, atau lokasi lainnya.

Tip

ASP.NET Core 2.1 dan yang lebih baru menyediakan ASP.NET Core Identity sebagai Pustaka Kelas Razor, sehingga Anda tidak akan melihat banyak kode yang diperlukan dalam proyek Anda, seperti halnya untuk versi sebelumnya. Untuk rincian tentang cara menyesuaikan kode Identitas agar sesuai dengan kebutuhan Anda, lihat Scaffold Identity dalam proyek ASP.NET Core.

Kode berikut ini diambil dari templat proyek ASP.NET Core Web Application MVC 3.1 dengan autentikasi akun pengguna individual yang dipilih. Ini menunjukkan cara mengonfigurasi ASP.NET Core Identity menggunakan Entity Framework Core dalam metode Startup.ConfigureServices.

public void ConfigureServices(IServiceCollection services)
{
    //...
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));

    services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
        .AddEntityFrameworkStores<ApplicationDbContext>();

    services.AddRazorPages();
    //...
}

Setelah ASP.NET Core Identity dikonfigurasi, Anda mengaktifkannya dengan menambahkan app.UseAuthentication() dan endpoints.MapRazorPages() seperti yang ditunjukkan dalam kode berikut dalam metode layanan Startup.Configure:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    //...
    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
    //...
}

Penting

Baris dalam kode sebelumnya HARUS DALAM URUTAN YANG DITUNJUKKAN agar Identitas dapat berfungsi dengan benar.

Menggunakan ASP.NET Core Identity akan memungkinkan beberapa skenario:

  • Buat informasi pengguna baru menggunakan tipe UserManager (userManager.CreateAsync).

  • Autentikasi pengguna menggunakan tipe SignInManager. Anda dapat menggunakan signInManager.SignInAsync untuk masuk secara langsung, atau signInManager.PasswordSignInAsync untuk mengonfirmasi kata sandi pengguna sudah benar lalu memasukkan mereka.

  • Identifikasi pengguna berdasarkan informasi yang disimpan dalam cookie (yang dibaca oleh ASP.NET middleware Identitas Inti) agar permintaan berikutnya dari browser akan menyertakan identitas dan klaim pengguna yang masuk.

ASP.NET Core Identity mendukung autentikasi dua faktor.

Untuk skenario autentikasi yang menggunakan penyimpanan data pengguna lokal dan yang mempertahankan identitas antara permintaan dengan menggunakan cookie (seperti biasa untuk aplikasi web MVC), ASP.NET Core Identity adalah solusi yang direkomendasikan.

Mengautentikasi dengan penyedia eksternal

ASP.NET Core juga mendukung penggunaan penyedia autentikasi eksternal untuk memungkinkan pengguna masuk melalui alur OAuth 2.0. Ini artinya pengguna dapat masuk menggunakan proses autentikasi yang ada dari penyedia seperti Microsoft, Google, Facebook, atau Twitter dan mengaitkan identitas tersebut dengan identitas ASP.NET Core di aplikasi Anda.

Untuk menggunakan autentikasi eksternal, selain menyertakan middleware autentikasi seperti yang disebutkan sebelumnya, menggunakan metode app.UseAuthentication(), Anda juga harus mendaftarkan penyedia eksternal seperti yang ditunjukkan Startup dalam contoh berikut:

public void ConfigureServices(IServiceCollection services)
{
    //...
    services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
        .AddEntityFrameworkStores<ApplicationDbContext>();

    services.AddAuthentication()
        .AddMicrosoftAccount(microsoftOptions =>
        {
            microsoftOptions.ClientId = Configuration["Authentication:Microsoft:ClientId"];
            microsoftOptions.ClientSecret = Configuration["Authentication:Microsoft:ClientSecret"];
        })
        .AddGoogle(googleOptions => { ... })
        .AddTwitter(twitterOptions => { ... })
        .AddFacebook(facebookOptions => { ... });
    //...
}

Penyedia autentikasi eksternal populer dan paket NuGet terkait ditunjukkan dalam tabel berikut:

Penyedia Paket
Microsoft Microsoft.AspNetCore.Authentication.MicrosoftAccount
Google Microsoft.AspNetCore.Authentication.Google
Facebook Microsoft.AspNetCore.Authentication.Facebook
Twitter Microsoft.AspNetCore.Authentication.Twitter

Dalam semua kasus, Anda harus menyelesaikan prosedur pendaftaran aplikasi yang bergantung pada vendor serta biasanya melibatkan:

  1. Mendapatkan ID Aplikasi Klien.
  2. Mendapatkan Rahasia Aplikasi Klien.
  3. Mengonfigurasi URL pengalihan, yang ditangani oleh middleware otorisasi dan penyedia terdaftar
  4. Secara opsional, mengonfigurasi URL keluar untuk menangani sign out dengan benar dalam skenario Akses Menyeluruh (SSO).

Untuk detail tentang cara mengonfigurasi aplikasi Anda untuk penyedia eksternal, lihat Autentikasi penyedia eksternal dalam dokumentasi ASP.NET Core).

Tip

Seluruh detail ditangani oleh middleware otorisasi dan layanan yang disebutkan sebelumnya. Jadi, Anda hanya perlu memilih opsi autentikasi Akun Pengguna Individu saat membuat proyek aplikasi web ASP.NET Core di Visual Studio, seperti yang ditunjukkan pada Gambar 9-3, selain mendaftarkan penyedia autentikasi yang telah disebutkan sebelumnya.

Screenshot of the New ASP.NET Core Web Application dialog.

Gambar 9-3. Memilih opsi Akun Pengguna Individual, untuk menggunakan autentikasi eksternal, saat membuat proyek aplikasi web di Visual Studio 2019.

Selain penyedia autentikasi eksternal yang tercantum sebelumnya, paket pihak ketiga tersedia yang menyediakan middleware untuk menggunakan lebih banyak penyedia autentikasi eksternal. Untuk daftar selengkapnya, lihat repositori AspNet.Security.OAuth.Providers di GitHub.

Anda juga bisa membuat middleware autentikasi eksternal Anda sendiri untuk menyelesaikan beberapa kebutuhan khusus.

Mengautentikasi dengan token pembawa

Mengautentikasi dengan ASP.NET Core Identity (atau Identity plus penyedia autentikasi eksternal) berfungsi dengan baik untuk banyak skenario aplikasi web di mana penyimpanan informasi pengguna dalam cookie dianggap sesuai. Tetapi, dalam skenario lain, cookie bukanlah cara alami untuk bertahan dan mengirimkan data.

Contohnya, dalam ASP.NET Core Web API yang mengekspos titik akhir RESTful yang mungkin diakses oleh Aplikasi Halaman Tunggal (SPAs), oleh klien asli, atau bahkan oleh API Web lainnya, Anda biasanya ingin menggunakan autentikasi token pembawa sebagai gantinya. Jenis aplikasi ini tidak berfungsi dengan cookie, tetapi dapat dengan mudah mengambil token pembawa lalu menyertakannya di header otorisasi permintaan berikutnya. Untuk mengaktifkan autentikasi token, ASP.NET Core mendukung beberapa opsi untuk menggunakan OAuth 2.0 dan OpenID Connect.

Mengautentikasi dengan IdP OpenID Connect atau OAuth 2.0

Jika informasi pengguna disimpan dalam Azure Active Directory atau solusi identitas lain yang mendukung OpenID Connect atau OAuth 2.0, Anda dapat menggunakan paket Microsoft.AspNetCore.Authentication.OpenIdConnect untuk mengautentikasi menggunakan alur kerja OpenID Connect. Contohnya, untuk mengautentikasi ke layanan mikro Identity.Api di eShopOnContainers, aplikasi web ASP.NET Core dapat menggunakan middleware dari paket tersebut seperti yang ditunjukkan dalam contoh yang disederhanakan berikut ini di Startup.cs:

// Startup.cs

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    //…
    app.UseAuthentication();
    //…
    app.UseEndpoints(endpoints =>
    {
        //...
    });
}

public void ConfigureServices(IServiceCollection services)
{
    var identityUrl = Configuration.GetValue<string>("IdentityUrl");
    var callBackUrl = Configuration.GetValue<string>("CallBackUrl");
    var sessionCookieLifetime = Configuration.GetValue("SessionCookieLifetimeMinutes", 60);

    // Add Authentication services

    services.AddAuthentication(options =>
    {
        options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddCookie(setup => setup.ExpireTimeSpan = TimeSpan.FromMinutes(sessionCookieLifetime))
    .AddOpenIdConnect(options =>
    {
        options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.Authority = identityUrl.ToString();
        options.SignedOutRedirectUri = callBackUrl.ToString();
        options.ClientId = useLoadTest ? "mvctest" : "mvc";
        options.ClientSecret = "secret";
        options.ResponseType = useLoadTest ? "code id_token token" : "code id_token";
        options.SaveTokens = true;
        options.GetClaimsFromUserInfoEndpoint = true;
        options.RequireHttpsMetadata = false;
        options.Scope.Add("openid");
        options.Scope.Add("profile");
        options.Scope.Add("orders");
        options.Scope.Add("basket");
        options.Scope.Add("marketing");
        options.Scope.Add("locations");
        options.Scope.Add("webshoppingagg");
        options.Scope.Add("orders.signalrhub");
    });
}

Saat Anda menggunakan alur kerja ini, middleware identitas inti ASP.NET tidak diperlukan, karena seluruh penyimpanan informasi pengguna dan autentikasi ditangani oleh layanan Identitas.

Menerbitkan token keamanan dari layanan ASP.NET Core

Jika Anda lebih memilih untuk mengeluarkan token keamanan untuk pengguna identitas inti ASP.NET lokal daripada menggunakan idP eksternal, Anda dapat memanfaatkan beberapa pustaka pihak ketiga yang bagus.

IdentityServer4 dan OpenIddict adalah penyedia OpenID Connect yang terintegrasi dengan mudah dengan ASP.NET Core Identity untuk memungkinkan Anda mengeluarkan token keamanan dari layanan ASP.NET Core. Dokumentasi IdentityServer4 memiliki instruksi mendalam untuk menggunakan pustaka. Meskipun demikian, langkah-langkah dasar untuk menggunakan IdentityServer4 untuk mengeluarkan token adalah sebagai berikut.

  1. Anda memanggil app.UseIdentityServer dalam metode Startup.Configure untuk menambahkan IdentityServer4 ke alur pemrosesan permintaan HTTP aplikasi. Ini memungkinkan pustaka melayani permintaan ke titik akhir OpenID Connect dan OAuth2 seperti /connect/token.

  2. Anda mengonfigurasi IdentityServer4 di Startup.ConfigureServices dengan melakukan panggilan ke services.AddIdentityServer.

  3. Anda mengonfigurasi server identitas dengan mengatur data berikut:

    • Kredensial yang digunakan untuk penandatanganan.

    • Sumber daya Identitas dan API yang mungkin diminta aksesnya oleh pengguna:

      • Sumber daya API mewakili data atau fungsionalitas yang dilindungi yang bisa diakses pengguna dengan token akses. Contoh sumber daya API adalah API web (atau set API) yang memerlukan otorisasi.

      • Sumber daya identitas mewakili informasi (klaim) yang diberikan pada klien untuk mengidentifikasi pengguna. Klaim dapat mencakup nama pengguna, alamat email, dan sebagainya.

    • Klien yang akan terhubung untuk meminta token.

    • Mekanisme penyimpanan untuk informasi pengguna, seperti ASP.NET Core Identity atau alternatifnya.

Saat Anda menentukan klien dan sumber daya untuk digunakan IdentityServer4, Anda bisa meneruskan IEnumerable<T> koleksi tipe yang sesuai ke metode yang mengambil klien dalam memori atau penyimpanan sumber daya. Atau untuk skenario yang lebih kompleks, Anda bisa menyediakan tipe penyedia klien atau sumber daya melalui Injeksi Dependensi.

Konfigurasi sampel untuk IdentityServer4 untuk menggunakan sumber daya dalam memori dan klien yang disediakan oleh jenis IClientStore kustom mungkin terlihat seperti contoh berikut ini:

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    //...
    services.AddSingleton<IClientStore, CustomClientStore>();
    services.AddIdentityServer()
        .AddSigningCredential("CN=sts")
        .AddInMemoryApiResources(MyApiResourceProvider.GetAllResources())
        .AddAspNetIdentity<ApplicationUser>();
    //...
}

Mengonsumsi token keamanan

Mengautentikasi terhadap titik akhir OpenID Connect atau mengeluarkan token keamanan Anda sendiri mencakup beberapa skenario. Tetapi bagaimana dengan layanan yang hanya harus membatasi akses ke pengguna yang memiliki token keamanan valid yang disediakan oleh layanan yang berbeda?

Untuk skenario tersebut, middleware autentikasi yang menangani token JWT tersedia dalam paket Microsoft.AspNetCore.Authentication.JwtBearer. JWT adalah singkatan dari "JSON Web Token" dan merupakan format token keamanan umum (ditentukan oleh RFC 7519) untuk mengomunikasikan klaim keamanan. Contoh yang disederhanakan tentang cara menggunakan middleware untuk menggunakan token tersebut mungkin terlihat seperti fragmen kode ini, diambil dari layanan mikro Ordering.Api eShopOnContainers.

// Startup.cs

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    //…
    // Configure the pipeline to use authentication
    app.UseAuthentication();
    //…
    app.UseEndpoints(endpoints =>
    {
        //...
    });
}

public void ConfigureServices(IServiceCollection services)
{
    var identityUrl = Configuration.GetValue<string>("IdentityUrl");

    // Add Authentication services

    services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme;

    }).AddJwtBearer(options =>
    {
        options.Authority = identityUrl;
        options.RequireHttpsMetadata = false;
        options.Audience = "orders";
    });
}

Parameter dalam penggunaan ini adalah:

  • Audience mewakili penerima token masuk atau sumber daya yang diberikan token. Jika nilai yang ditentukan dalam parameter ini tidak cocok dengan parameter dalam token, maka token akan ditolak.

  • Authority adalah alamat server autentikasi penerbit token. Middleware autentikasi pembawa JWT menggunakan URI ini untuk mendapatkan kunci umum yang bisa digunakan untuk memvalidasi tanda tangan token. Middleware juga mengonfirmasi bahwa parameter iss dalam token cocok dengan URI ini.

Parameter lain, RequireHttpsMetadata, berguna untuk tujuan pengujian; Anda mengatur parameter ini ke false agar Anda dapat menguji di lingkungan di mana Anda tidak memiliki sertifikat. Dalam penyebaran dunia nyata, token pembawa JWT harus selalu diteruskan hanya melalui HTTPS.

Dengan adanya middleware ini, token JWT akan secara otomatis diekstraksi dari header otorisasi. Mereka lalu dideserialisasi, divalidasi (menggunakan nilai dalam parameter Audience dan Authority), dan disimpan sebagai informasi pengguna untuk dirujuk nanti oleh tindakan MVC atau filter otorisasi.

Middleware autentikasi pembawa JWT juga bisa mendukung skenario yang lebih canggih, seperti menggunakan sertifikat lokal untuk memvalidasi token jika otoritas tidak tersedia. Untuk skenario ini, Anda dapat menentukan objek TokenValidationParameters dalam objek JwtBearerOptions.

Sumber Daya Tambahan: