简体   繁体   English

如何在.Net 中解析 SAML 断言请求

[英]How to parse a SAML assertion request in .Net

I'm trying to implement a SAML SSO solution in.Net, but I'm having a problem parsing the assertion.我正在尝试在.Net 中实现 SAML SSO 解决方案,但在解析断言时遇到问题。

I have a sample assertion (looks like byte[] data as text) and corresponding .p7b file.我有一个示例断言(看起来像byte[]数据作为文本)和相应的.p7b文件。

I want to load the keys from the .p7b and decrypt the assertion to an XML document.我想从.p7b加载密钥并将断言解密为 XML 文档。

So far I think I'm reading the keys correctly:到目前为止,我认为我正在正确读取密钥:

// get the key data
byte[] certificateData = System.IO.File.ReadAllBytes("myKeys.p7b");

// decode the keys
var cms = new SignedCms(SubjectIdentifierType.IssuerAndSerialNumber);
cms.Decode(certificateData);

var samlCertificates = cms.Certificates;

Then I try to parse the assertion I get a problem:然后我尝试解析我遇到问题的断言:

// we have a keychain of X509Certificate2s, we need a collection of tokens
var certificatesAsTokens =
    from X509Certificate2 cert in samlCertificates
    select new X509SecurityToken(cert) as SecurityToken;

// get a token resolver
var tokens = new ReadOnlyCollection<SecurityToken>(
    certificatesAsTokens.ToList());
var resolver = SecurityTokenResolver.CreateDefaultSecurityTokenResolver(
    tokens, true);

// get the SAML data in an XML reader
var reader = XmlReader.Create(assertionPostStream);

// use the WS Security stuff to parse the reader
var securityToken = WSSecurityTokenSerializer.
    DefaultInstance.ReadToken(reader, resolver) as SamlSecurityToken;

That last statement throws an exception, stating that it can't parse the XML content.最后一条语句引发异常,指出它无法解析 XML 内容。

I think this means that I'm missing a step decrypting the assertion - getting the byte[] as text converted to a SAML format XML document.我认为这意味着我错过了解密断言的步骤 - 将byte[]作为文本转换为 SAML 格式 XML 文档。

Anyone know how to add this step?有人知道如何添加此步骤吗? Am I missing something else?我还缺少其他东西吗?

I've figured this out - I was missing part of the SAML specification. 我已经弄明白了 - 我错过了SAML规范的一部分。

The assertion is sent (rather weirdly, since it isn't encrypted) as base64 data, and it was being URL encoded twice as it was sent. 断言被发送(相当奇怪,因为它没有加密)作为base64数据,并且它被发送的URL编码两次。

So adding this step gives us a valid assertion: 所以添加这个步骤给了我们一个有效的断言:

// spec says "SAMLResponse=" 
string rawSamlData = Request["SAMLResponse"];

// the sample data sent us may be already encoded, 
// which results in double encoding
if (rawSamlData.Contains('%'))
{
    rawSamlData = HttpUtility.UrlDecode(rawSamlData);
}

// read the base64 encoded bytes
byte[] samlData = Convert.FromBase64String(rawSamlData);

// read back into a UTF string
string samlAssertion = Encoding.UTF8.GetString(samlData);

The authentication still isn't working , but I now have valid XML so it's a different problem. 身份验证仍然无法正常工作 ,但我现在拥有有效的XML,因此这是一个不同的问题。

This is my working source code:这是我的工作源代码:

            byte[] samlData = Convert.FromBase64String(samlresponse);

            var decompressedStream = SAMLUtility.Decompress(samlData);
            StreamReader reader = new StreamReader(decompressedStream);
            var decodedSaml = reader.ReadToEnd();

            var serializer = new XmlSerializer(typeof(Response));
            Response samlResponse;

            using (TextReader reader1 = new StringReader(decodedSaml))
            {
                samlResponse = (Response)serializer.Deserialize(reader1);
            }

            if (samlResponse.Status.StatusCode.Value.Contains("Success"))
                return samlResponse;
            else
                return null;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM