Пользовательская авторизация с помощью аутентификации Azure AD в OWIN Web API
Мы используем аутентификацию Azure AD для одного из наших клиентских приложений. Мы хотим реализовать авторизацию на основе утверждений вместе с ней.
Наше приложение настроено как клиентское приложение на основе Angular, соединяющееся через веб-API (оба клиентских сервера защищены с помощью аутентификации на предъявителя AD Azure). Серверное приложение размещается с использованием OWIN.
Нам нужно предоставить пользовательскую авторизацию на стороне сервера. В Azure AD предусмотрена возможность добавления пользователей и ролей. Однако этого нам недостаточно. Наше управление пользователями осуществляется через группы AD и Security. Чтобы получить доступ к приложению, пользователям необходима часть базовой группы, и дополнительные права (доступ к определенному разделу приложения, редактирование определенного объекта и т. Д.) Назначаются на основе дополнительных групп или предоставляются непосредственно пользователям в приложении. По сути, не все пользователи будут зарегистрированы в приложении, и нам, возможно, придется запросить AD, используя Graph API, чтобы проверить, к какой группе относятся все конкретные приложения.
Модель аутентификации и авторизации OWIN основана на сервере аутентификации и сервере ресурсов. Мы можем разделить их по мере необходимости. Однако в нашем случае нам нужно разделить аутентификацию и авторизацию. Когда клиент представляет токен на предъявителя, нам необходимо проверить, является ли токен действительным, и затем добавить утверждения в профиль пользователя. Нам также необходимо кэшировать заявки пользователей, чтобы мы не часто обращались к базе данных. (Наше клиентское приложение выполняет несколько вызовов Web API за одно действие пользователя.)
Каково расположение в Identity 2.0, где
- Я могу проверить токен
- вставить претензии конкретных приложений
Если все мое приложение вращается вокруг авторизации пользователя и все запросы должны быть отфильтрованы по тем данным, к которым пользователь может получить доступ, что является более подходящим шаблоном проектирования для приложения Web API?
2 ответа
Я считаю, что вам нужны фильтры аутентификации и авторизации в стеке ASP.NET Web API 2.0.
Вы можете реализовать авторизацию для каждого веб-метода, реализовав System.Web.Http.Filters.IAuthorizationFilter в классе атрибутов, а затем украсить методы веб-действий контроллера службы этим атрибутом. Web API 2.0 выберет метод на основе URL-маршрутизации, заметит, что в этом методе реализован атрибут, реализующий IAuthorizationFilter, и вызовет метод ExecuteAuthorizationFilterAsync для этого экземпляра атрибута перед вызовом веб-метода. Размещение шага авторизации перед вызовом веб-метода позволяет быстро отбрасывать недействительные запросы, прежде чем приступить к тяжелой работе с привязкой параметров.
Входящий токен проверяется реализацией IAuthenticationFilter, которая выполняется перед этапом авторизации.
Документацию и примеры очень сложно найти. Вот один из немногих релевантных результатов поиска: http://thegrumpycoder.com/post/105427070626/secure-web-services-with-web-api-and-sitecore
Вы можете проверить, помогает ли это...
UserProfile profile = new UserProfile(); //To deserialize the response stream (JSON)
string tenantId = ClaimsPrincipal.Current.FindFirst(TenantIdClaimType).Value;
AuthenticationResult result = null;
try
{
// Get the access token from the cache
string userObjectID =
ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier")
.Value;
AuthenticationContext authContext = new AuthenticationContext(Startup.Authority, new NaiveSessionCache(userObjectID));
//use ClientID, ClientSecret
ClientCredential credential = new ClientCredential("b557ceed-xxxx-xxxx-xxxx-xxxxxxxbc240", "AXFxx//xxxxxxxxxxxxxjVFz4sqYm8NDAPEOLkU=");
result = authContext.AcquireTokenSilent("https://graph.windows.net", credential,
new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));
// AcquireTokenSilent may throw exception if the cache is empty. In that case, logout the user and make him login.
string requestUrl = String.Format(
CultureInfo.InvariantCulture,
"https://graph.windows.net/cdmsdev.onmicrosoft.com/groups/b40xxxx-14a8-xxxx-9559-xxxxxxca90c8/members/?api-version=1.6");
//Above grap API url is for getting list of users who belong to a specific group (with GUID b40xxxx-1....)
HttpClient client = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, requestUrl);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
HttpResponseMessage response = client.SendAsync(request).Result;
if (response.IsSuccessStatusCode)
{
var upn = ClaimsPrincipal.Current.Identity.Name;
string responseString = response.Content.ReadAsStringAsync().Result;
profile = JsonConvert.DeserializeObject<UserProfile>(responseString);
if (profile.Users.Contains(upn)) //check if the current user is in the list of users of the Admin group
return true;
}
}
catch (Exception e)
{
//handle authorization exception here
}
URL API графа может быть заменен функцией для проверки членства в определенной группе, которая будет непосредственно возвращать bool
значение вместо получения всех пользователей этой группы.