適用於:
員工租戶 (瞭解更多資訊)
本文說明如何在您的 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.
// ...
}
// ...
}
有條件地驗證範圍
在某些情況下,您會想要有條件地驗證範圍。 您可以在 VerifyUserHasAnyAcceptedScope 上使用 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.
// ...
}
// ...
}
檢查並確認控制器層級的作用範圍
您也可以確認整個控制器的範圍
使用硬式編碼範圍確認控制器上的範圍
下列程式碼片段顯示控制器上硬式編碼範圍的 [RequiredScope] 屬性使用方式。 要使用 RequiredScopeAttribute,您可以選擇以下其中一種方式:
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");
// ...
}
不過您也可以使用控制器上的 [Authorize(Roles = "access_as_application")] 屬性或動作 (或 Razor 頁面)。
[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) 為基礎的授權模式來控制沒有 roles 宣告的權杖,藉此保護您的 Web API。
如果您在 ASP.NET Core 上使用 Microsoft.Identity.Web,則必須宣告您正在使用 ACL 型授權,否則若提供的宣告中既沒有角色也沒有範圍,Microsoft Identity Web 會拋出例外。
System.UnauthorizedAccessException: IDW10201: Neither scope or roles claim was found in the bearer token.
若要避免這個例外狀況,請在 AllowWebApiToBeAuthorizedByACL 中或以程式設計的方式將 true 設定屬性設定為 。
{
"AzureAD"
{
// other properties
"AllowWebApiToBeAuthorizedByACL" : true,
// other properties
}
}
如果您將 AllowWebApiToBeAuthorizedByACL 設為 true,您必須負責確保 ACL 機制。
下一步
若要深入了解,請在下列多部分教學課程系列中建置可登入使用者的 ASP.NET Core Web 應用程式
探索 Microsoft 身分識別平台 Web API 範例