¿Cómo preparo correctamente una solicitud SAML de 'Enlace de redireccionamiento HTTP' usando C #?
Necesito crear una transacción de autenticación SAML 2.0 iniciada por SP utilizando el método de enlace de redireccionamiento HTTP. Resulta que esto es bastante fácil. Solo obtenga el URI de IdP y concatene un solo parámetro de cadena de consultaSAMLRequest
. El parámetro es un bloque codificado de xml que describe la solicitud SAML. Hasta ahora tan bueno.
El problema viene al convertir el SAML en el parámetro de cadena de consulta. Creo que este proceso de preparación debe ser:
Construye una cadena SAMLComprimir esta cadenaBase64 codifica la cadenaUrlcifre la cadena.La solicitud SAML
<samlp:AuthnRequest
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
ID="{0}"
Version="2.0"
AssertionConsumerServiceIndex="0"
AttributeConsumingServiceIndex="0">
<saml:Issuer>URN:xx-xx-xx</saml:Issuer>
<samlp:NameIDPolicy
AllowCreate="true"
Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"/>
</samlp:AuthnRequest>
El código
private string GetSAMLHttpRedirectUri(string idpUri)
{
var saml = string.Format(SAMLRequest, Guid.NewGuid());
var bytes = Encoding.UTF8.GetBytes(saml);
using (var output = new MemoryStream())
{
using (var zip = new DeflaterOutputStream(output))
{
zip.Write(bytes, 0, bytes.Length);
}
var base64 = Convert.ToBase64String(output.ToArray());
var urlEncode = HttpUtility.UrlEncode(base64);
return string.Concat(idpUri, "?SAMLRequest=", urlEncode);
}
}
Sospecho que la compresión es de alguna manera la culpa. Estoy usando elDeflaterOutputStream
clase deSharpZipLib ¿Qué se supone que debe implementar un algoritmo de desinflado estándar de la industria, así que quizás hay algunas configuraciones aquí que tengo mal?
La salida codificada se puede probar usando esteDepurador SAML2.0 (Es una herramienta de conversión en línea útil). Cuando decodifico mi salida usando esta herramienta, sale como una tontería.
Por lo tanto, la pregunta es: ¿Sabe cómo convertir una cadena SAML en el parámetro de consulta SAMLRequest correctamente desinflado y codificado?
Gracias
EDITAR 1
La respuesta aceptada a continuación da la respuesta al problema. Aquí está el código final corregido por todos los comentarios y respuestas posteriores.
Codificar SAMLRequest - Código de trabajo
private string GenerateSAMLRequestParam()
{
var saml = string.Format(SAMLRequest, Guid.NewGuid());
var bytes = Encoding.UTF8.GetBytes(saml);
using (var output = new MemoryStream())
{
using (var zip = new DeflateStream(output, CompressionMode.Compress))
{
zip.Write(bytes, 0, bytes.Length);
}
var base64 = Convert.ToBase64String(output.ToArray());
return HttpUtility.UrlEncode(base64);
}
}
losSAMLRequest
La variable contiene la SAML que se muestra en la parte superior de esta pregunta.
Decodificar SAMLResponse - Código de trabajo
private string DecodeSAMLResponse(string response)
{
var utf8 = Encoding.UTF8;
var bytes = utf8.GetBytes(response);
using (var output = new MemoryStream())
{
using (new DeflateStream(output, CompressionMode.Decompress))
{
output.Write(bytes, 0, bytes.Length);
}
var base64 = utf8.GetString(output.ToArray());
return utf8.GetString(Convert.FromBase64String(base64));
}
}