private XmlElement GetKeyIdentifierClause(X509SecurityToken certToken) { using (XmlDocumentWriterHelper documentWriterHelper = new XmlDocumentWriterHelper()) { // The key is located in the same XML document, so referencing that // with a local key identifier. var keyIdentifierClause = certToken.CreateKeyIdentifierClause <LocalIdKeyIdentifierClause>(); Debug.Assert(keyIdentifierClause != null); _tokenSerializer.WriteKeyIdentifierClause( documentWriterHelper.CreateDocumentWriter(), keyIdentifierClause); XmlDocument xmlDocument = documentWriterHelper.ReadDocument(); return(xmlDocument.DocumentElement); } }
private Saml2Assertion CreateSamlAssertionWithSymmetricKey(BinarySecretSecurityToken proofToken) { X509SecurityToken x509SecurityToken = new X509SecurityToken(base.ClientCredentials.ClientCertificate.Certificate); X509SecurityToken x509SecurityToken2 = new X509SecurityToken(base.ClientCredentials.ServiceCertificate.DefaultCertificate); SecurityKey signatureKey = x509SecurityToken.SecurityKeys[0]; SecurityKeyIdentifierClause securityKeyIdentifierClause = x509SecurityToken.CreateKeyIdentifierClause <X509ThumbprintKeyIdentifierClause>(); SecurityKeyIdentifier signatureKeyIdentifier = new SecurityKeyIdentifier(new SecurityKeyIdentifierClause[] { securityKeyIdentifierClause }); SecurityKey securityKey = x509SecurityToken2.SecurityKeys[0]; SecurityKeyIdentifierClause securityKeyIdentifierClause2 = x509SecurityToken2.CreateKeyIdentifierClause <X509ThumbprintKeyIdentifierClause>(); SecurityKeyIdentifier encryptingKeyIdentifier = new SecurityKeyIdentifier(new SecurityKeyIdentifierClause[] { securityKeyIdentifierClause2 }); byte[] keyBytes = proofToken.GetKeyBytes(); byte[] encryptedKey = securityKey.EncryptKey(base.SecurityAlgorithmSuite.DefaultAsymmetricKeyWrapAlgorithm, keyBytes); SecurityKeyIdentifier proofKeyIdentifier = new SecurityKeyIdentifier(new SecurityKeyIdentifierClause[] { new EncryptedKeyIdentifierClause(encryptedKey, base.SecurityAlgorithmSuite.DefaultAsymmetricKeyWrapAlgorithm, encryptingKeyIdentifier) }); return(this.CreateSamlAssertion(signatureKey, signatureKeyIdentifier, proofKeyIdentifier)); }
/// <summary> /// Creates a SAML assertion based on a symmetric proof key /// </summary> /// <param name="claims">A ClaimSet containing the claims to be placed into the SAML assertion</param> /// <param name="signatureToken">An X509SecurityToken that will be used to sign the SAML assertion</param> /// <param name="encryptionToken">An X509SecurityToken that will be used to encrypt the proof key</param> /// <param name="proofToken">A BinarySecretSecurityToken containing the proof key</param> /// <param name="algoSuite">The algorithm suite to use when performing cryptographic operations</param> /// <returns>A SAML assertion containing the passed in claims and proof key, signed by the provided signature token</returns> public static SamlAssertion CreateSymmetricKeyBasedAssertion(ClaimSet claims, X509SecurityToken signatureToken, X509SecurityToken encryptionToken, BinarySecretSecurityToken proofToken, SecurityAlgorithmSuite algoSuite) { // Check various input parameters if (claims == null) { throw new ArgumentNullException("claims"); } if (claims.Count == 0) { throw new ArgumentException("Provided ClaimSet must contain at least one claim"); } if (proofToken == null) { throw new ArgumentNullException("proofToken"); } if (signatureToken == null) { throw new ArgumentNullException("signatureToken"); } if (encryptionToken == null) { throw new ArgumentNullException("encryptionToken"); } if (proofToken == null) { throw new ArgumentNullException("proofToken"); } if (algoSuite == null) { throw new ArgumentNullException("algoSuite"); } // Get signing key and a key identifier for same SecurityKey signatureKey = signatureToken.SecurityKeys[0]; SecurityKeyIdentifierClause signatureSkic = signatureToken.CreateKeyIdentifierClause <X509ThumbprintKeyIdentifierClause>(); SecurityKeyIdentifier signatureKeyIdentifier = new SecurityKeyIdentifier(signatureSkic); // Get encryption key and a key identifier for same SecurityKey encryptionKey = encryptionToken.SecurityKeys[0]; SecurityKeyIdentifierClause encryptionSkic = encryptionToken.CreateKeyIdentifierClause <X509ThumbprintKeyIdentifierClause>(); SecurityKeyIdentifier encryptionKeyIdentifier = new SecurityKeyIdentifier(encryptionSkic); // Encrypt the proof key and create a key identifier for same byte[] proofKey = proofToken.GetKeyBytes(); byte[] encryptedSecret = new byte[proofKey.Length]; encryptedSecret = encryptionKey.EncryptKey(algoSuite.DefaultAsymmetricKeyWrapAlgorithm, proofKey); SecurityKeyIdentifier proofKeyIdentifier = new SecurityKeyIdentifier(new EncryptedKeyIdentifierClause(encryptedSecret, algoSuite.DefaultAsymmetricKeyWrapAlgorithm, encryptionKeyIdentifier)); // Create the assertion return(CreateAssertion(claims, signatureKey, signatureKeyIdentifier, proofKeyIdentifier, algoSuite)); }
private RequestSecurityTokenResponseWSTrust13 Issue(RequestSecurityTokenWSTrust13 rst) { // If rst is null, an exception is thrown. if (rst == null) { throw new ArgumentNullException("rst"); } // Create an RSTR object. RequestSecurityTokenResponseWSTrust13 rstr = new RequestSecurityTokenResponseWSTrust13(); string tokenType = rst.TokenType; Console.WriteLine("Issue: Request for token type {0}", tokenType); if (tokenType != null && tokenType != "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1") { throw new NotSupportedException("Unsupported token type " + tokenType); } SecurityKey signingKey = issuerToken.SecurityKeys[0]; SecurityKeyIdentifier signingKeyIdentifier = new SecurityKeyIdentifier(issuerToken.CreateKeyIdentifierClause <X509ThumbprintKeyIdentifierClause>()); SecurityKeyIdentifier proofKeyIdentifier = null; if (rst.IsProofKeyAsymmetric()) { throw new NotSupportedException("Public key issuance is not supported"); } // Symmetric proof key. Console.WriteLine("Constructing Symmetric Proof Key"); // Construct the session key. This is the symmetric key that the client and the service share. // It appears twice in the response message; once for the service and // once for the client. For the service, it is typically embedded in the issued token, // for the client, it is returned in a wst:RequestedProofToken element. byte[] sessionKey = GetSessionKey(rst, rstr); // Get a token to use when encrypting key material for the service. SecurityToken encryptingToken = DetermineEncryptingToken(rst); // Encrypt the session key for the service. GetEncryptedKey(encryptingToken, sessionKey, out proofKeyIdentifier); // Issued tokens are valid for 12 hours by default. DateTime effectiveTime = DateTime.Now; DateTime expirationTime = DateTime.Now + new TimeSpan(12, 0, 0); SecurityToken samlToken = CreateSAMLToken(effectiveTime, expirationTime, signingKey, signingKeyIdentifier, proofKeyIdentifier); rstr.RequestedSecurityToken = samlToken; rstr.Context = rst.Context; rstr.TokenType = tokenType; SecurityKeyIdentifierClause samlReference = samlToken.CreateKeyIdentifierClause <SamlAssertionKeyIdentifierClause>(); rstr.RequestedAttachedReference = samlReference; rstr.RequestedUnattachedReference = samlReference; return(rstr); }
/// <summary> /// Creates a SAML token for the specified email address and security token. /// </summary> private SamlSecurityToken CreateSAMLToken( string emailAddress, X509SecurityToken issuerToken) { // Create list of confirmation strings List <string> confirmations = new List <string>(); // Add holder-of-key string to list of confirmation strings confirmations.Add("urn:oasis:names:tc:SAML:1.0:cm:bearer"); // Create SAML subject statement based on issuer member variable, confirmation string collection // local variable and proof key identifier parameter SamlSubject subject = new SamlSubject("urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", null, emailAddress); // Create a list of SAML attributes List <SamlAttribute> attributes = new List <SamlAttribute>(); Claim claim = Claim.CreateNameClaim(emailAddress); attributes.Add(new SamlAttribute(claim)); // Create list of SAML statements List <SamlStatement> statements = new List <SamlStatement>(); // Add a SAML attribute statement to the list of statements. Attribute statement is based on // subject statement and SAML attributes resulting from claims statements.Add(new SamlAttributeStatement(subject, attributes)); // Create a valid from/until condition DateTime validFrom = DateTime.UtcNow; DateTime validTo = DateTime.UtcNow.AddHours(12); SamlConditions conditions = new SamlConditions(validFrom, validTo); // Create the SAML assertion SamlAssertion assertion = new SamlAssertion( "_" + Guid.NewGuid().ToString(), issuerToken.Certificate.Subject, validFrom, conditions, null, statements); SecurityKey signingKey = new System.IdentityModel.Tokens.RsaSecurityKey((RSA)issuerToken.Certificate.PrivateKey); // Set the signing credentials for the SAML assertion assertion.SigningCredentials = new SigningCredentials( signingKey, System.IdentityModel.Tokens.SecurityAlgorithms.RsaSha1Signature, System.IdentityModel.Tokens.SecurityAlgorithms.Sha1Digest, new SecurityKeyIdentifier(issuerToken.CreateKeyIdentifierClause <X509ThumbprintKeyIdentifierClause>())); return(new SamlSecurityToken(assertion)); }
public static SamlAssertion CreateSymmetricKeyBasedAssertion(ClaimSet claims, X509SecurityToken signatureToken, X509SecurityToken encryptionToken, BinarySecretSecurityToken proofToken, SecurityAlgorithmSuite algoSuite) { if (claims == null) { throw new ArgumentNullException("claims"); } if (claims.Count == 0) { throw new ArgumentException("Provided ClaimSet must contain at least one claim"); } if (proofToken == null) { throw new ArgumentNullException("proofToken"); } if (signatureToken == null) { throw new ArgumentNullException("signatureToken"); } if (encryptionToken == null) { throw new ArgumentNullException("encryptionToken"); } if (proofToken == null) { throw new ArgumentNullException("proofToken"); } if (algoSuite == null) { throw new ArgumentNullException("algoSuite"); } SecurityKey signatureKey = signatureToken.SecurityKeys[0]; SecurityKeyIdentifierClause securityKeyIdentifierClause = signatureToken.CreateKeyIdentifierClause <X509ThumbprintKeyIdentifierClause>(); SecurityKeyIdentifier signatureKeyIdentifier = new SecurityKeyIdentifier(new SecurityKeyIdentifierClause[] { securityKeyIdentifierClause }); SecurityKey securityKey = encryptionToken.SecurityKeys[0]; SecurityKeyIdentifierClause securityKeyIdentifierClause2 = encryptionToken.CreateKeyIdentifierClause <X509ThumbprintKeyIdentifierClause>(); SecurityKeyIdentifier encryptingKeyIdentifier = new SecurityKeyIdentifier(new SecurityKeyIdentifierClause[] { securityKeyIdentifierClause2 }); byte[] keyBytes = proofToken.GetKeyBytes(); byte[] encryptedKey = new byte[keyBytes.Length]; encryptedKey = securityKey.EncryptKey(algoSuite.DefaultAsymmetricKeyWrapAlgorithm, keyBytes); SecurityKeyIdentifier proofKeyIdentifier = new SecurityKeyIdentifier(new SecurityKeyIdentifierClause[] { new EncryptedKeyIdentifierClause(encryptedKey, algoSuite.DefaultAsymmetricKeyWrapAlgorithm, encryptingKeyIdentifier) }); return(SamlUtilities.CreateAssertion(claims, signatureKey, signatureKeyIdentifier, proofKeyIdentifier, algoSuite)); }
private Saml2Assertion CreateSamlAssertionWithAsymmetricKey(SecurityToken proofToken) { X509SecurityToken x509SecurityToken = new X509SecurityToken(base.ClientCredentials.ClientCertificate.Certificate); SecurityKey signatureKey = x509SecurityToken.SecurityKeys[0]; SecurityKeyIdentifierClause securityKeyIdentifierClause = x509SecurityToken.CreateKeyIdentifierClause <X509ThumbprintKeyIdentifierClause>(); SecurityKeyIdentifier signatureKeyIdentifier = new SecurityKeyIdentifier(new SecurityKeyIdentifierClause[] { securityKeyIdentifierClause }); SecurityKeyIdentifier proofKeyIdentifier = new SecurityKeyIdentifier(new SecurityKeyIdentifierClause[] { proofToken.CreateKeyIdentifierClause <RsaKeyIdentifierClause>() }); return(this.CreateSamlAssertion(signatureKey, signatureKeyIdentifier, proofKeyIdentifier)); }
/// <summary> /// Returns a SecurityTokenReference element which contains a reference /// by id to a client certificate that is located in the same XML document. /// </summary> private XmlElement GetKeyIdentifierClause(X509SecurityToken certToken) { var keyIdentifierClause = certToken.CreateKeyIdentifierClause <LocalIdKeyIdentifierClause>(); Debug.Assert(keyIdentifierClause != null); using (XmlDocumentWriterHelper documentWriterHelper = new XmlDocumentWriterHelper()) { _tokenSerializer.WriteKeyIdentifierClause( documentWriterHelper.CreateDocumentWriter(), keyIdentifierClause); XmlDocument xmlDocument = documentWriterHelper.ReadDocument(); return(xmlDocument.DocumentElement); } }
public static ExtendedEntityDescriptor CreateMetadata(this ISPOptions spOptions, AuthServicesUrls urls) { var ed = new ExtendedEntityDescriptor { EntityId = spOptions.EntityId, Organization = spOptions.Organization, CacheDuration = spOptions.MetadataCacheDuration }; foreach (var contact in spOptions.Contacts) { ed.Contacts.Add(contact); } var spsso = new ExtendedServiceProviderSingleSignOnDescriptor(); spsso.ProtocolsSupported.Add(new Uri("urn:oasis:names:tc:SAML:2.0:protocol")); spsso.AssertionConsumerServices.Add(0, new IndexedProtocolEndpoint() { Index = 0, IsDefault = true, Binding = Saml2Binding.HttpPostUri, Location = urls.AssertionConsumerServiceUrl }); spsso.AssertionConsumerServices.Add(1, new IndexedProtocolEndpoint() { Index = 1, IsDefault = false, Binding = Saml2Binding.HttpArtifactUri, Location = urls.AssertionConsumerServiceUrl }); foreach (var attributeService in spOptions.AttributeConsumingServices) { spsso.AttributeConsumingServices.Add(attributeService); } if (spOptions.ServiceCertificates != null) { var publishCertificates = spOptions.MetadataCertificates; foreach (var serviceCert in publishCertificates) { using (var securityToken = new X509SecurityToken(serviceCert.Certificate)) { spsso.Keys.Add( new KeyDescriptor { Use = (KeyType)(byte)serviceCert.Use, KeyInfo = new SecurityKeyIdentifier(securityToken.CreateKeyIdentifierClause <X509RawDataKeyIdentifierClause>()) } ); } } } if (spOptions.DiscoveryServiceUrl != null && !string.IsNullOrEmpty(spOptions.DiscoveryServiceUrl.OriginalString)) { spsso.Extensions.DiscoveryResponse = new IndexedProtocolEndpoint { Binding = Saml2Binding.DiscoveryResponseUri, Index = 0, IsDefault = true, Location = urls.SignInUrl }; } ed.RoleDescriptors.Add(spsso); return(ed); }
/// <summary> /// Creates a SAML token for the specified email address. /// </summary> public static async System.Threading.Tasks.Task <UserIdentity> CreateSAMLTokenAsync(string emailAddress) { // Normally this would be done by a server that is capable of verifying that // the user is a legimate holder of email address. Using a local certficate to // signed the SAML token is a short cut that would never be done in a real system. CertificateIdentifier userid = new CertificateIdentifier(); userid.StoreType = CertificateStoreType.X509Store; userid.StorePath = "LocalMachine\\My"; userid.SubjectName = "UA Sample Client"; X509Certificate2 certificate = await userid.Find(); X509SecurityToken signingToken = new X509SecurityToken(certificate); // Create list of confirmation strings List <string> confirmations = new List <string>(); // Add holder-of-key string to list of confirmation strings confirmations.Add("urn:oasis:names:tc:SAML:1.0:cm:bearer"); // Create SAML subject statement based on issuer member variable, confirmation string collection // local variable and proof key identifier parameter SamlSubject subject = new SamlSubject("urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", null, emailAddress); // Create a list of SAML attributes List <SamlAttribute> attributes = new List <SamlAttribute>(); Claim claim = Claim.CreateNameClaim(emailAddress); attributes.Add(new SamlAttribute(claim)); // Create list of SAML statements List <SamlStatement> statements = new List <SamlStatement>(); // Add a SAML attribute statement to the list of statements. Attribute statement is based on // subject statement and SAML attributes resulting from claims statements.Add(new SamlAttributeStatement(subject, attributes)); // Create a valid from/until condition DateTime validFrom = DateTime.UtcNow; DateTime validTo = DateTime.UtcNow.AddHours(12); SamlConditions conditions = new SamlConditions(validFrom, validTo); // Create the SAML assertion SamlAssertion assertion = new SamlAssertion( "_" + Guid.NewGuid().ToString(), signingToken.Certificate.Subject, validFrom, conditions, null, statements); SecurityKey signingKey = new System.IdentityModel.Tokens.RsaSecurityKey((RSA)signingToken.Certificate.PrivateKey); // Set the signing credentials for the SAML assertion assertion.SigningCredentials = new SigningCredentials( signingKey, System.IdentityModel.Tokens.SecurityAlgorithms.RsaSha1Signature, System.IdentityModel.Tokens.SecurityAlgorithms.Sha1Digest, new SecurityKeyIdentifier(signingToken.CreateKeyIdentifierClause <X509ThumbprintKeyIdentifierClause>())); // TODO // return new UserIdentity(new SamlSecurityToken(assertion)); throw new NotImplementedException(); }
/// <summary> /// Build the contents of the SAML token /// </summary> /// <param name="writer"><b>XmlDictionaryWriter</b> to write the contents of this token to</param> protected override void OnWriteBodyContents(XmlDictionaryWriter writer) { // Subject SamlSubject subject = new SamlSubject(); if (this.useKey != null) { // Add the key and the Holder-Of-Key confirmation method subject.KeyIdentifier = this.useKey; subject.ConfirmationMethods.Add(SamlConstants.HolderOfKey); } else { // This is a bearer token subject.ConfirmationMethods.Add(SamlConstants.SenderVouches); } // Attributes, statements, conditions, and assertions List <SamlStatement> statements = new List <SamlStatement>(); List <SamlAttribute> attributes = GetTokenAttributes(); statements.Add(new SamlAuthenticationStatement(subject, Constants.Saml.AuthenticationMethods.Unspecified, DateTime.Now, null, null, null)); statements.Add(new SamlAttributeStatement(subject, attributes)); SamlConditions conditions = new SamlConditions(DateTime.Now, (DateTime.Now + TimeSpan.FromHours(8.0))); SamlAssertion assertion = new SamlAssertion("uuid-" + Guid.NewGuid(), Program.Issuer, DateTime.Now, conditions, null, statements); // Build the signing token SecurityToken signingToken = new X509SecurityToken(Program.SigningCertificate); SecurityKeyIdentifier keyIdentifier = new SecurityKeyIdentifier(signingToken.CreateKeyIdentifierClause <X509RawDataKeyIdentifierClause>()); SigningCredentials signingCredentials = new SigningCredentials(signingToken.SecurityKeys[0], SecurityAlgorithms.RsaSha1Signature, SecurityAlgorithms.Sha1Digest, keyIdentifier); assertion.SigningCredentials = signingCredentials; // Build the SAML token SamlSecurityToken token = new SamlSecurityToken(assertion); SecurityKeyIdentifierClause attachedReference = token.CreateKeyIdentifierClause <SamlAssertionKeyIdentifierClause>(); SecurityKeyIdentifierClause unattachedReference = token.CreateKeyIdentifierClause <SamlAssertionKeyIdentifierClause>(); // // Write the XML // //writer = XmlDictionaryWriter.CreateTextWriter(File.CreateText("output.xml").BaseStream); // RSTR writer.WriteStartElement(Constants.WSTrust.NamespaceUri.Prefix, Constants.WSTrust.Elements.RequestSecurityTokenResponse, Constants.WSTrust.NamespaceUri.Uri); if (context != null) { writer.WriteAttributeString(Constants.WSTrust.Attributes.Context, context); } // TokenType writer.WriteElementString(Constants.WSTrust.NamespaceUri.Prefix, Constants.WSTrust.Elements.TokenType, Constants.WSTrust.NamespaceUri.Uri, Constants.WSTrust.TokenTypes.Saml10Assertion); // RequestedSecurityToken (the SAML token) SecurityTokenSerializer tokenSerializer = new WSSecurityTokenSerializer(); writer.WriteStartElement(Constants.WSTrust.NamespaceUri.Prefix, Constants.WSTrust.Elements.RequestedSecurityToken, Constants.WSTrust.NamespaceUri.Uri); tokenSerializer.WriteToken(writer, token); writer.WriteEndElement(); // RequestedAttachedReference writer.WriteStartElement(Constants.WSTrust.NamespaceUri.Prefix, Constants.WSTrust.Elements.RequestedAttachedReference, Constants.WSTrust.NamespaceUri.Uri); tokenSerializer.WriteKeyIdentifierClause(writer, attachedReference); writer.WriteEndElement(); // RequestedUnattachedReference writer.WriteStartElement(Constants.WSTrust.NamespaceUri.Prefix, Constants.WSTrust.Elements.RequestedUnattachedReference, Constants.WSTrust.NamespaceUri.Uri); tokenSerializer.WriteKeyIdentifierClause(writer, unattachedReference); writer.WriteEndElement(); // RequestedDisplayToken (display token) string displayTokenNS = "http://schemas.xmlsoap.org/ws/2005/05/identity"; writer.WriteStartElement("wsid", "RequestedDisplayToken", displayTokenNS); writer.WriteStartElement("wsid", "DisplayToken", displayTokenNS); foreach (SamlAttribute attribute in attributes) { writer.WriteStartElement("wsid", "DisplayClaim", displayTokenNS); writer.WriteAttributeString("Uri", attribute.Namespace + "/" + attribute.Name); writer.WriteStartElement("wsid", "DisplayTag", displayTokenNS); writer.WriteValue(attribute.Name); writer.WriteEndElement(); writer.WriteStartElement("wsid", "Description", displayTokenNS); writer.WriteValue(attribute.Namespace + "/" + attribute.Name); writer.WriteEndElement(); foreach (string attributeValue in attribute.AttributeValues) { writer.WriteStartElement("wsid", "DisplayValue", displayTokenNS); writer.WriteValue(attributeValue); writer.WriteEndElement(); } writer.WriteEndElement(); } writer.WriteEndElement(); writer.WriteEndElement(); // RSTR End writer.WriteEndElement(); //writer.Close(); }