Middleware otentikasi ASP.NET Core 2.0

89

Dengan Core 1.1 mengikuti saran @ blowdart dan menerapkan middleware khusus:

https://stackoverflow.com/a/31465227/29821

Ini bekerja seperti ini:

  1. Middleware berlari. Mengambil token dari header permintaan.
  2. Memverifikasi token dan jika valid membuat identitas (ClaimsIdentity) yang berisi beberapa klaim yang kemudian ditambahkan melalui HttpContext.User.AddIdentity ();
  3. Di ConfigureServices using services.AddAuthorization, saya telah menambahkan kebijakan untuk mewajibkan klaim yang disediakan oleh middleware.
  4. Dalam pengontrol / tindakan, saya kemudian akan menggunakan [Otorisasi (Peran = "beberapa peran yang ditambahkan middleware")]

Ini agak berfungsi dengan 2.0, kecuali jika token tidak valid (langkah 2 di atas) dan klaim tidak pernah ditambahkan, saya mendapatkan "Tidak ada otentikasiScheme yang ditentukan, dan tidak ada DefaultChallengeScheme yang ditemukan."

Jadi sekarang saya membaca bahwa auth berubah di 2.0:

https://docs.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x

Apa jalur yang benar bagi saya untuk melakukan hal yang sama di ASP.NET Core 2.0? Saya tidak melihat contoh untuk melakukan otentikasi khusus.

pbz
sumber
Coba tautan ini, meskipun dikatakan 2 skema tetapi akan memberi tahu Anda tentang Otentikasi wildermuth.com/2017/08/19/…
Mithun Pattankar
bisakah Anda menambahkan kode Anda sehingga kami dapat melihatnya? Saya tahu saya memiliki masalah dengan JWT di core2.0 - adalah kasus memindahkannya saat startup
Webezine

Jawaban:

195

Jadi, setelah seharian mencoba memecahkan masalah ini, akhirnya saya menemukan bagaimana Microsoft ingin kami membuat penangan otentikasi khusus untuk pengaturan middleware tunggal baru mereka di inti 2.0.

Setelah melihat-lihat beberapa dokumentasi di MSDN, saya menemukan kelas yang disebut AuthenticationHandler<TOption>yang mengimplementasikan IAuthenticationHandlerantarmuka.

Dari sana, saya menemukan seluruh basis kode dengan skema otentikasi yang ada yang terletak di https://github.com/aspnet/Security

