在服务器/应用程序ID1006之间共享IClaimsPrincipal / FedAuth Cookie

时间:2012-11-30 16:21:54

标签: wif federated-identity ws-federation

我有一个使用Azure ACS(和间接ADFS)进行身份验证的ASP.NET应用程序 - 一切正常。现在我被要求将SessionToken传递给另一个后端服务,在那里可以验证它并提取声明。 [长篇故事,而不是我的选择]

我对解密方面有所帮助,我确信我遗漏了一些基本的东西。

要设置阶段,解密时的错误是:

ID1006: The format of the data is incorrect. The encryption key length is negative: '-724221793'. The cookie may have been truncated.

ASP.NET网站使用RSA包装器ala:

void WSFederationAuthenticationModule_OnServiceConfigurationCreated(object sender, ServiceConfigurationCreatedEventArgs e)
    {
        string thumbprint = "BDE74A3EB573297C7EE79EB980B0727D73987B0D";

        X509Certificate2 certificate = GetCertificate(thumbprint);

        List<CookieTransform> sessionTransforms = new List<CookieTransform>(new CookieTransform[] 
        { 
            new DeflateCookieTransform(), 
            new RsaEncryptionCookieTransform(certificate), 
            new RsaSignatureCookieTransform(certificate) 
        });

        SessionSecurityTokenHandler sessionHandler = new SessionSecurityTokenHandler(sessionTransforms.AsReadOnly());
        e.ServiceConfiguration.SecurityTokenHandlers.AddOrReplace(sessionHandler);
    }

(指纹与Fed.til在web.config中添加的值相同。

我用以下代码编写令牌:

if (Microsoft.IdentityModel.Web.FederatedAuthentication.SessionAuthenticationModule.TryReadSessionTokenFromCookie(out token))
{
    Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler th = new Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler();
    byte[] results = th.WriteToken(token);
...

给了我:

<?xml version="1.0" encoding="utf-8"?>
<SecurityContextToken p1:Id="_53382b9e-8c4b-490e-bfd5-de2e8c0f25fe-94C8D2D9079647B013081356972DE275" 
                  xmlns:p1="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" 
                  xmlns="http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512">
<Identifier>urn:uuid:54bd1bd7-1110-462b-847e-7f49c1043b32</Identifier>
<Instance>urn:uuid:0462b7d7-717e-4ce2-b942-b0d6a968355b</Instance>
<Cookie xmlns="http://schemas.microsoft.com/ws/2006/05/security">AQAAANCMnd blah blah 1048 bytes total
</Cookie>
</SecurityContextToken>

并且,在另一个盒子上使用相同的证书(以及作为仅用于测试的文件读入的令牌),我有:

public static void Attempt2(FileStream fileIn, X509Certificate2 certificate, out SecurityToken theToken)
    {
        List<CookieTransform> sessionTransforms = new List<CookieTransform>(new CookieTransform[] 
        { 
            new DeflateCookieTransform(),
            new RsaSignatureCookieTransform(certificate), 
            new RsaEncryptionCookieTransform(certificate) 
        });

        SessionSecurityTokenHandler sessionHandler = new SessionSecurityTokenHandler(sessionTransforms.AsReadOnly());

        // setup
        SecurityTokenResolver resolver;
        {
            var token = new X509SecurityToken(certificate);

            var tokens = new List<SecurityToken>() { token };

            resolver = SecurityTokenResolver.CreateDefaultSecurityTokenResolver(tokens.AsReadOnly(), false);
        }

        sessionHandler.Configuration = new SecurityTokenHandlerConfiguration();
        sessionHandler.Configuration.IssuerTokenResolver = resolver;

        using (var reader = XmlReader.Create(fileIn))
        {
            theToken = sessionHandler.ReadToken(reader);
        }

    }

然后ReadToken抛出

的FormatException
ID1006: The format of the data is incorrect. The encryption key length is negative: '-724221793'. The cookie may have been truncated.

此时,我无法判断我的整体方法是否有缺陷,或者我是否只是错过了解决所有这一切的众所周知的“一线”。

哦,我正在使用VS2010 SP1作为网站(.NET 4.0),我在解码端尝试了VS2010SP1 .NET 4.0和VS2012 .NET 4.5。

谢谢!

2 个答案:

答案 0 :(得分:0)

后端服务的应用池帐户是否具有对证书的读取权限?如果没有为后端服务提供您的应用程序池帐户,则可以读取对证书的访问权限。由于这个原因,我过去遇到了加密/解密问题。

答案 1 :(得分:0)

这可能会有所帮助,这会将您的FedAuth cookie转换为可读的XML字符串,如:

<?xml version="1.0" encoding="utf-8"?>
<SecurityContextToken p1:Id="_548a372e-1111-4df8-b610-1f9f618a5687-953155F0C35B4862A5BCE4D5D0C5ADF0" xmlns:p1="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns="http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512">
    <Identifier>urn:uuid:c9f9b733-1111-4b01-8af3-23c8af3e19a6</Identifier>
    <Instance>urn:uuid:ee955207-1111-4498-afa3-4b184e97d0be</Instance>
    <Cookie xmlns="http://schemas.microsoft.com/ws/2006/05/security">long_string==</Cookie>
</SecurityContextToken>

代码:

private string FedAuthToXmlString(string fedAuthCombinedString)
{
    // fedAuthCombinedString is from FedAuth + FedAuth1 cookies: just combine the strings

    byte[] authBytes = Convert.FromBase64String(fedAuthCombinedString);
    string decodedString = Encoding.UTF8.GetString(authBytes);

    var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
    store.Open(OpenFlags.ReadOnly);
    var thumbprint = "CERT_THUMBPRINT";  // from config

    var cert = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false)[0];

    var sessionTransforms = new List<System.IdentityModel.CookieTransform>(new System.IdentityModel.CookieTransform[]
    {
        new System.IdentityModel.DeflateCookieTransform(),
        new System.IdentityModel.RsaSignatureCookieTransform(cert),
        new System.IdentityModel.RsaEncryptionCookieTransform(cert)
    });

    SessionSecurityTokenHandler sessionHandler = new SessionSecurityTokenHandler(sessionTransforms.AsReadOnly());

    SecurityTokenResolver resolver;
    {
        var token = new X509SecurityToken(cert);
        var tokens = new List<SecurityToken>() { token };
        resolver = SecurityTokenResolver.CreateDefaultSecurityTokenResolver(tokens.AsReadOnly(), false);
    }

    sessionHandler.Configuration = new SecurityTokenHandlerConfiguration();
    sessionHandler.Configuration.IssuerTokenResolver = resolver;

    var i = 0; // clear out invalid leading xml
    while ((int)decodedString[i] != 60 && i < decodedString.Length - 1) i++; // while the first character is not <

    store.Close();

    return decodedString.Substring(i);
}