Few people have asked me for the source code of ExtractSAMLAssertion helper method/class,
which I have used in my article and blog posts. So here you go...
Please note this is just raw test code and doesn’t
have any error checking and other related goodies.
class Program
{
static void Main(string[]
args)
{
var
binding = new WSHttpBinding(SecurityMode.Message);
binding.Security.Message.ClientCredentialType = MessageCredentialType.None;
binding.Security.Message.EstablishSecurityContext = false;
var fac
= new WSTrustChannelFactory(binding,
"http://localhost:9000/STS");
fac.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
fac.Open();
var rst
= new RequestSecurityToken
{
AppliesTo = new
EndpointAddress("http://localhost"),
RequestType = WSTrustFeb2005Constants.RequestTypes.Issue
};
var token = fac.CreateChannel().Issue(rst) as
GenericXmlSecurityToken;
var
rpCert = new X509Certificate2("localhost.pfx", "a");
var xml
= ExtractSAMLAssertion(token,
rpCert);
}
private static string
ExtractSAMLAssertion(GenericXmlSecurityToken
token, X509Certificate2 rpCert)
{
string
txtAssertion = string.Empty;
var
handlerCol = SecurityTokenHandlerCollection.CreateDefaultSecurityTokenHandlerCollection();
var han
= handlerCol.OfType<EncryptedSecurityTokenHandler>().FirstOrDefault();
if (han
!= null)
{
han.Configuration.ServiceTokenResolver = new EncryptedKeyResolver(rpCert);
var
sr = new StringReader(token.TokenXml.OuterXml);
var
rdr2 = XmlReader.Create(sr);
var
rtok = han.ReadToken(rdr2) as SamlSecurityToken;
var
stat = rtok.Assertion.Statements[0];
var
ms = new MemoryStream();
var
memWriter = XmlDictionaryWriter.CreateTextWriter(ms);
stat.WriteXml(memWriter, new SamlSerializer(),
new WSSecurityTokenSerializer());
memWriter.Flush();
ms.Seek(0, SeekOrigin.Begin);
txtAssertion = new StreamReader(ms).ReadToEnd();
}
return
txtAssertion;
}
}
class EncryptedKeyResolver : SecurityTokenResolver
{
// Relying party
certificate - must hold private key.
X509Certificate2
rpCert;
public
EncryptedKeyResolver(X509Certificate2
rpCert)
{
this.rpCert
= rpCert;
}
protected override bool
TryResolveSecurityKeyCore(SecurityKeyIdentifierClause
keyIdentifierClause, out SecurityKey key)
{
key = null;
try
{
var
ekec = keyIdentifierClause as EncryptedKeyIdentifierClause;
if
(ekec != null)
{
switch
(ekec.EncryptionMethod)
{
case
"http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p":
{
var encKey =
ekec.GetEncryptedKey();
var rsa = rpCert.PrivateKey as RSACryptoServiceProvider;
var decKey = rsa.Decrypt(encKey, true);
key = new
InMemorySymmetricSecurityKey(decKey);
return true;
}
}
var
data = ekec.GetEncryptedKey();
var
id = ekec.EncryptingKeyIdentifier;
}
}
catch (Exception eexx)
{
Console.WriteLine(eexx);
throw
eexx;
}
return false;
}
protected override bool
TryResolveTokenCore(SecurityKeyIdentifierClause
keyIdentifierClause, out SecurityToken token)
{
throw new NotImplementedException();
}
protected override bool
TryResolveTokenCore(SecurityKeyIdentifier
keyIdentifier, out SecurityToken
token)
{
throw new NotImplementedException();
}
}