Di dalam salah satunya, ini menunjukkan bagaimana Microsoft mengimplementasikan skema otentikasi JwtBearer. ( https://github.com/aspnet/Security/tree/master/src/Microsoft.AspNetCore.Authentication.JwtBearer )

Saya menyalin sebagian besar kode itu ke folder baru, dan membersihkan semua hal yang berkaitan dengannya JwtBearer.

Di JwtBearerHandlerkelas (yang meluas AuthenticationHandler<>), ada penggantian untukTask<AuthenticateResult> HandleAuthenticateAsync()

Saya menambahkan di middleware lama kami untuk menyiapkan klaim melalui server token khusus, dan masih mengalami beberapa masalah dengan izin, hanya mengeluarkan 200 OKalih - alih 401 Unauthorizedketika token tidak valid dan tidak ada klaim yang disiapkan.

Saya menyadari bahwa saya telah menimpa Task HandleChallengeAsync(AuthenticationProperties properties)yang karena alasan apa pun digunakan untuk mengatur izin melalui [Authorize(Roles="")]dalam pengontrol.

Setelah menghapus penggantian ini, kode telah berfungsi, dan berhasil dilempar 401ketika izin tidak cocok.

Kesimpulan utama dari ini adalah bahwa sekarang Anda tidak dapat menggunakan middleware kustom, Anda harus mengimplementasikannya melalui AuthenticationHandler<>dan Anda harus mengatur DefaultAuthenticateSchemedan DefaultChallengeSchemekapan menggunakan services.AddAuthentication(...).

Berikut adalah contoh tampilan semua ini:

Di Startup.cs / ConfigureServices () tambahkan:

services.AddAuthentication(options =>
{
    // the scheme name has to match the value we're going to use in AuthenticationBuilder.AddScheme(...)
    options.DefaultAuthenticateScheme = "Custom Scheme";
    options.DefaultChallengeScheme = "Custom Scheme";
})
.AddCustomAuth(o => { });

Di Startup.cs / Configure () tambahkan:

app.UseAuthentication();

Buat file baru CustomAuthExtensions.cs

public static class CustomAuthExtensions
{
    public static AuthenticationBuilder AddCustomAuth(this AuthenticationBuilder builder, Action<CustomAuthOptions> configureOptions)
    {
        return builder.AddScheme<CustomAuthOptions, CustomAuthHandler>("Custom Scheme", "Custom Auth", configureOptions);
    }
}

Buat file baru CustomAuthOptions.cs

public class CustomAuthOptions: AuthenticationSchemeOptions
{
    public CustomAuthOptions()
    {

    }
}

Buat file baru CustomAuthHandler.cs

internal class CustomAuthHandler : AuthenticationHandler<CustomAuthOptions>
{
    public CustomAuthHandler(IOptionsMonitor<CustomAuthOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
    {
        // store custom services here...
    }
    protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        // build the claims and put them in "Context"; you need to import the Microsoft.AspNetCore.Authentication package
        return AuthenticateResult.NoResult();
    }
}
Zac
sumber
1
posting yang bagus, tetapi saya memiliki beberapa masalah dalam menyusun kode Anda. Jenis CustomAuthOptions dan AuthenticateResult tidak ada. Bisakah Anda memposting itu?
alexb
8
Apakah Anda bersedia untuk membagikan kesimpulan Anda dalam kode di repo Github?
CSharper
2
Bisakah Anda menjelaskan DefaultAuthenticateSchemedan DefaultChallengeScheme? Saya tidak mengerti mengapa keduanya digunakan? dan apa perbedaan di antara keduanya.
Mohammed Noureldin
11
+1 untuk "Dari sana, saya menemukan seluruh basis kode dengan skema autentikasi yang ada di github.com/aspnet/Security ." Lihat saja bagaimana tim ASP.NET melakukannya saat Anda mengikuti jawaban (benar-benar luar biasa) ini. Apakah ada di antara kita yang pernah berpikir bahwa suatu hari kita akan mengajukan pertanyaan tentang kode dan praktik MS dan jawabannya adalah, "lihat saja basis kode mereka?"
Marc L.
3
Untuk orang lain yang datang nanti, Anda AuthExtensionharus berada di dalam Microsoft.Extensions.DependencyInjectionnamespace. Lihat contoh ini: github.com/aspnet/Security/blob/rel/2.0.0/src/…
Garry Polley
4

Ada banyak perubahan dalam Identitas dari Core 1.x ke Core 2.0 seperti yang ditunjukkan artikel yang Anda rujuk. Perubahan utama adalah menjauh dari pendekatan middleware dan menggunakan injeksi ketergantungan untuk mengonfigurasi layanan kustom. Ini memberikan lebih banyak fleksibilitas dalam menyesuaikan Identity untuk implementasi yang lebih kompleks. Jadi, Anda ingin menjauh dari pendekatan middleware yang Anda sebutkan di atas dan beralih ke layanan. Ikuti langkah-langkah migrasi di artikel referensi untuk mencapai tujuan ini. Mulailah dengan mengganti app.UseIdentity dengan app.UseAuthentication . UseIdentity disusutkan dan tidak akan didukung di versi mendatang. Untuk contoh lengkap tentang cara memasukkan transformasi klaim khusus dan melakukan otorisasi pada klaimlihat posting blog ini .

Kevin Junghans
sumber
12
Apakah ada contoh tentang cara menggunakan ini dengan aplikasi WebAPI?
alexb