Skyddat webb-API: Verifiera omfång och approller

I den här artikeln beskrivs hur du kan lägga till auktorisering i webb-API:et. Det här skyddet säkerställer att API:et endast anropas av:

  • Program för användare som har rätt omfång och roller.
  • Daemon-appar som har rätt programroller.

Kodfragmenten i den här artikeln extraheras från följande kodexempel på GitHub:

Om du vill skydda ett ASP.NET- eller ASP.NET Core-webb-API måste du lägga till [Authorize] attributet i något av följande objekt:

  • Själva kontrollanten om du vill att alla kontrollantåtgärder ska skyddas
  • Den enskilda kontrollantåtgärden för ditt API
    [Authorize]
    public class TodoListController : Controller
    {
     // ...
    }

Men det här skyddet räcker inte. Det garanterar bara att ASP.NET och ASP.NET Core verifierar token. Ditt API måste verifiera att den token som används för att anropa API:et begärs med de förväntade anspråken. Dessa anspråk behöver i synnerhet verifieras:

  • Omfången om API:et anropas för en användares räkning.
  • Approllerna om API:et kan anropas från en daemonapp.

Verifiera omfång i API:er som anropas för användarnas räkning

Om en klientapp anropar ditt API för en användares räkning måste API:et begära en ägartoken som har specifika omfång för API:et. Mer information finns i Kodkonfiguration | Ägartoken.

I ASP.NET Core kan du använda Microsoft.Identity.Web för att verifiera omfång i varje kontrollantåtgärd. Du kan också verifiera dem på kontrollantnivå eller för hela programmet.

Verifiera omfången för varje kontrollantåtgärd

Du kan kontrollera omfången i kontrollantåtgärden med hjälp av attributet [RequiredScope] . Det här attributet har flera åsidosättningar. En som tar de nödvändiga omfången direkt och en som tar en nyckel till konfigurationen.

Verifiera omfången för en kontrollantåtgärd med hårdkodade omfång

Följande kodfragment visar användningen av [RequiredScope] attributet med hårdkodade omfång.

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.
        // ...
    }
 // ...
}
Verifiera omfången för en kontrollantåtgärd med omfång som definierats i konfigurationen

Du kan också deklarera de här nödvändiga omfången i konfigurationen och referera till konfigurationsnyckeln:

Om du till exempel har följande konfiguration i appsettings.json :

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

Referera sedan till det i attributet [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.
        // ...
    }
 // ...
}
Verifiera omfång villkorligt

Det finns fall där du vill verifiera omfång villkorligt. Du kan göra detta med hjälp av VerifyUserHasAnyAcceptedScope tilläggsmetoden på 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.
        // ...
    }
 // ...
}

Kontrollera omfången på kontrollantens nivå

Du kan också verifiera omfången för hela kontrollanten

Verifiera omfången på en kontrollant med hårdkodade omfång

Följande kodfragment visar användningen av [RequiredScope] attributet med hårdkodade omfång på kontrollanten. Om du vill använda RequiredScopeAttribute måste du antingen:

  • Använd AddMicrosoftIdentityWebApi i Startup.cs, som du ser i Kodkonfiguration
  • eller på annat sätt lägga till i ScopeAuthorizationRequirement auktoriseringsprinciperna enligt beskrivningen i auktoriseringsprinciper.
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.
        // ...
    }
 // ...
}
Verifiera omfången på en kontrollant med omfång som definierats i konfigurationen

Precis som vid åtgärd kan du även deklarera de här nödvändiga omfången i konfigurationen och referera till konfigurationsnyckeln:

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.
        // ...
    }
 // ...
}

Verifiera omfången mer globalt

Att definiera detaljerade omfång för webb-API:et och verifiera omfången i varje kontrollantåtgärd är den rekommenderade metoden. Men det är också möjligt att verifiera omfången på programnivå eller kontrollant. Mer information finns i anspråksbaserad auktorisering i ASP.NET Core-dokumentationen.

Vad är verifierat?

Attributet [RequiredScope] och VerifyUserHasAnyAcceptedScope metoden gör något som liknar följande steg:

  • Kontrollera att det finns ett anspråk med namnet http://schemas.microsoft.com/identity/claims/scope eller scp.
  • Kontrollera att anspråket har ett värde som innehåller det omfång som förväntas av API:et.

Verifiera approller i API:er som anropas av daemon-appar

Om webb-API:et anropas av en daemonapp bör appen kräva en programbehörighet till webb-API:et. Som du ser i Exponera programbehörigheter (approller) exponerar ditt API sådana behörigheter. Ett exempel är approllen access_as_application .

Nu måste ditt API kontrollera att den token som den tar emot innehåller anspråket roles och att det här anspråket har det förväntade värdet. Verifieringskoden liknar den kod som verifierar delegerade behörigheter, förutom att kontrollantens åtgärdstester för roller i stället för omfång:

Följande kodfragment visar hur du verifierar programrollen.

using Microsoft.Identity.Web

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

I stället kan du använda attributen [Authorize(Roles = "access_as_application")] på kontrollanten eller en åtgärd (eller en razor-sida).

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

Rollbaserad auktorisering i ASP.NET Core innehåller flera metoder för att implementera rollbaserad auktorisering. Utvecklare kan välja en av dem som passar deras respektive scenarier.

Arbetsexempel finns i inkrementell självstudie om auktorisering av roller och grupper i webbappen.

Verifiera approller i API:er som anropas för användarnas räkning

Användare kan också använda rollanspråk i användartilldelningsmönster, som du ser i Så här lägger du till approller i ditt program och tar emot dem i token. Om rollerna kan tilldelas till båda låter kontrollroller appar logga in när användare och användare loggar in som appar. Vi rekommenderar att du deklarerar olika roller för användare och appar för att förhindra den här förvirringen.

Om du har definierat approller med användare/grupp kan rollanspråk också verifieras i API:et tillsammans med omfång. Verifieringslogik för approllerna i det här scenariot förblir densamma som om API anropas av daemon-apparna eftersom det inte finns någon differentiering i rollanspråket för användare/grupp och program.

Acceptera endast apptoken om webb-API:et endast ska anropas av daemon-appar

Om du bara vill att daemon-appar ska anropa webb-API:et lägger du till villkoret att token är en apptoken när du verifierar approllen.

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

Om du kontrollerar inverteringsvillkoret kan endast appar som loggar in en användare anropa ditt API.

Använda ACL-baserad auktorisering

Alternativt kan du skydda ditt webb-API med ett ACL-baserat auktoriseringsmönster (Access Control List) för att kontrollera token utan anspråketroles.

Om du använder Microsoft.Identity.Web på ASP.NET Core måste du deklarera att du använder ACL-baserad auktorisering, annars utlöser Microsoft Identity Web ett undantag när varken roller eller omfång finns i de angivna anspråken:

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

Undvik det här undantaget genom att ange konfigurationsegenskapen AllowWebApiToBeAuthorizedByACL till true i appsettings.json eller programmatiskt.

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

Om du anger AllowWebApiToBeAuthorizedByACL till trueär det ditt ansvar att säkerställa ACL-mekanismen.

Nästa steg

  • Läs mer genom att skapa en ASP.NET Core-webbapp som loggar in användare i följande självstudieserie i flera delar

  • Utforska Microsofts identitetsplattform webb-API-exempel