Note: Though, this might look non SharePoint, actually, this is used inside SharePoint code and also, I am using a SharePoint certificate. Hence, I have used this category for this forum.
I am able to generate the Security Token only from Claims, based on the below link.
http://devproconnections.com/development/generating-saml-tokens-wif-part-2
Following is the code.
SecurityTokenDescriptor descriptor = new SecurityTokenDescriptor();
string digestAlgorithm = "http://www.w3.org/2001/04/xmlenc#sha256";
string signatureAlgorithm = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";
X509Certificate2 signingCert = GetSTSCertificate(issuer);
System.Security.Cryptography.RSACryptoServiceProvider rsa = signingCert.PrivateKey as System.Security.Cryptography.RSACryptoServiceProvider;
RsaSecurityKey rsaKey = new RsaSecurityKey(rsa);
RsaKeyIdentifierClause rsaClause = new RsaKeyIdentifierClause(rsa);
SecurityKeyIdentifier signingSki = new SecurityKeyIdentifier(new SecurityKeyIdentifierClause[] { rsaClause });
SigningCredentials signingCredentials = new SigningCredentials(rsaKey, signatureAlgorithm, digestAlgorithm, signingSki);
descriptor.TokenType = "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0";
descriptor.TokenIssuerName = issuer;
descriptor.SigningCredentials = signingCredentials;
descriptor.Subject = new System.Security.Claims.ClaimsIdentity(claimColln);
descriptor.AppliesToAddress = url;
DateTime issueInstant = DateTime.UtcNow;
descriptor.Lifetime = new System.IdentityModel.Protocols.WSTrust.Lifetime(issueInstant, issueInstant + new TimeSpan(23, 0, 0));
SamlSecurityTokenHandler tokenHandler = new SamlSecurityTokenHandler();
SamlSecurityToken token = tokenHandler.CreateToken(descriptor) as SamlSecurityToken;
return token;In the above code, I got the DigestAlgorithm and SignatureAlgorithm from the Assertion XML of the token generated using SPSecurityContext.SecurityTokenForFormsAuthentication method call. I am using the SharePoint certificate issued by "SharePoint Security Token Service". I am able to generate the token and I need to read the Assertion of the token using the following code, which returns the assertion as a string.
var handlers = Microsoft.IdentityModel.Web.FederatedAuthentication.ServiceConfiguration.SecurityTokenHandlers;
var sb = new System.Text.StringBuilder(128);
handlers.WriteToken(new XmlTextWriter(new StringWriter(sb)), token);
return sb.ToString();Also, I am able to re-generate the token from the above string, using the following code.
System.IdentityModel.Tokens.SecurityToken token = null;
using (StringReader sr = new StringReader(samlAssertion))
{
using (XmlReader reader = XmlReader.Create(sr))
{
if (!reader.ReadToFollowing("saml:Assertion"))
{
throw new Exception("Assertion not found!");
}
SecurityTokenHandlerCollection collection = SecurityTokenHandlerCollection.CreateDefaultSecurityTokenHandlerCollection();
collection.ElementAt(2).Configuration.AudienceRestriction.AllowedAudienceUris.Add(siteUri);
token = collection.ReadToken(reader.ReadSubtree());
}
}
return token;After all this (all the above is working fine), when I try to re-validate the token to get the claims again, I am getting an exception. Following is the code used for re-validation.
var configuration = new SecurityTokenHandlerConfiguration();
configuration.AudienceRestriction.AudienceMode = AudienceUriMode.Never;
configuration.CertificateValidationMode = X509CertificateValidationMode.None;
configuration.RevocationMode = X509RevocationMode.NoCheck;
configuration.CertificateValidator = X509CertificateValidator.None;
configuration.AudienceRestriction.AllowedAudienceUris.Add(uri);
var registry = new ConfigurationBasedIssuerNameRegistry();
X509Certificate2 cert = GetSTSCertificate(issuer);
string certThumbprint = cert.Thumbprint;
registry.AddTrustedIssuer(certThumbprint, cert.Issuer);
configuration.IssuerNameRegistry = registry;
var handler = SecurityTokenHandlerCollection.CreateDefaultSecurityTokenHandlerCollection(configuration);
var identity = handler.ValidateToken(securityToken).First(); <-- This line throws exception.
return identity;ID4175: The issuer of the security token was not recognized by the IssuerNameRegistry. To accept security tokens from this issuer, configure the IssuerNameRegistry to return a valid name for this issuer.
If you look above, I am also adding the registry issuer and all that, in the code. But still, it is throwing error. Can anyone please help?
Ven