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

12

我有一个使用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)

这个应用程序使用了ADFS v2的非常标准的WIF实现,而没有使用RsaEncryptionCookieTransform。我正在寻找任何关于如何诊断的建议。我迄今为止尝试过以下几个方法:

  1. 应用程序池正在使用设置为“true”的“Load User Profile”选项的ASP.NET v4.0标识。
  2. 我删除了C:\Users\ASP.NET v4.0\AppData文件夹,并成功地重新创建了它。
  3. 我检查了证书私钥的权限,它们是良好的。我还尝试禁用令牌加密,但并没有任何区别。

希望能得到任何建议。

7个回答

19

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

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


1
谢谢。你证实了我的怀疑,这与cookie有关,所以我进行了大量的试错,并发现这是由另一个WIF安全的Web应用程序(在另一台服务器上)创建了一个路径为/的WIF cookie,显然正在尝试被此Web应用程序解密。我通过调整两个应用程序使用的路径值来解决了这个问题。奇怪的是,我只在IE中看到了这个错误,而不是Firefox / Chrome。我需要花更多时间来更好地理解这个问题。 - Brice Williams
我也遇到过同样的问题。很高兴你解决了它。我不确定为什么只有在IE中才能看到这个问题,但更改cookie路径应该是解决方法。 - Garrett Vlieger
我不小心删除了本地网站后,也遇到了同样的问题。删除了 wif 和 asp.net 的 cookies 后问题得以解决。 - Mike Cheel
1
在将我的负载均衡器指向不同的环境后,遇到了相同的问题。清除缓存解决了错误。 - TabsNotSpaces

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之外是否还有其他方法来处理它。非常感谢任何帮助! 谢谢! Alex

1
Application_Error全局处理程序似乎是合适的位置。以下代码可以参考:var exc = Server.GetLastError(); if (exc is CryptographicException || exc.InnerException is CryptographicException) { Server.ClearError(); ResetAuthentication(); }这对我很有效。 - achekh

3

我解决了我的问题,因为我有两个应用程序使用相同的cookie名称“FedAuth”(这是默认名称)。只需更改一个不同的名称即可解决:

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


2
以下方法对我有用:
您需要将
添加到 system.identityModel/identityConfiguration。
参考文献: SessionSecurityTokenHandler尝试使用DPAPI解密RSA加密的cookie中的SessionSecurityToken;为什么?
  <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>

1
删除 FedAuth cookies 可能会起作用。当异常发生时,请在 Global.asax 文件的 Application_Error 方法中尝试此操作:
Microsoft.IdentityModel.Web.FederatedAuthentication.SessionAuthenticationModule.SignOut();

0

0
这个问题是由于权限不足引起的。 应用程序池应该具有ApplicationPoolIdentity身份才能使其正常工作。 转到您的应用程序池 ->高级设置 ->内置帐户来更改设置。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接