API web protegida: Comprobación de ámbitos y roles de aplicaciónProtected web API: Verify scopes and app roles

En este artículo se describe cómo se puede agregar autorización a la API web.This article describes how you can add authorization to your web API. Esta protección garantiza que solo llamen a la API:This protection ensures that the API is called only by:

  • Aplicaciones en nombre de usuarios que tienen los ámbitos correctos.Applications on behalf of users who have the right scopes.
  • Aplicaciones de demonio que tienen los roles de aplicación correctos.Daemon apps that have the right application roles.

Nota

Los fragmentos de código de este artículo se han extraído de los ejemplos de código siguientes en GitHub:The code snippets in this article are extracted from the following code samples on GitHub:

Para proteger una API web de ASP.NET o ASP.NET Core, debe agregar el atributo [Authorize] en uno de los siguientes elementos:To protect an ASP.NET or ASP.NET Core web API, you must add the [Authorize] attribute to one of the following items:

  • El propio controlador, si quiere que todas las acciones del controlador estén protegidas.The controller itself if you want all controller actions to be protected
  • La acción de controlador individual para la API.The individual controller action for your API
    [Authorize]
    public class TodoListController : Controller
    {
     ...
    }

Aun así, esta protección no es suficiente.But this protection isn't enough. Solo garantiza que ASP.NET y ASP.NET Core validen el token.It guarantees only that ASP.NET and ASP.NET Core validate the token. La API debe verificar que el token usado para llamar a la API se haya solicitado con las notificaciones esperadas.Your API needs to verify that the token used to call the API is requested with the expected claims. Estas notificaciones requieren una verificación en particular:These claims in particular need verification:

  • Los ámbitos, si se llama a la API en nombre de un usuario.The scopes if the API is called on behalf of a user.
  • Los roles de aplicación, si se puede llamar a la API desde una aplicación de demonio.The app roles if the API can be called from a daemon app.

Verificación de los ámbitos de las API a las que se llama en nombre de los usuariosVerify scopes in APIs called on behalf of users

Si una aplicación cliente llama a la API en nombre de un usuario, la API debe solicitar un token de portador con ámbitos específicos para la API.If a client app calls your API on behalf of a user, the API needs to request a bearer token that has specific scopes for the API. Para más información, consulte Configuración del código | Token de portador.For more information, see Code configuration | Bearer token.

.NET Core.NET Core

Verificación de los ámbitos en cada acción de controladorVerify the scopes on each controller action

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

El método VerifyUserHasAnyAcceptedScope hace algo similar a los pasos siguientes:The VerifyUserHasAnyAcceptedScope method does something like the following steps:

  • Verificar que hay una notificación denominada http://schemas.microsoft.com/identity/claims/scope o scp.Verify there's a claim named http://schemas.microsoft.com/identity/claims/scope or scp.
  • Verificar que la notificación tiene un valor que contiene el ámbito que espera la API.Verify the claim has a value that contains the scope expected by the API.

Verificación de los ámbitos más globalmenteVerify the scopes more globally

La definición de ámbitos pormenorizados para la API web y la verificación de los ámbitos en cada acción del controlador es el enfoque recomendado.Defining granular scopes for your web API and verifying the scopes in each controller action is the recommended approach. Sin embargo, también es posible verificar los ámbitos en el nivel de la aplicación o un controlador mediante ASP.NET Core.However, it's also possible to verify the scopes at the level of the application or a controller by using ASP.NET Core. Para obtener más información, consulte Autorización basada en notificaciones en la documentación de ASP.NET Core.For details, see Claim-based authorization in the ASP.NET core documentation.

.NET MVC.NET MVC

Para ASP.NET, solo tiene que reemplazar HttpContext.User por ClaimsPrincipal.Current y reemplazar el tipo de notificación "http://schemas.microsoft.com/identity/claims/scope" por "scp".For ASP.NET, just replace HttpContext.User with ClaimsPrincipal.Current, and replace the claim type "http://schemas.microsoft.com/identity/claims/scope" with "scp". Consulte también el fragmento de código incluido más adelante en este artículo.Also see the code snippet later in this article.

Verificación de los roles de aplicación de las API a las que llaman aplicaciones de demonioVerify app roles in APIs called by daemon apps

Si una aplicación de demonio llama a la API web, la aplicación debe solicitar un permiso de aplicación a la API web.If your web API is called by a daemon app, that app should require an application permission to your web API. Como se muestra en Exposición de los permisos de aplicación (roles de aplicación), la API expone estos permisos.As shown in Exposing application permissions (app roles), your API exposes such permissions. Un ejemplo es el rol de aplicación access_as_application.One example is the access_as_application app role.

Ahora debe hacer que la API verifique que el token recibido contiene la notificación roles y que esta notificación tiene el valor esperado.You now need to have your API verify that the token it receives contains the roles claim and that this claim has the expected value. El código de verificación es similar al código que verifica los permisos delegados, con la diferencia de que la acción del controlador prueba los roles en lugar de los ámbitos:The verification code is similar to the code that verifies delegated permissions, except that your controller action tests for roles instead of scopes:

ASP.NET CoreASP.NET Core

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

El método ValidateAppRole se define en Microsoft.Identity.Web en RolesRequiredHttpContextExtensions.cs.The ValidateAppRole method is defined in Microsoft.Identity.Web in RolesRequiredHttpContextExtensions.cs.

ASP.NET MVCASP.NET MVC

private void ValidateAppRole(string appRole)
{
    //
    // The `role` claim tells you what permissions the client application has in the service.
    // In this case, we look for a `role` value of `access_as_application`.
    //
    Claim roleClaim = ClaimsPrincipal.Current.FindFirst("roles");
    if (roleClaim == null || !roleClaim.Value.Split(' ').Contains(appRole))
    {
        throw new HttpResponseException(new HttpResponseMessage
        { StatusCode = HttpStatusCode.Unauthorized,
            ReasonPhrase = $"The 'roles' claim does not contain '{appRole}' or was not found"
        });
    }
}
}

Aceptación de tokens solo de aplicación si la API web debe invocarse únicamente mediante aplicaciones de demonioAccepting app-only tokens if the web API should be called only by daemon apps

Los usuarios también pueden usar notificaciones de roles en patrones de asignación de usuarios, tal como se muestra en Procedimientos: Agregar roles de aplicación en la aplicación y recibirlos en el token.Users can also use roles claims in user assignment patterns, as shown in How to: Add app roles in your application and receive them in the token. Si los roles se asignan a ambos, comprobar los roles permitirá a las aplicaciones iniciar sesión como usuarios y a los usuarios iniciar sesión como aplicaciones.If the roles are assignable to both, checking roles will let apps sign in as users and users to sign in as apps. Le recomendamos que declare roles diferentes para los usuarios y las aplicaciones a fin de evitar esta confusión.We recommend that you declare different roles for users and apps to prevent this confusion.

Si quiere que únicamente las aplicaciones de demonio llamen a la API web, al validar el rol de aplicación, agregue una condición de que el token es solo de aplicación.If you want only daemon apps to call your web API, add the condition that the token is an app-only token when you validate the app role.

string oid = ClaimsPrincipal.Current.FindFirst("oid")?.Value;
string sub = ClaimsPrincipal.Current.FindFirst("sub")?.Value;
bool isAppOnlyToken = oid == sub;

Si aplica la condición inversa, permite que llamen a la API solo las aplicaciones que inician la sesión de un usuario.Checking the inverse condition allows only apps that sign in a user to call your API.

Pasos siguientesNext steps

Avance al siguiente artículo de este escenario, Paso a producción.Move on to the next article in this scenario, Move to production.