受保護的 Web API:驗證範圍和應用程式角色
本文說明如何將授權新增至 Web API。 此保護可確保只有下列方式呼叫 API:
- 代表具有適當範圍和角色的用戶的應用程式。
- 具有正確應用程式角色的精靈應用程式。
本文中的代碼段會從 GitHub 上的下列程式代碼範例擷取:
若要保護 ASP.NET 或 ASP.NET Core Web API,您必須將 屬性新增 [Authorize]
至下列其中一個專案:
- 如果您想要保護所有控制器動作,控制器本身
- API 的個別控制器動作
[Authorize]
public class TodoListController : Controller
{
// ...
}
但這項保護還不夠。 它只保證 ASP.NET 和 ASP.NET Core 驗證令牌。 您的 API 必須確認用來呼叫 API 的令牌是使用預期的宣告要求。 這些宣告特別需要驗證:
- 如果 API 是代表使用者呼叫,則 為範圍 。
- 如果可以從精靈應用程式呼叫 API,則 為應用程式角色 。
代表使用者驗證 API 中的範圍
如果用戶端應用程式代表使用者呼叫您的 API,API 必須要求具有 API 特定範圍的持有人令牌。 如需詳細資訊,請參閱 程式代碼設定 |持有人令牌。
在 ASP.NET Core 中,您可以使用 Microsoft.Identity.Web 來驗證每個控制器動作中的範圍。 您也可以在控制器層級或整個應用程式進行驗證。
確認每個控制器動作的範圍
您可以使用 屬性來驗證控制器動作 [RequiredScope]
中的範圍。 此屬性有數個覆寫。 直接採用必要範圍的一個,另一個採用組態索引鍵。
使用硬式編碼範圍確認控制器動作上的範圍
下列代碼段顯示屬性搭配硬式編碼範圍的使用 [RequiredScope]
方式。
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.
// ...
}
// ...
}
使用組態中定義的範圍,確認控制器動作上的範圍
您也可以在設定中宣告這些必要的範圍,並參考組態索引鍵:
例如,在 appsettings.json 您有下列組態:
{
"AzureAd" : {
// more settings
"Scopes" : "access_as_user access_as_admin"
}
}
然後,在屬性中 [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.
// ...
}
// ...
}
有條件地驗證範圍
在某些情況下,您想要有條件地驗證範圍。 您可以使用 上的HttpContext
擴充方法來執行這項操作VerifyUserHasAnyAcceptedScope
。
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.
// ...
}
// ...
}
確認控制器層級的範圍
您也可以驗證整個控制器的範圍
使用硬式編碼範圍確認控制器上的範圍
下列代碼段顯示屬性在 [RequiredScope]
控制器上使用硬式編碼範圍。 若要使用 RequiredScopeAttribute,您必須:
- 在 Startup.cs 中使用
AddMicrosoftIdentityWebApi
,如程式代碼設定所示 - 否則,請將 新增
ScopeAuthorizationRequirement
至授權原則,如授權原則中所述。
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.
// ...
}
// ...
}
使用組態中定義的範圍確認控制器上的範圍
如同動作,您也可以在設定中宣告這些必要的範圍,並參考組態索引鍵:
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.
// ...
}
// ...
}
更全域地驗證範圍
定義 Web API 的細微範圍,並確認每個控制器動作中的範圍是建議的方法。 不過,您也可以驗證應用程式或控制器層級的範圍。 如需詳細資訊,請參閱 ASP.NET Core 檔中的宣告型授權 。
驗證的內容為何?
[RequiredScope]
屬性和VerifyUserHasAnyAcceptedScope
方法會執行如下的步驟:
- 確認有名為
http://schemas.microsoft.com/identity/claims/scope
或scp
的宣告。 - 確認宣告具有值,其中包含 API 預期的範圍。
確認精靈應用程式所呼叫 API 中的應用程式角色
如果您的 Web API 是由 精靈應用程式呼叫,該應用程式應該需要 Web API 的應用程式許可權。 如公開應用程式許可權(應用程式角色)所示,您的 API 會公開這類許可權。 其中一個範例是 access_as_application
應用程式角色。
您現在必須讓 API 確認它收到的令牌包含 roles
宣告,且此宣告具有預期的值。 驗證碼類似於驗證委派許可權的程式代碼,不同之處在於您的控制器動作會測試角色,而不是範圍:
下列代碼段示範如何驗證應用程式角色;
using Microsoft.Identity.Web
[Authorize]
public class TodoListController : ApiController
{
public IEnumerable<TodoItem> Get()
{
HttpContext.ValidateAppRole("access_as_application");
// ...
}
相反地,您可以在控制器或動作(或 razor 頁面)上使用 [Authorize(Roles = "access_as_application")]
屬性。
[Authorize(Roles = "access_as_application")]
MyController : ApiController
{
// ...
}
ASP.NET Core 中的角色型授權列出數種方法來實作角色型授權。 開發人員可以選擇其中一個適合其個別案例的案例。
如需工作範例,請參閱角色和群組授權的 Web 應用程式累加教學課程。
代表使用者驗證 API 中的應用程式角色
使用者也可以在使用者指派模式中使用角色宣告,如 如何在應用程式中新增應用程式角色,並在令牌中接收它們所示。 如果角色可指派給兩者,檢查角色會讓應用程式以使用者身分登入,而使用者以應用程式身分登入。 建議您為使用者和應用程式宣告不同的角色,以避免發生這種混淆。
如果您已使用使用者/群組定義應用程式角色,則角色宣告也可以在 API 中連同範圍一起驗證。 此案例中應用程式角色的驗證邏輯與精靈應用程式呼叫 API 相同,因為使用者/群組和應用程式的角色宣告沒有差異。
如果 Web API 只能由精靈應用程式呼叫,則接受僅限應用程式令牌
如果您只想讓精靈應用程式呼叫 Web API,請在驗證應用程式角色時新增令牌為僅限應用程式令牌的條件。
string oid = ClaimsPrincipal.Current.FindFirst("oid")?.Value;
string sub = ClaimsPrincipal.Current.FindFirst("sub")?.Value;
bool isAppOnly = oid != null && sub != null && oid == sub;
檢查反向條件只允許登入使用者的應用程式呼叫您的 API。
使用 ACL 型授權
或者,除了以應用程式角色為基礎的授權,您也可以使用 存取控制 清單 (ACL) 型授權模式來保護 Web API,以控制令牌,而不需要roles
宣告。
如果您在 Microsoft.Identity.Web
ASP.NET Core 上使用 ,則必須宣告您使用 ACL 型授權,否則當角色和範圍都未在提供的宣告中時,Microsoft Identity Web 會擲回例外狀況:
System.UnauthorizedAccessException: IDW10201: Neither scope or roles claim was found in the bearer token.
若要避免這個例外狀況,請在 AllowWebApiToBeAuthorizedByACL
appsettings.json 或以程式設計方式將 組態屬性設定為 true
。
{
"AzureAD"
{
// other properties
"AllowWebApiToBeAuthorizedByACL" : true,
// other properties
}
}
如果您將 設定 AllowWebApiToBeAuthorizedByACL
為 true
,這是 您確保 ACL 機制的責任 。
下一步
探索 Microsoft 身分識別平台 Web API 範例