API web yang dilindungi: Memverifikasi cakupan dan peran aplikasi

Artikel ini menjelaskan cara menambahkan otorisasi ke API web Anda. Perlindungan ini memastikan bahwa API hanya disebut dengan:

  • Aplikasi atas nama pengguna yang memiliki cakupan dan peran yang tepat.
  • Aplikasi Daemon yang memiliki peran aplikasi yang tepat.

Cuplikan kode dalam artikel ini diekstraksi dari sampel kode berikut di GitHub:

Untuk melindungi ASP.NET atau API web ASP.NET Core, Anda harus menambahkan atribut [Authorize] ke salah satu item berikut:

  • Pengontrol itu sendiri jika Anda ingin semua tindakan pengontrol dilindungi
  • Tindakan pengontrol individual untuk API Anda
    [Authorize]
    public class TodoListController : Controller
    {
     // ...
    }

Tapi perlindungan ini tidak cukup. Ini hanya menjamin bahwa ASP.NET dan ASP.NET Core memvalidasi token. API Anda perlu memverifikasi bahwa token yang digunakan untuk memanggil API diminta dengan klaim yang diharapkan. Klaim ini khususnya perlu verifikasi:

  • Cakupan jika API dipanggil atas nama pengguna.
  • Peran aplikasi jika API dapat dipanggil dari aplikasi daemon.

Memverifikasi cakupan dalam API yang dipanggil atas nama pengguna

Jika aplikasi klien memanggil API Anda atas nama pengguna, API perlu meminta token pembawa yang memiliki cakupan khusus untuk API. Untuk informasi selengkapnya, lihat Konfigurasi kode | Token pembawa.

Di ASP.NET Core, Anda dapat menggunakan Microsoft.Identity.Web untuk memverifikasi cakupan di setiap tindakan pengontrol. Anda juga dapat memverifikasinya di tingkat pengontrol atau untuk seluruh aplikasi.

Memverifikasi cakupan pada setiap tindakan pengontrol

Anda dapat memverifikasi cakupan dalam tindakan pengontrol dengan menggunakan atribut [RequiredScope]. Atribut ini memiliki beberapa overrides. Salah satu yang mengambil ruang lingkup yang diperlukan secara langsung, dan salah satu yang mengambil kunci untuk konfigurasi.

Memverifikasi ruang lingkup pada tindakan pengontrol dengan lingkup hardcoded

Cuplikan kode berikut menunjukkan penggunaan atribut [RequiredScope] dengan cakupan hardcode.

using Microsoft.Identity.Web

[Authorize]
public class TodoListController : Controller
{
    /// <summary>
    /// The web API will accept only tokens that have the `access_as_user` scope for
    /// this API.
    /// </summary>
    const string scopeRequiredByApi = "access_as_user";

    // GET: api/values
    [HttpGet]
    [RequiredScope(scopeRequiredByApi)]
    public IEnumerable<TodoItem> Get()
    {
        // Do the work and return the result.
        // ...
    }
 // ...
}
Memverifikasi ruang lingkup pada tindakan pengontrol dengan ruang lingkup yang ditentukan dalam konfigurasi

Anda juga dapat mendeklarasikan ruang lingkup yang diperlukan ini dalam konfigurasi, dan referensi kunci konfigurasi:

Misalnya, dalam appsettings.json Anda memiliki konfigurasi berikut:

{
 "AzureAd" : {
   // more settings
   "Scopes" : "access_as_user access_as_admin"
  }
}

Kemudian, rujuk di atribut [RequiredScope]:

using Microsoft.Identity.Web

[Authorize]
public class TodoListController : Controller
{
    // GET: api/values
    [HttpGet]
    [RequiredScope(RequiredScopesConfigurationKey = "AzureAd:Scopes")]
    public IEnumerable<TodoItem> Get()
    {
        // Do the work and return the result.
        // ...
    }
 // ...
}
Memverifikasi lingkup secara kondisional

Ada kasus di mana Anda ingin memverifikasi ruang lingkup secara kondisional. Anda dapat melakukannya menggunakan metode ekstensi VerifyUserHasAnyAcceptedScope di HttpContext.

