2017-02-15 25 views
3

Я в ситуации, когда мне нужно получить доступ к 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

  1. App запрашивает маркер аутентификации от ADFS
  2. ADFS дает REQUESTEE маркер аутентификации, если информация верна
  3. App делает запрос веб-API и отправляет токен внутри куки-файла FedAuth (по умолчанию в любом случае) в виде строки с кодировкой base64
  4. Web Api отправляет токен в ADFS, чтобы узнать, n корректно.
  5. ADFS отвечает каким-то успехом
  6. 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 или мне нужно запросить токен по-другому?

ответ

3

Вы не можете использовать WS-Fed для вызова веб-API. Вам нужно OpenID Connect/OAuth, как в Calling a web API in a web app using Azure AD and OpenID Connect.

Это для Azure AD, но это иллюстрирует поток.

Какая версия ADFS?

+0

Похоже, сервер ADFS был 2.0, но скоро будет обновлен. До сих пор я применил немного пэчворкового решения (генерация маркера OAuth и проверка на веб-ави), но только ради того, чтобы кто-либо еще нашел этот пост, что бы вы предложили в качестве приемлемого решения этой проблемы? – Tennaheim

+0

Используйте идентификатор сервера и федерацию с ADFS. – nzpcmad

+0

Я также пытаюсь вызвать веб-api, но он не вызывается с использованием приложения wpf. Ошибка авторизации возникает во время вызова. Если я удалил атрибут authorize из контроллера, он будет вызван – Mohan