Поделиться через


Защищенный веб-API: проверка областей и ролей приложения

Область применения: Зеленый круг с символом белой галочки. арендаторы рабочей силы Белый круг с серым символом X. внешние арендаторы (подробнее)

В этой статье описывается, как можно добавить авторизацию в веб-API. Эта защита гарантирует, что API будет вызываться только:

  • Приложения от имени пользователей, обладающих соответствующими областями и ролями.
  • демон-приложения, имеющие правильные роли приложений.

Фрагменты кода в этой статье взяты из следующих примеров кода на сайте GitHub:

Чтобы защитить веб-API ASP.NET или ASP.NET Core, необходимо добавить атрибут [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.
        // ...
    }
 // ...
}

Убедитесь в глобальной проверке областей охвата

Мы рекомендуем детально определить области действия для веб-API и проверить эти области для каждого действия контроллера. Но вы можете проверить области на уровне приложения или контроллера. Для получения дополнительной информации см. авторизацию на основе утверждений в документации по ASP.NET Core.

Что входит в проверку?

Атрибут [RequiredScope] и метод VerifyUserHasAnyAcceptedScope выполняют примерно следующие шаги:

  • Проверьте, существует ли утверждение с именем http://schemas.microsoft.com/identity/claims/scope или scp.
  • Проверьте, что утверждение имеет значение, которое содержит область, ожидаемую API.

Проверка ролей приложения в интерфейсах API, которые вызываются приложениями управляющей программы

Если веб-API вызывается демон-приложением, это приложение должно требовать разрешения на доступ к вашему веб-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 содержит несколько подходов к реализации авторизации на основе ролей. Разработчики могут выбрать один из них, который подходит для их сценариев.

Рабочие примеры см. в пошаговом руководстве по созданию веб-приложения с авторизацией по ролям и группам.

Проверка ролей приложений в интерфейсах API, вызываемых от имени пользователей

Пользователи также могут использовать утверждения ролей в схемах назначения пользователей, как показано в разделе Как добавить роли приложения в ваше приложение и получить их в токене. Если роли могут быть назначены обоим, проверка ролей позволит приложениям входить в систему в качестве пользователей, а пользователям входить в качестве приложений. Для предотвращения этой путаницы рекомендуется объявлять разные роли для пользователей и приложений.

Если вы определили роли приложений с пользователем или группой, утверждение ролей также можно проверить в API вместе с областями. Логика проверки ролей приложения в этом сценарии остается такой же, как если API вызывается приложениями управляющей программы, так как в утверждении роли для пользователя или группы и приложения нет различий.

Принятие токенов только для приложений, если веб-API должен вызываться исключительно демон-приложениями.

Если вы хотите, чтобы только демон-приложения вызывали ваш веб-API, добавьте условие, что токен является только токеном приложения при проверке роли приложения.

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

Проверка обратного условия позволяет только приложениям, которые входят в систему в качестве пользователя, вызывать ваш API.

Использование авторизации на основе списков управления доступом

Вместо авторизации на основе ролей приложения можно использовать для защиты веб-API другой шаблон авторизации, основанный на списках управления доступом (ACL), который позволяет управлять маркерами без утверждения 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 на значение true в appsettings.json или программно.

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

Если задано значение AllowWebApiToBeAuthorizedByACLtrue, это ваша ответственность за обеспечение механизма ACL.

Следующие шаги

  • Узнайте больше, создав веб-приложение ASP.NET Core, которое позволяет пользователям входить в систему, в следующей серии руководств с несколькими частями

  • Ознакомьтесь с веб-API примерами платформы удостоверений Майкрософт