using Microsoft.Identity.Web

[Authorize]
public class TodoListController : Controller
{
    /// <summary>
    /// The web API will accept only tokens 1) for users, 2) that have the `access_as_user` scope for
    /// this API.
    /// </summary>
    static readonly string[] scopeRequiredByApi = new string[] { "access_as_user" };

    // GET: api/values
    [HttpGet]
    public IEnumerable<TodoItem> Get()
    {
         HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi);
        // Do the work and return the result.
        // ...
    }
 // ...
}

Memverifikasi ruang lingkup pada tingkat pengontrol

Anda juga dapat memverifikasi ruang lingkup untuk seluruh pengontrol

Memverifikasi ruang lingkup pada pengontrol dengan lingkup hardcoded

Cuplikan kode berikut menunjukkan penggunaan atribut [RequiredScope] dengan cakupan hardcode pada pengontrol. Untuk menggunakan RequiredScopeAttribute, Anda harus:

  • Gunakan AddMicrosoftIdentityWebApi dalam Startup.cs, seperti yang terlihat dalam Konfigurasi kode
  • atau menambahkan ke kebijakan otorisasi seperti yang ScopeAuthorizationRequirement dijelaskan dalam kebijakan otorisasi.
using Microsoft.Identity.Web

[Authorize]
[RequiredScope(scopeRequiredByApi)]
public class TodoListController : Controller
{
    /// <summary>
    /// The web API will accept only tokens 1) for users, 2) that have the `access_as_user` scope for
    /// this API.
    /// </summary>
    static readonly string[] scopeRequiredByApi = new string[] { "access_as_user" };

    // GET: api/values
    [HttpGet]
    public IEnumerable<TodoItem> Get()
    {
        // Do the work and return the result.
        // ...
    }
 // ...
}
Memverifikasi ruang lingkup pada pengontrol dengan ruang lingkup yang ditentukan dalam konfigurasi

Seperti pada tindakan, Anda juga dapat mendeklarasikan ruang lingkup yang diperlukan ini dalam konfigurasi, dan mereferensikan kunci konfigurasi:

using Microsoft.Identity.Web

[Authorize]
[RequiredScope(RequiredScopesConfigurationKey = "AzureAd:Scopes")]
public class TodoListController : Controller
{
    // GET: api/values
    [HttpGet]
    public IEnumerable<TodoItem> Get()
    {
        // Do the work and return the result.
        // ...
    }
 // ...
}

Memverifikasi cakupan secara lebih global

Menentukan cakupan terperinci untuk API web Anda dan memverifikasi cakupan dalam setiap tindakan pengontrol adalah pendekatan yang disarankan. Namun itu juga memungkinkan untuk memverifikasi cakupan di tingkat aplikasi atau pengontrol. Untuk detailnya, lihat otorisasi berbasis klaim dalam dokumentasi ASP.NET Core.

Apa yang diverifikasi?

Atribut [RequiredScope] dan metode VerifyUserHasAnyAcceptedScope, melakukan sesuatu seperti langkah-langkah berikut:

  • Verifikasi ada klaim bernama http://schemas.microsoft.com/identity/claims/scope atau scp.
  • Verifikasi klaim memiliki nilai yang berisi cakupan yang diharapkan oleh API.

Memverifikasi peran aplikasi dalam API yang disebut oleh aplikasi daemon

Jika API web Anda dipanggil oleh aplikasi daemon, aplikasi tersebut harus memerlukan izin aplikasi ke API web Anda. Seperti yang ditunjukkan dalam Mengekspos izin aplikasi (peran aplikasi), API Anda akan mengekspos izin tersebut. Salah satu contohnya adalah access_as_application peran aplikasi.

Anda sekarang perlu memiliki API Anda memverifikasi bahwa token yang diterimanya berisi roles klaim dan bahwa klaim ini memiliki nilai yang diharapkan. Kode verifikasi mirip dengan kode yang memverifikasi izin yang didelegasikan, kecuali bahwa tindakan pengontrol Anda menguji peran, bukan cakupan:

