2016-04-15 5 views
2

Мы используем Ping Federate для защиты двух веб-серверов (оба IIS и оба защищены с использованием набора интеграции IIS или модуля opentoken от Ping). На одном сервере размещено приложение WEB API, а на других узлах - веб-страница. Приложение Web API поддерживает CORS.Pingfederate opentoken module Запрос CORS возвращает 302 вместо 200

Веб-страница отправляет запросы Ajax с данными json на сервер API. Это заставляет браузер инициировать запрос опций перед полетом. На сервере API модуль Ping перехватывает этот запрос, который не содержит учетных данных (спецификации говорят, что запросы опционных опций не должны содержать учетные данные) и возвращают перенаправление 302 до того, как код веб-API сможет обрабатывать его, когда он должен вернуть 200 .

Единственное, что я могу предположить, это создать настраиваемый модуль, который обрабатывает запросы параметров и устанавливает его перед модулем opentoken. Есть ли другие возможные/лучшие решения?

ответ

1

Вместо ожидания PING я поставил IAuthorizationFilter поверх своего .NET Integration Kit/Agent. Хорошая вещь о настраиваемом фильтре, подобном этому, - это усиление контроля над требованиями безопасности конечных точек API.

При написании фильтра я использовал следующие ссылки:

  • http://www.asp.net/web-api/overview/security/authentication-filters
  • https://msdn.microsoft.com/en-us/magazine/dn781361.aspx

    с использованием opentoken; с использованием PF.SAML.Result; с использованием системы; с использованием System.Collections.Generic; с использованием System.Configuration; с использованием System.Linq; с использованием System.Net.Http; с использованием System.Net.Http.Headers; с использованием System.Security.Claims; с использованием System.Text; с использованием System.Threading; с использованием System.Threading.Tasks; с использованием System.Web.Http.Filters;

    namespace PF.SAML.Фильтры { public class PingAuthenticationAttribute: IAuthenticationFilter { public bool AllowMultiple {get {return false; }}

    // http://www.asp.net/web-api/overview/security/authentication-filters 
        // https://msdn.microsoft.com/en-us/magazine/dn781361.aspx 
        public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken) 
        { 
         await Task.Run(() => { 
          /* 
          * Look for credentials in the request. 
          * If there are no credentials, do nothing and return (no-op). 
          * If there are credentials but the filter does not recognize the authentication scheme, do nothing and return (no-op). Another filter in the pipeline might understand the scheme. 
          * If there are credentials that the filter understands, try to authenticate them. 
          * If the credentials are bad, return 401 by setting context.ErrorResult. 
          * If the credentials are valid, create an IPrincipal and set context.Principal. 
          */ 
          var opentoken = context.Request.Headers.GetCookies() 
           .SelectMany(c => c.Cookies) 
           .Where(c => c.Name == "opentoken") 
           .FirstOrDefault(); 
    
          if(opentoken == null) return; 
    
          var userInfo = getOpenToken(opentoken.Value); 
    
          if(userInfo == null) { 
           context.ErrorResult = new AuthenticationFailureResult("Invalid Token", context.Request); 
           return; 
          } 
    
          var claims = new List<Claim>(); 
          foreach(var item in userInfo) { 
           foreach(var value in userInfo[item.Key]) { 
            claims.Add(new Claim(item.Key, value)); 
           } 
          } 
    
          var id = new ClaimsIdentity(claims, "opentoken"); 
          var principle = new ClaimsPrincipal(new[] { id }); 
    
          context.Principal = principle; 
    
         }); 
        } 
    
        public async Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken) 
        { 
         await Task.Run(() => { 
          var challenge = new AuthenticationHeaderValue("SAML"); 
          context.Result = new AddChallengeOnUnauthorizedResult(challenge, context.Result); 
         }); 
        } 
    
    
        private MultiStringDictionary getOpenToken(string token) 
        { 
         MultiStringDictionary attributes = null; 
    
         Configuration.Agent agentConfig = (Configuration.Agent) ConfigurationManager.GetSection("pfConfigurationGroup/agentConfiguration"); 
         AgentConfiguration config = new AgentConfiguration 
         { 
          CookieDomain = agentConfig.CookieDomain, 
          CookiePath = agentConfig.CookiePath, 
          NotBeforeTolerance = agentConfig.NotBeforeTolerance, 
          ObfuscatePassword = agentConfig.ObfuscatePassword, 
          RenewUntilLifetime = agentConfig.RenewUntilLifetime, 
          SecureCookie = agentConfig.SecureCookie, 
          SessionCookie = agentConfig.SessionCookie, 
          TokenLifetime = agentConfig.TokenLifetime, 
          TokenName = agentConfig.TokenName, 
          UseCookie = agentConfig.UseCookie, 
          UseSunJCE = agentConfig.UseSunJCE, 
          UseVerboseErrorMessages = agentConfig.UseVerboseErrorMessages 
         }; 
    
         var str = (config.ObfuscatePassword 
          ? Encoding.UTF8.GetString(Obfuscator.Deobfuscate(agentConfig.Password)) 
          : Encoding.ASCII.GetString(Convert.FromBase64String(agentConfig.Password))); 
         config.SetPassword(str, Token.CipherSuite.AES_128_CBC); 
    
         // TODO: Check for token expiration 
    
         Agent agent = new Agent(config); 
         attributes = agent.ReadTokenMultiStringDictionary(token); 
    
         return attributes; 
        } 
    } 
    

    }

+0

В итоге я объединил свои серверы, чтобы обойти эту проблему. Это похоже на лучший способ, если PING не предоставляет решения, поэтому я буду отмечать это как ответ, но может изменить его, если PING предоставляет полезную информацию. – jp36

+0

Я бы рекомендовал поместить пример созданного вами фильтра (если возможно) или более общий пример фильтра. StackOverflow хмурится только ответами на ссылки (ссылки могут умереть, сложнее найти информацию и т. Д.). - Пример получает upvote! – jp36

0

Является ли это ошибкой с внедрением агента/интеграции интегрального пакета PING Federate IIS?

Я согласен с OP. Текущая рекомендация W3C (https://www.w3.org/TR/cors/#preflight-request) явно указывает на исключить учетные данные пользователя в запросе предполетного/ОПЦИИ. Поэтому запрос OPTIONS разрешает анонимный запрос. Как мне кажется, 302, обращаясь к поставщику удостоверений (IdP), не соответствует рекомендации.


(Это только помогает на самом PING сервере, комплект интеграции по-прежнему необходимо разрешить анонимные OPTIONS запросы.) Ping Federate вернулся с большим количеством параметров конфигурации в файле молы конфигурации:

<security-constraint> 
    <web-resource-collection> 
     <web-resource-name>Disable TRACE OPTIONS HEAD</web-resource-name> 
     <url-pattern>/*</url-pattern> 
     <http-method>TRACE</http-method> 
     <http-method>OPTIONS</http-method> 
    </web-resource-collection> 
    <auth-constraint/> 
</security-constraint> 
+0

Я думаю, что это может быть ошибка. Я жду, чтобы услышать от PING, чтобы узнать, есть ли у них больше информации об этой проблеме. – jp36

 Смежные вопросы

  • Нет связанных вопросов^_^