diff --git a/src/SAML2.Core/Config/IdentityProvider.cs b/src/SAML2.Core/Config/IdentityProvider.cs
index f1b7e05..477bbe6 100644
--- a/src/SAML2.Core/Config/IdentityProvider.cs
+++ b/src/SAML2.Core/Config/IdentityProvider.cs
@@ -73,7 +73,6 @@ public class IdentityProvider
/// The response encoding.
public string ResponseEncoding { get; set; }
-
///
/// Gets or sets the artifact resolution.
///
diff --git a/src/SAML2.Core/Config/Saml2Configuration.cs b/src/SAML2.Core/Config/Saml2Configuration.cs
index 36b359e..35d362d 100644
--- a/src/SAML2.Core/Config/Saml2Configuration.cs
+++ b/src/SAML2.Core/Config/Saml2Configuration.cs
@@ -53,6 +53,15 @@ public class Saml2Configuration
/// The service provider.
public ServiceProvider ServiceProvider { get; set; }
+ ///
+ /// Gets or sets a value weather the response SAML message from IdP should be decompressed after it's BAse64 endoded.
+ /// Compression is used by some IdP providers for example PingFederate.
+ /// This perform these decode steps: https://www.samltool.com/decode.php (see Base64 Decode + Inflate page)
+ /// Default: false
+ ///
+ /// The response encoding.
+ public bool InflateResponseMessage { get; set; }
+
public Saml2Configuration()
{
IdentityProviders = new IdentityProviders();
diff --git a/src/SAML2.Core/Protocol/Utility.cs b/src/SAML2.Core/Protocol/Utility.cs
index f863c46..ff1b7ac 100644
--- a/src/SAML2.Core/Protocol/Utility.cs
+++ b/src/SAML2.Core/Protocol/Utility.cs
@@ -9,6 +9,7 @@
using System;
using System.Collections.Generic;
using System.IO;
+using System.IO.Compression;
using System.Linq;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
@@ -153,14 +154,34 @@ public static void PreHandleAssertion(XmlElement elem, IdentityProvider endpoint
///
/// This is base64 encoded SAML Response (usually SAMLResponse on query string)
/// The encoding.
+ /// Wheater the response message should be inflated (decompressed).
/// The decoded SAML response XML.
- public static XmlDocument GetDecodedSamlResponse(string samlResponse, Encoding encoding)
+ public static XmlDocument GetDecodedSamlResponse(string samlResponse, Encoding encoding, bool infateResponse)
{
logger.Debug(TraceMessages.SamlResponseDecoding);
+ var samlResponseBytes = Convert.FromBase64String(samlResponse);
+ if (infateResponse)
+ {
+ logger.Debug(TraceMessages.SamlResponseDecodingDeflating);
+
+ // The response message is compressed using the Deflate algorith. Need to decompress it first.
+ using (var decompressedStream = new MemoryStream())
+ {
+ using (var compressedStream = new MemoryStream(samlResponseBytes))
+ using (var decompressor = new DeflateStream(compressedStream, CompressionMode.Decompress))
+ {
+ decompressor.CopyTo(decompressedStream);
+ }
+ samlResponseBytes = decompressedStream.ToArray();
+ }
+
+ logger.Debug(TraceMessages.SamlResponseDecodingDeflated);
+ }
+
+ samlResponse = encoding.GetString(samlResponseBytes);
var doc = new XmlDocument { PreserveWhitespace = true };
- samlResponse = encoding.GetString(Convert.FromBase64String(samlResponse));
doc.LoadXml(samlResponse);
logger.DebugFormat(TraceMessages.SamlResponseDecoded, samlResponse);
@@ -381,7 +402,7 @@ public static void HandleSoap(HttpArtifactBindingBuilder builder, Stream inputSt
public static Saml20Assertion HandleResponse(Saml2Configuration config, string samlResponse, IDictionary session, Func getFromCache, Action setInCache)
{
var defaultEncoding = Encoding.UTF8;
- var doc = Utility.GetDecodedSamlResponse(samlResponse, defaultEncoding);
+ var doc = Utility.GetDecodedSamlResponse(samlResponse, defaultEncoding, config.InflateResponseMessage);
logger.DebugFormat(TraceMessages.SamlResponseReceived, doc.OuterXml);
// Determine whether the assertion should be decrypted before being validated.
@@ -419,7 +440,7 @@ public static Saml20Assertion HandleResponse(Saml2Configuration config, string s
}
if (encodingOverride.CodePage != defaultEncoding.CodePage) {
- var doc1 = GetDecodedSamlResponse(samlResponse, encodingOverride);
+ var doc1 = GetDecodedSamlResponse(samlResponse, encodingOverride, config.InflateResponseMessage);
assertion = GetAssertion(doc1.DocumentElement, out isEncrypted);
}
}
diff --git a/src/SAML2.Core/Resources.Designer.cs b/src/SAML2.Core/Resources.Designer.cs
index 0ad53b4..19ec3d2 100644
--- a/src/SAML2.Core/Resources.Designer.cs
+++ b/src/SAML2.Core/Resources.Designer.cs
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
-// Runtime Version:4.0.30319.0
+// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
diff --git a/src/SAML2.Core/TraceMessages.resx b/src/SAML2.Core/TraceMessages.resx
index 1f40883..bb1794b 100644
--- a/src/SAML2.Core/TraceMessages.resx
+++ b/src/SAML2.Core/TraceMessages.resx
@@ -112,10 +112,10 @@
2.0
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Artifact created: {0}
@@ -273,4 +273,10 @@
SignOn handler called
+
+ Deflating the response SAML message
+
+
+ The response SAML message was deflated
+
\ No newline at end of file
diff --git a/src/SAML2.sln b/src/SAML2.sln
index 72ae66d..a71bf44 100644
--- a/src/SAML2.sln
+++ b/src/SAML2.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 14
-VisualStudioVersion = 14.0.22310.1
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SAML2.Core", "SAML2.Core\SAML2.Core.csproj", "{75E5BAD2-A20C-43CC-B5C8-38004CEDBDFD}"
EndProject