Cuplikan kode berikut menunjukkan cara memverifikasi peran aplikasi;

using Microsoft.Identity.Web

[Authorize]
public class TodoListController : ApiController
{
    public IEnumerable<TodoItem> Get()
    {
        HttpContext.ValidateAppRole("access_as_application");
        // ...
    }

Sebagai gantinya [Authorize(Roles = "access_as_application")] , Anda dapat menggunakan atribut pada pengontrol atau tindakan (atau halaman pisau cukur).

[Authorize(Roles = "access_as_application")]
MyController : ApiController
{
    // ...
}

Otorisasi berbasis peran dalam ASP.NET Core mencantumkan beberapa pendekatan untuk menerapkan otorisasi berbasis peran. Pengembang dapat memilih salah satu di antara mereka yang sesuai dengan skenario masing-masing.

Untuk sampel yang berfungsi, lihat tutorial tahapan aplikasi web tentang otorisasi menurut peran dan grup.

Memverifikasi peran aplikasi dalam API yang dipanggil atas nama pengguna

Pengguna juga dapat menggunakan klaim peran dalam pola penugasan pengguna, seperti yang ditunjukkan dalam Cara menambahkan peran aplikasi di aplikasi Anda dan menerimanya di token. Jika peran dapat ditetapkan untuk keduanya, peran pemeriksaan akan memungkinkan aplikasi masuk sebagai pengguna dan pengguna untuk masuk sebagai aplikasi. Kami menyarankan agar Anda mendeklarasikan peran yang berbeda bagi pengguna dan aplikasi untuk mencegah kebingungan ini.

Jika Anda telah menentukan peran aplikasi dengan pengguna/grup, klaim peran juga dapat diverifikasi di API bersama dengan cakupan. Logika verifikasi peran aplikasi dalam skenario ini tetap sama seperti jika API dipanggil oleh aplikasi daemon karena tidak ada diferensiasi dalam klaim peran untuk pengguna/grup dan aplikasi.

Menerima token khusus aplikasi jika API web hanya boleh dipanggil oleh aplikasi daemon

Jika Anda hanya ingin aplikasi daemon memanggil API web Anda, tambahkan kondisi bahwa token adalah token khusus aplikasi saat Anda memvalidasi peran aplikasi.

string oid = ClaimsPrincipal.Current.FindFirst("oid")?.Value;
string sub = ClaimsPrincipal.Current.FindFirst("sub")?.Value;
bool isAppOnly = oid != null && sub != null && oid == sub;

Memeriksa kondisi terbalik hanya memungkinkan aplikasi yang masuk ke pengguna untuk memanggil API Anda.

Menggunakan otorisasi berbasis ACL

Atau untuk otorisasi berbasis peran aplikasi, Anda dapat melindungi API web Anda dengan pola otorisasi berbasis Access Control List (ACL) untuk mengontrol token tanpa roles klaim.

Jika Anda menggunakan Microsoft.Identity.Web ASP.NET Core, Anda harus menyatakan bahwa Anda menggunakan otorisasi berbasis ACL, jika tidak, Microsoft Identity Web akan memberikan pengecualian ketika tidak ada peran atau cakupan dalam klaim yang disediakan:

System.UnauthorizedAccessException: IDW10201: Neither scope or roles claim was found in the bearer token.

Untuk menghindari pengecualian ini, atur AllowWebApiToBeAuthorizedByACL properti konfigurasi ke true secara appsettings.json atau terprogram.

{
 "AzureAD"
 {
  // other properties
  "AllowWebApiToBeAuthorizedByACL" : true,
  // other properties
 }
}

Jika Anda mengatur AllowWebApiToBeAuthorizedByACL ke true, ini adalah tanggung jawab Anda untuk memastikan mekanisme ACL.

Langkah berikutnya

  • Pelajari selengkapnya dengan membangun aplikasi web ASP.NET Core yang memasukkan pengguna dalam seri tutorial multi-bagian berikut

  • Menjelajahi sampel API web platform identitas Microsoft