OWIN - 清除无效的WSFederation cookie

时间:2017-03-28 13:08:39

标签: asp.net-web-api owin adfs ws-federation owin-middleware

我使用ADFS cookie身份验证实现了一个ASP.Net Web API 2项目,并将其托管在IIS上。一切正常。

但是,有些客户端因旧配置更改而变旧无效。调用我的API时,此类cookie会导致以下错误:

[CryptographicException: Key not valid for use in specified state.
]
   System.Security.Cryptography.ProtectedData.Unprotect(Byte[] encryptedData, Byte[] optionalEntropy, DataProtectionScope scope) +447
   System.IdentityModel.ProtectedDataCookieTransform.Decode(Byte[] encoded) +49

[InvalidOperationException: ID1073: A CryptographicException occurred when attempting to decrypt the cookie using the ProtectedData API (see inner exception for details). If you are using IIS 7.5, this could be due to the loadUserProfile setting on the Application Pool being set to false. ]
   System.IdentityModel.ProtectedDataCookieTransform.Decode(Byte[] encoded) +329
   System.IdentityModel.Tokens.SessionSecurityTokenHandler.ApplyTransforms(Byte[] cookie, Boolean outbound) +167
   System.IdentityModel.Tokens.SessionSecurityTokenHandler.ReadToken(XmlReader reader, SecurityTokenResolver tokenResolver) +826
   System.IdentityModel.Tokens.SessionSecurityTokenHandler.ReadToken(Byte[] token, SecurityTokenResolver tokenResolver) +92
   System.IdentityModel.Services.SessionAuthenticationModule.ReadSessionTokenFromCookie(Byte[] sessionCookie) +569
   System.IdentityModel.Services.SessionAuthenticationModule.TryReadSessionTokenFromCookie(SessionSecurityToken& sessionToken) +306
   System.IdentityModel.Services.SessionAuthenticationModule.OnAuthenticateRequest(Object sender, EventArgs eventArgs) +159
   System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +142
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +92

明显的解决方法是清除cookie。但是,我将来可能会再次更改Cookie配置,因此我想从API中自动清除所有无效的Cookie。

我尝试添加自定义OWIN中间件并覆盖IExceptionHandler

这是我的WIF配置:

<system.identityModel>
  <identityConfiguration>
    <audienceUris>
      <add value="https://my.web-api.com" />
    </audienceUris>
    <issuerNameRegistry type="System.IdentityModel.Tokens.ValidatingIssuerNameRegistry, System.IdentityModel.Tokens.ValidatingIssuerNameRegistry">
      <authority name="ADFS">
        <keys>
          <add thumbprint="--a thumbprint--" />
        </keys>
        <validIssuers>
          <add name="http://my.adfs.com/adfs/services/trust" />
        </validIssuers>
      </authority>
    </issuerNameRegistry>
  </identityConfiguration>
</system.identityModel>
<system.identityModel.services>
  <federationConfiguration>
    <wsFederation issuer="https://my.adfs.com/adfs/ls" realm="https://my.web-api.com" requireHttps="true" passiveRedirectEnabled="false"
                  persistentCookiesOnPassiveRedirects="true" />
    <cookieHandler name="my.cookie" path="/" persistentSessionLifetime="7.0:0:0" />
    <serviceCertificate>
      <certificateReference x509FindType="FindBySubjectName" findValue="my.web-api.com" storeLocation="LocalMachine" storeName="My" />
    </serviceCertificate>
  </federationConfiguration>
</system.identityModel.services>

这是我的Startup课程:

public class Startup
{
    public void Configuration(IAppBuilder appBuilder)
    {
        var config = new HttpConfiguration();

        config.Services.Replace(typeof(IExceptionHandler), new CryptographicExceptionHandler());
        WebApiConfig.Register(config);
        appBuilder.UseWebApi(config);
        appBuilder.Use<ClearInvalidCookiesMiddleware>();
    }
}

无论CryptographicExceptionHandlerClearInvalidCookiesMiddleware内部是什么,他们的代码都没有被调用,而且我得到500错误。我还尝试在ClearInvalidCookiesMiddleware之前移动UseWebApi

我的目标是添加Set-Cookie响应标头以清除无效的Cookie并返回401或重定向。

在这种情况下,如何让OWIN自定义响应?

1 个答案:

答案 0 :(得分:0)

解决方案似乎会覆盖SessionAuthenticationModule.OnAuthenticateRequest并在出现例外时调用SignOut()

class ClearInvalidCookiesSessionAuthenticationModule : SessionAuthenticationModule
{
    protected override void OnAuthenticateRequest(object sender, EventArgs eventArgs)
    {
        try
        {
            base.OnAuthenticateRequest(sender, eventArgs);
        }
        catch(InvalidOperationException ex) when (ex.InnerException is CryptographicException) // Invalid cookie signing key
        {
            SignOut();
        }
        catch(System.Xml.XmlException) // Invalid cookie structure
        {
            SignOut();
        }
    }
}

要使用继承的类而不是默认的类,应在Web.config中插入以下行:

<system.webServer>
  <modules ...>
    <!-- Insert the line below or replace existing SessionAuthenticationModule -->
    <add name="SessionAuthenticationModule" preCondition="managedHandler"
         type="MyNamespace.ClearInvalidCookiesSessionAuthenticationModule, MyAssembly" />
    ...
  </modules>
...
</system.webServer>