2016-04-15 9 views
2

Ping Federateを使用して、2つのWebサーバー(IIS統合キットを使用して保護されたIISとPingのopentokenモジュールの両方)を保護します。一方のサーバーはWEB APIアプリケーションをホストし、他方のサーバーはWebページをホストします。 Web APIアプリケーションでCORSが有効になっています。Pingfederate opentoken module CORSリクエストは200の代わりに302を返します。

ウェブページは、jsonデータを含むAjaxのポストリクエストをAPIサーバーに送信します。これにより、ブラウザはプリフライトオプション要求を開始します。 APIサーバーでは、Pingモジュールは資格情報を含まないこの要求をインターセプトします(仕様では、プリフライトオプション要求に資格情報が含まれていないと言われています)。そして、Web APIコードが200を返すべきときに処理する前に302リダイレクトを返します。

私の唯一の推測は、オプション要求を処理してopentokenモジュールの前にインストールするカスタムモジュールを作ることです。他の可能な/より良い解決策がありますか?

答えて

1

PINGを待つ代わりに、IAuthorizationFilterを.NET Integration Kit/Agentの上に置きました。このようなカスタムフィルタについての素晴らしい点は、APIエンドポイントのセキュリティ要件をより詳細に制御できることです。

私は以下の参考文献に使用されるフィルタの書き込み:opentokenを使用して

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

    を。 PF.SAML.Resultを使用している 。 using System; using System.Collections.Generic; using System.Configuration; using System.Linq; System.Net.Http;を使用している ; System.Net.Http.Headersを使用している ; using System.Security.Claims; using System.Text; System.Threadingを使用している ; using System.Threading.Tasks; using System.Web.Http.Filters;

    名前空間PF.SAML。フィルタ { パブリッククラスPingAuthenticationAttribute:IAuthenticationFilter { 公共ブールAllowMultiple {{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 Agent/integration kitの実装に伴うバグですか?

私はOPに同意します。現在のW3C勧告(https://www.w3.org/TR/cors/#preflight-request)は、は、プリフライト/ OPTIONS要求でユーザー資格情報を除外していると明示しています。したがって、OPTIONS要求は匿名要求を許可する必要があります。アイデンティティプロバイダ(IdP)を指し示す302を取得することは、私には推薦に従わないと言います。


(これが唯一のPINGサーバー自体に役立ちます、統合キットは、まだ匿名のOPTIONS要求を許可する必要があります。) のPingフェデレートは、桟橋の設定ファイルに多くの構成設定で戻ってきた:

<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

関連する問題