Я в ситуации, когда мне нужно получить доступ к ASP.NET Web Api, использующему ADFS для аутентификации. Я могу надежно ударить его через свой браузер, пройдя через портал входа в ADFS и получив соответствующий файл cookie FedAuth. К сожалению, мне нужно получить доступ к нему за пределами выделенного браузера для использования в мобильном приложении. Проект представляет собой слегка измененную версию стандартного шаблона веб-апитера Visual Studio, настроенного для проверки работы и школьной аутентификации (на месте) и настроенного для аутентификации cookie.Аутентификация ASP.NET Web Api с использованием ADFS
бит кода из Startup.Auth.cs:
public void Configuration(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseWsFederationAuthentication(
new WsFederationAuthenticationOptions
{
Wtrealm = realm,
MetadataAddress = adfsMetadata
});
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = WsFederationAuthenticationDefaults.AuthenticationType
});
}
Я не могу показаться, чтобы выяснить, с чего начать. Я пробовал просить токен доступа из ADFS и могу получить разные версии утверждений SAML, используя соответствующую информацию для входа, но он отвергается веб-API. Не понял ли я, как он должен работать?
Из моего понимания, что он должен идти, как это: How I think it's supposed to work
- App запрашивает маркер аутентификации от ADFS
- ADFS дает REQUESTEE маркер аутентификации, если информация верна
- App делает запрос веб-API и отправляет токен внутри куки-файла FedAuth (по умолчанию в любом случае) в виде строки с кодировкой base64
- Web Api отправляет токен в ADFS, чтобы узнать, n корректно.
- ADFS отвечает каким-то успехом
- Web Api отвечает на приложение либо с отказом, либо с частицами данных в зависимости от того, как прошла аутентификация.
Это то, что я имею прямо сейчас, пытаясь выяснить, как получить правильные жетоны.
using System;
using System.IdentityModel.Protocols.WSTrust;
using System.IdentityModel.Tokens;
using System.Net;
using System.Net.Http;
using System.ServiceModel;
using System.ServiceModel.Security;
using Thinktecture.IdentityModel.Extensions;
using Thinktecture.IdentityModel.WSTrust;
namespace ConsoleApplication1
{
class Program
{
private const string UserName = "USERNAME";
private const string Password = "PASSWORD";
private const string Domain = "DOMAIN";
private const string ADFSEndpoint = "ADFS ENDPOINT";
private const string ApiBaseUri = "THE API";
private const string ApiEndPoint = "AN ENDPOINT";
static void Main(string[] args)
{
SecurityToken token = RequestSecurityToken(); // Obtain security token from ADFS.
CallApi(token); // Call api.
Console.ReadKey(); // Stop console from closing
}
private static SecurityToken RequestSecurityToken()
{
var trustChannelFactory =
new WSTrustChannelFactory(new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential),
new EndpointAddress(new Uri(ADFSEndpoint)))
{
TrustVersion = TrustVersion.WSTrust13,
Credentials = { UserName = { UserName = UserName + "@" + Domain, Password = Password } },
};
var requestSecurityToken = new RequestSecurityToken
{
RequestType = RequestTypes.Issue,
KeyType = KeyTypes.Bearer,
AppliesTo = new EndpointReference(ApiBaseUri)
};
RequestSecurityTokenResponse response;
var securityToken = trustChannelFactory.CreateChannel().Issue(requestSecurityToken, out response);
return securityToken;
}
private static async void CallApi(SecurityToken securityToken)
{
using (var handler = new HttpClientHandler { CookieContainer = new CookieContainer() })
{
using (var client = new HttpClient(handler))
{
handler.CookieContainer.MaxCookieSize = 8000; // Trying to make sure I can fit it in the cookie
var cookie = new Cookie {
Name = "FedAuth",
Value = Base64Encode(securityToken.ToTokenXmlString()),
HttpOnly = true,
Secure = true
};
handler.CookieContainer.Add(new Uri(ApiBaseUri), cookie);
var response = client.GetAsync(new Uri(ApiBaseUri + ApiEndPoint)).Result;
string result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
}
public static string Base64Encode(string plainText)
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
return System.Convert.ToBase64String(plainTextBytes);
}
}
}
Я не могу точно вспомнить, что код, который я на основе моего примера, но если кто-нибудь может мне точку в правильном направлении или скажите мне, где я облажался, я ценю это.
Редактировать: Извините, забыли добавить то, что я получаю. Web Api вырывает кучу отладочной информации, потому что было выбрано исключение, сообщая мне, что ожидается отказ SecurityContextToken вместо saml: Assertion, который я, по-видимому, получаю. Возможно, мой googlefoo недостаточно мощный, но я не могу понять, с чего начать. Могу ли я настроить api для принятия утверждений SAML или мне нужно запросить токен по-другому?
Похоже, сервер ADFS был 2.0, но скоро будет обновлен. До сих пор я применил немного пэчворкового решения (генерация маркера OAuth и проверка на веб-ави), но только ради того, чтобы кто-либо еще нашел этот пост, что бы вы предложили в качестве приемлемого решения этой проблемы? – Tennaheim
Используйте идентификатор сервера и федерацию с ADFS. – nzpcmad
Я также пытаюсь вызвать веб-api, но он не вызывается с использованием приложения wpf. Ошибка авторизации возникает во время вызова. Если я удалил атрибут authorize из контроллера, он будет вызван – Mohan