Microsoft.IdentityModel:密钥无法在指定状态下使用

时间:2011-11-22 16:37:03

标签: cryptography wif

我有一个使用Windows Identity Foundation的声明感知Web应用程序,除了在一台服务器上运行良好。我在事件日志中看到了如下所示的错误消息。

Exception information: 
    Exception type: CryptographicException 
    Exception message: Key not valid for use in specified state.

   at System.Security.Cryptography.ProtectedData.Unprotect(Byte[] encryptedData, Byte[] optionalEntropy, DataProtectionScope scope)
   at Microsoft.IdentityModel.Web.ProtectedDataCookieTransform.Decode(Byte[] encoded)

此应用程序使用非常标准的WIF实现与ADFS v2。它没有使用RsaEncryptionCookieTransform。我正在寻找有关如何诊断这一点的任何建议。到目前为止我尝试过的事情:

  1. 应用程序池使用的是ASP.NET v4.0标识,其“加载用户配置文件”设置为true。
  2. 我删除了C:\ Users \ ASP.NET v4.0 \ AppData文件夹,看到它已成功重新创建。
  3. 我检查了证书私钥的权限,这很好。我也试过禁用令牌加密,这没有任何区别。
  4. 任何建议都将受到赞赏。

7 个答案:

答案 0 :(得分:15)

这通常是由应用程序无法解密身份验证令牌cookie引起的。确保拥有应用程序池的标识具有足够的权限来访问您的证书存储区。尝试将身份更改为NetworkService,看看是否有帮助。

您还应该清除浏览器的Cookie,以确保您没有来自缓存的其他应用程序的Cookie。

答案 1 :(得分:7)

该问题100%可重现:

实际上,在重新部署应用程序之后,旧的身份验证cookie留在客户端计算机上(客户端没有注销) - 此错误在客户端出现在任何后续请求中。 要修复此错误,客户端必须删除cookie和/或登录,然后从STS注销。一旦完成 - 错误消失,一切都很好,直到下次升级....

经过一些研究,我认为这是SessionAuthenticationModule中需要修复的错误。如果仔细查看上面的堆栈跟踪,有一个名为TryReadSessionTokenFromCookie的有趣方法,它设置了认证模块将“尝试”从cookie读取令牌的期望,如果失败则返回false - 这是代码(感谢ReSharper的):

public bool TryReadSessionTokenFromCookie(out SessionSecurityToken sessionToken)
{
    byte[] sessionCookie = this.CookieHandler.Read();
    if (sessionCookie == null)
    {
        sessionToken = null;
        return false;
    }
    sessionToken = this.ReadSessionTokenFromCookie(sessionCookie);
    if (DiagnosticUtil.TraceUtil.ShouldTrace(TraceEventType.Verbose))
    {
        DiagnosticUtil.TraceUtil.Trace(TraceEventType.Verbose, TraceCode.Diagnostics, SR.GetString("TraceValidateToken", new object[0]), new TokenTraceRecord(sessionToken), null);
    }
    return true;
}

显然,此方法的代码在未处理的错误中失败,并且开发人员没有任何选项来以或多或少的合理方式处理错误。 (...或者至少我找不到任何东西,因为这个HTTP模块没有将此错误传递给HttpApplication对象进行处理,并将其抛入用户的脸部。) 所以,我认为有两个错误: 1)安全令牌处理程序需要更具体地说明抛出ID1073的原因(服务器端解密错误或错误(旧)cookie错误) 2)开发人员必须有办法处理此错误并签署用户(如果发生)。我会对这个问题采取任何帮助...... 任何人都可以创建示例代码,显示如何拦截此异常,以便在发生此错误时用户可以自动注销?同样,Application.Error事件似乎没有从这个模块中被触发 - 除了编写我自己的SessionAuthenticationModule之外,不确定还能做些什么来处理它。 任何帮助都被高度赞赏!!! 谢谢! 亚历

答案 2 :(得分:3)

我解决了我的情况,因为我为两个应用程序提供了相同的cookie名称“FedAuth”(默认情况下这是名称)。只需添加一个不同的名称即可:

<system.identityModel.services>
<federationConfiguration>
  <cookieHandler name="ACookieName" />
</federationConfiguration>

答案 3 :(得分:2)

以下对我有用:

您需要将section添加到system.identityModel / identityConfiguration

参考: SessionSecurityTokenHandler trying to decrypt SessionSecurityToken in RSA-encrypted cookie using DPAPI; why?

  <system.identityModel>
    <identityConfiguration saveBootstrapContext="true">
      <audienceUris>
        <add value="yoursite.com" />
      </audienceUris>
      <issuerNameRegistry type="Thinktecture.IdentityModel.Tokens.MetadataBasedIssuerNameRegistry, Thinktecture.IdentityModel">
        <trustedIssuerMetadata issuerName="urn:federation:company:stage" metadataAddress="https://federation-sts-stage.company.com/FederationMetadata/2007-06/FederationMetadata.xml"></trustedIssuerMetadata>
      </issuerNameRegistry>
      <certificateValidation certificateValidationMode="None" />
<securityTokenHandlers>
     <add type="System.IdentityModel.Services.Tokens.MachineKeySessionSecurityTokenHandler,  
             System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />

      <remove type="System.IdentityModel.Tokens.SessionSecurityTokenHandler, 
            System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
    </securityTokenHandlers>
    </identityConfiguration>
  </system.identityModel>

答案 4 :(得分:1)

删除FedAuth Cookie可能有效。发生异常时,请在Application_Error文件的Global.asax方法中尝试此操作:

Microsoft.IdentityModel.Web.FederatedAuthentication.SessionAuthenticationModule.SignOut();

答案 5 :(得分:0)

http应用程序似乎没有捕获此错误。 请改为http://social.technet.microsoft.com/wiki/contents/articles/1898.aspx#Q1

答案 6 :(得分:0)

此问题是由于权限不足所致。 应用程序池应具有 ApplicationPoolIdentity 身份以使其正常运行。 转到您的apppool->高级设置->内置帐户以更改设置