/// <summary>
        /// Creates a Saml2Assertion from a ClaimsIdentity.
        /// </summary>
        /// <returns>Saml2Assertion</returns>
        public static Saml2Assertion ToSaml2Assertion(this ClaimsIdentity identity, EntityId issuer)
        {
            if (identity == null)
            {
                throw new ArgumentNullException("identity");
            }

            if (issuer == null)
            {
                throw new ArgumentNullException("issuer");
            }

            var assertion = new Saml2Assertion(new Saml2NameIdentifier(issuer.Id));

            assertion.Subject = new Saml2Subject(new Saml2NameIdentifier(
                identity.Claims.Single(c => c.Type == ClaimTypes.NameIdentifier).Value));

            foreach (var claim in identity.Claims.Where(c => c.Type != ClaimTypes.NameIdentifier).GroupBy(c => c.Type))
            {
                assertion.Statements.Add(new Saml2AttributeStatement(new Saml2Attribute(claim.Key, claim.Select(c => c.Value))));
            };

            assertion.Conditions = new Saml2Conditions()
            {
                NotOnOrAfter = DateTime.UtcNow.AddMinutes(2)
            };

            return assertion;
        }
        /// <summary>
        /// Creates a Saml2Assertion from a ClaimsIdentity.
        /// </summary>
        /// <param name="identity">Claims to include in Assertion.</param>
        /// <param name="issuer">Issuer to include in assertion.</param>
        /// <param name="audience">Audience to set as audience restriction.</param>
        /// <returns>Saml2Assertion</returns>
        public static Saml2Assertion ToSaml2Assertion(
            this ClaimsIdentity identity,
            EntityId issuer,
            Uri audience)
        {
            if (identity == null)
            {
                throw new ArgumentNullException(nameof(identity));
            }

            if (issuer == null)
            {
                throw new ArgumentNullException(nameof(issuer));
            }

            var assertion = new Saml2Assertion(new Saml2NameIdentifier(issuer.Id))
            {
                Subject = new Saml2Subject(new Saml2NameIdentifier(
                    identity.Claims.Single(c => c.Type == ClaimTypes.NameIdentifier).Value)),
            };

            assertion.Statements.Add(
                new Saml2AuthenticationStatement(
                    new Saml2AuthenticationContext(
                        new Uri("urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified")))
                {
                    SessionIndex = identity.Claims.SingleOrDefault(
                        c => c.Type == AuthServicesClaimTypes.SessionIndex)?.Value
                });

            var attributeClaims = identity.Claims.Where(
                c => c.Type != ClaimTypes.NameIdentifier
                && c.Type != AuthServicesClaimTypes.SessionIndex).GroupBy(c => c.Type);

            if (attributeClaims.Any())
            {
                assertion.Statements.Add(
                    new Saml2AttributeStatement(
                        attributeClaims.Select(
                            ac => new Saml2Attribute(ac.Key, ac.Select(c => c.Value)))));
            }

            assertion.Conditions = new Saml2Conditions()
            {
                NotOnOrAfter = DateTime.UtcNow.AddMinutes(2)
            };

            if(audience != null)
            {
                assertion.Conditions.AudienceRestrictions.Add(
                    new Saml2AudienceRestriction(audience));
            }

            return assertion;
        }
 private void ValidateRecipient(Saml2Assertion assertion)
 {
     var actual = assertion.Subject.SubjectConfirmations[0].SubjectConfirmationData.Recipient;
     if (actual != allowedRecipient)
         throw new SecurityTokenException(string.Format("Message=Recipient not valid, Expected={0}, Actual={1}",
             allowedRecipient, actual));
 }
        /// <summary>
        /// Initializes a new instance of <see cref="Saml2Evidence"/> class from a <see cref="Saml2Assertion"/>.
        /// </summary>
        /// <param name="assertion"><see cref="Saml2Assertion"/> containing the evidence.</param>
        public Saml2Evidence(Saml2Assertion assertion)
        {
            if (null == assertion)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("assertion");
            }

            this.assertions.Add(assertion);
        }
        private void ValidateNotOnOrAfter(Saml2Assertion assertion)
        {
            DateTime now = DateTime.UtcNow;
            if (assertion.Subject.SubjectConfirmations[0].SubjectConfirmationData.NotOnOrAfter == null)
                throw new SecurityTokenExpiredException(string.Format("Message=NotOnOrAfter is missing"));

            var subjectNotOnOrAfter = assertion.Subject.SubjectConfirmations[0].SubjectConfirmationData.NotOnOrAfter + Configuration.MaxClockSkew.Negate();
            if (subjectNotOnOrAfter < now)
                throw new SecurityTokenExpiredException(string.Format("Message=NotOnOrAfter invalid on SubjectConfirmationData, NotOnOrAfter={0}, now={1}", subjectNotOnOrAfter, now));
        }
        public string ToXml(Saml2Assertion assertion)
        {
            var tokenHandlers = new Saml2SecurityTokenHandler();
            var stringBuilder = new StringBuilder();
            using (var xmlWriter = new XmlTextWriter(new StringWriter(stringBuilder)))
            {
                var token = new Saml2SecurityToken(assertion);
                tokenHandlers.WriteToken(xmlWriter, token);

                return stringBuilder.ToString();
            }
        }
        public static SecurityToken MakeBootstrapSecurityToken()
        {
            Saml2NameIdentifier identifier = new Saml2NameIdentifier("http://localhost/Echo");

            Saml2Assertion assertion = new Saml2Assertion(identifier);

            assertion.Issuer = new Saml2NameIdentifier("idp1.test.oio.dk");
            assertion.Subject = new Saml2Subject(new Saml2NameIdentifier("Casper", new Uri("urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified")));
            Saml2Attribute atribute = new Saml2Attribute("dk:gov:saml:attribute:AssuranceLevel", "2");
            atribute.NameFormat = new Uri("urn:oasis:names:tc:SAML:2.0:attrname-format:basic");

            assertion.Statements.Add(new Saml2AttributeStatement(atribute));
            return new Saml2SecurityToken(assertion);
        }
        public void Saml2AssertionExtensions_ToXElement_Subject()
        {
            var subjectName = "JohnDoe";
            var assertion = new Saml2Assertion(
                new Saml2NameIdentifier("http://idp.example.com"))
                {
                    Subject = new Saml2Subject(new Saml2NameIdentifier(subjectName))
                };

            var subject = assertion.ToXElement();

            subject.Element(Saml2Namespaces.Saml2 + "Subject").
                Element(Saml2Namespaces.Saml2 + "NameID").Value.Should().Be(subjectName);
        }
Esempio n. 9
0
        /// <summary>
        /// Initializes an instance of <see cref="Saml2SecurityToken"/> from a <see cref="Saml2Assertion"/>.
        /// </summary>
        /// <param name="assertion">A <see cref="Saml2Assertion"/> to initialize from.</param>
        /// <param name="keys">A collection of <see cref="SecurityKey"/> to include in the token.</param>
        /// <param name="issuerToken">A <see cref="SecurityToken"/> representing the issuer.</param>
        public Saml2SecurityToken(Saml2Assertion assertion, ReadOnlyCollection <SecurityKey> keys, SecurityToken issuerToken)
        {
            if (null == assertion)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("assertion");
            }

            if (null == keys)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("keys");
            }

            this.assertion   = assertion;
            this.keys        = keys;
            this.issuerToken = issuerToken;
        }
        public void Saml2AssertionExtensions_ToXElement_Conditions()
        {
            var assertion = new Saml2Assertion(
                new Saml2NameIdentifier("http://idp.example.com"))
            {
                Conditions = new Saml2Conditions()
                {
                    NotOnOrAfter = new DateTime(2099, 07, 25, 19, 52, 42, DateTimeKind.Utc)
                }
            };

            var subject = assertion.ToXElement();

            subject.Element(Saml2Namespaces.Saml2 + "Conditions")
                .Attribute("NotOnOrAfter").Value.Should().Be("2099-07-25T19:52:42Z");
        }
        /// <summary>
        /// Creates a Saml2Assertion from a ClaimsIdentity.
        /// </summary>
        /// <returns>Saml2Assertion</returns>
        public static Saml2Assertion ToSaml2Assertion(this ClaimsIdentity identity, string issuer)
        {
            if (identity == null)
            {
                throw new ArgumentNullException("identity");
            }

            var assertion = new Saml2Assertion(new Saml2NameIdentifier(issuer));

            assertion.Subject = new Saml2Subject(new Saml2NameIdentifier(
                identity.Claims.Single(c => c.Type == ClaimTypes.NameIdentifier).Value));

            assertion.Conditions = new Saml2Conditions()
            {
                NotOnOrAfter = DateTime.UtcNow.AddMinutes(2)
            };

            return assertion;
        }
        private Saml2Assertion NewAssertion()
        {
            var assertion = new Saml2Assertion(new Saml2NameIdentifier(certificate.Subject));
            assertion.Id = new Saml2Id();
            assertion.IssueInstant = DateTime.Now;

            assertion.Subject = new Saml2Subject(new Saml2NameIdentifier("CPS") { Value = "id3" });
            assertion.Statements.Add(new Saml2AttributeStatement(new Saml2Attribute("identifiantFacturation", "id1")));
            assertion.Statements.Add(new Saml2AttributeStatement(new Saml2Attribute("codeSpecialiteAMO", "id2")));

            var saml2SubjectConfirmation = new Saml2SubjectConfirmation(new Uri("urn:oasis:names:tc:SAML:2.0:cm:bearer"));
            saml2SubjectConfirmation.SubjectConfirmationData = new Saml2SubjectConfirmationData();
            saml2SubjectConfirmation.SubjectConfirmationData.Recipient = new Uri("http://identityserver3");
            saml2SubjectConfirmation.SubjectConfirmationData.NotOnOrAfter = DateTime.UtcNow;

            assertion.Subject.SubjectConfirmations.Add(saml2SubjectConfirmation);

            assertion.SigningCredentials = new X509SigningCredentials(certificate);
            return assertion;
        }
        public void Saml2AssertionExtensions_ToXElement_Xml_BasicAttributes()
        {
            // Grab the current time before and after creating the assertion to
            // handle the unlikely event that the second part of the date time
            // is incremented during the test run. We don't want any heisenbugs.
            var before = DateTime.UtcNow.ToSaml2DateTimeString();

            var issuer = "http://idp.example.com";
            var assertion = new Saml2Assertion(new Saml2NameIdentifier(issuer));

            var after = DateTime.UtcNow.ToSaml2DateTimeString();

            var subject = assertion.ToXElement();

            subject.ToString().Should().StartWith(
                @"<saml2:Assertion xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion");
            subject.Attribute("Version").Value.Should().Be("2.0");
            subject.Attribute("ID").Value.Should().NotBeBlank();
            subject.Attribute("IssueInstant").Value.Should().Match(
                i => i == before || i == after);
        }
        private string GetExpected(Saml2Assertion assertion)
        {
            return string.Format(@"
<Assertion ID=""{0}"" IssueInstant=""{1}"" Version=""2.0"" xmlns=""urn:oasis:names:tc:SAML:2.0:assertion"">
    <Issuer>{2}</Issuer>
    <Signature xmlns=""http://www.w3.org/2000/09/xmldsig#"">
    <SignedInfo>
    <CanonicalizationMethod Algorithm=""http://www.w3.org/2001/10/xml-exc-c14n#"" />
    <SignatureMethod Algorithm=""http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"" />
    <Reference URI=""#{0}"">
    <Transforms>
    <Transform Algorithm=""http://www.w3.org/2000/09/xmldsig#enveloped-signature"" />
        <Transform Algorithm=""http://www.w3.org/2001/10/xml-exc-c14n#"" />
        </Transforms>
        <DigestMethod Algorithm=""http://www.w3.org/2001/04/xmlenc#sha256"" />
",
                assertion.Id.Value, assertion.IssueInstant.ToUniversalTime().ToString(Generated),
                certificate.IssuerName.Name
                )
                .RemoveNewLineSymbols()
                .RemoveXmlIndentation();
        }
 internal ReadOnlyCollection<SecurityKey> ResolveSecurityKeys(Saml2Assertion assertion, SecurityTokenResolver resolver)
 {
   
     Saml2Subject subject = assertion.Subject;
   
     Saml2SubjectConfirmation confirmation = subject.SubjectConfirmations[0];
     if (confirmation.SubjectConfirmationData != null)
     {
         this.ValidateConfirmationData(confirmation.SubjectConfirmationData);
     }
     
     List<SecurityKey> list = new List<SecurityKey>();
     foreach (SecurityKeyIdentifier identifier in confirmation.SubjectConfirmationData.KeyIdentifiers)
     {
         SecurityKey key = null;
         foreach (SecurityKeyIdentifierClause clause in identifier)
         {
             if ((resolver != null) && resolver.TryResolveSecurityKey(clause, out key))
             {
                 list.Add(key);
                 break;
             }
         }
         if (key == null)
         {
             if (identifier.CanCreateKey)
             {
                 key = identifier.CreateKey();
                 list.Add(key);
                 continue;
             }
             list.Add(new SecurityKeyElement(identifier, resolver));
         }
     }
     return list.AsReadOnly();
 }
        /// <summary>
        /// Resolves the Signing Key Identifier to a SecurityToken.
        /// </summary>
        /// <param name="assertion">The Assertion for which the Issuer token is to be resolved.</param>
        /// <param name="issuerResolver">The current SecurityTokenResolver associated with this handler.</param>
        /// <returns>Instance of SecurityToken</returns>
        /// <exception cref="ArgumentNullException">Input parameter 'assertion' is null.</exception>
        /// <exception cref="SecurityTokenException">Unable to resolve token.</exception>
        protected virtual SecurityToken ResolveIssuerToken(Saml2Assertion assertion, SecurityTokenResolver issuerResolver)
        {
            if (null == assertion)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("assertion");
            }

            SecurityToken token;
            if (this.TryResolveIssuerToken(assertion, issuerResolver, out token))
            {
                return token;
            }
            else
            {
                string exceptionMessage = SR.GetString(assertion.SigningCredentials == null ? SR.ID4141 : SR.ID4142);
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(exceptionMessage));
            }
        }
Esempio n. 17
0
        public void Saml2Response_GetClaims_CorrectEncryptedSingleAssertion_UsingWIF()
        {
            var response =
            @"<saml2p:Response xmlns:saml2p=""urn:oasis:names:tc:SAML:2.0:protocol""
            xmlns:saml2=""urn:oasis:names:tc:SAML:2.0:assertion""
            ID = """ + MethodBase.GetCurrentMethod().Name + @""" Version=""2.0"" IssueInstant=""2013-01-01T00:00:00Z"">
                <saml2:Issuer>https://idp.example.com</saml2:Issuer>
                <saml2p:Status>
                    <saml2p:StatusCode Value=""urn:oasis:names:tc:SAML:2.0:status:Success"" />
                </saml2p:Status>
                {0}
            </saml2p:Response>";

            var assertion = new Saml2Assertion(new Saml2NameIdentifier("https://idp.example.com"));
            assertion.Subject = new Saml2Subject(new Saml2NameIdentifier("WIFUser"));
            assertion.Subject.SubjectConfirmations.Add(new Saml2SubjectConfirmation(new Uri("urn:oasis:names:tc:SAML:2.0:cm:bearer")));
            assertion.Conditions = new Saml2Conditions { NotOnOrAfter = new DateTime(2100, 1, 1) };

            var token = new Saml2SecurityToken(assertion);
            var handler = new Saml2SecurityTokenHandler();

            assertion.SigningCredentials = new X509SigningCredentials(SignedXmlHelper.TestCert,
                signatureAlgorithm: SecurityAlgorithms.RsaSha1Signature,
                digestAlgorithm: SecurityAlgorithms.Sha1Digest);

            assertion.EncryptingCredentials = new EncryptedKeyEncryptingCredentials(
                SignedXmlHelper.TestCert2,
                keyWrappingAlgorithm: SecurityAlgorithms.RsaOaepKeyWrap,
                keySizeInBits: 256,
                encryptionAlgorithm: SecurityAlgorithms.Aes192Encryption);

            string assertionXml = String.Empty;
            using (var sw = new StringWriter())
            {
                using (var xw = XmlWriter.Create(sw, new XmlWriterSettings { OmitXmlDeclaration = true }))
                {
                    handler.WriteToken(xw, token);
                }
                assertionXml = sw.ToString();
            }
            var responseWithAssertion = string.Format(response, assertionXml);

            var claims = Saml2Response.Read(responseWithAssertion).GetClaims(Options.FromConfiguration);
            claims.Count().Should().Be(1);
            claims.First().FindFirst(ClaimTypes.NameIdentifier).Value.Should().Be("WIFUser");
        }
 public WrappedSerializer(Saml2SecurityTokenHandler parent, Saml2Assertion assertion)
 {
     this.assertion = assertion;
     this.parent = parent;
 }
        /// <summary>
        /// Deserializes the SAML Signing KeyInfo
        /// </summary>
        /// <param name="reader">A <see cref="XmlReader"/> positioned at a than can be positioned at a ds:KeyInfo element.</param>
        /// <param name="assertion">The <see cref="Saml2Assertion"/> that is having the signature checked.</param>
        /// <returns>The <see cref="SecurityKeyIdentifier"/> that defines the key to use to check the signature.</returns>
        /// <exception cref="ArgumentNullException">Input parameter 'reader' is null.</exception>
        protected virtual SecurityKeyIdentifier ReadSigningKeyInfo(XmlReader reader, Saml2Assertion assertion)
        {
            if (null == reader)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
            }

            SecurityKeyIdentifier ski;

            if (this.KeyInfoSerializer.CanReadKeyIdentifier(reader))
            {
                ski = this.KeyInfoSerializer.ReadKeyIdentifier(reader);
            }
            else
            {
                KeyInfo keyInfo = new KeyInfo(this.KeyInfoSerializer);
                keyInfo.ReadXml(XmlDictionaryReader.CreateDictionaryReader(reader));
                ski = keyInfo.KeyIdentifier;
            }

            // no key info
            if (ski.Count == 0)
            {
                return new SecurityKeyIdentifier(new Saml2SecurityKeyIdentifierClause(assertion));
            }

            return ski;
        }
        /// <summary>
        /// Serializes the provided SamlAssertion to the XmlWriter.
        /// </summary>
        /// <param name="writer">A <see cref="XmlWriter"/> to serialize the <see cref="Saml2Assertion"/>.</param>
        /// <param name="data">The <see cref="Saml2Assertion"/> to serialize.</param>
        /// <exception cref="ArgumentNullException">The <paramref name="writer"/> or <paramref name="data"/> parameters are null.</exception>
        /// <exception cref="InvalidOperationException"> The <paramref name="data"/>  has both <see cref="EncryptingCredentials"/> and <see cref="ReceivedEncryptingCredentials"/> properties null.</exception>
        /// <exception cref="InvalidOperationException">The <paramref name="data"/> must have a <see cref="Saml2Subject"/> if no <see cref="Saml2Statement"/> are present.</exception>
        /// <exception cref="InvalidOperationException">The SAML2 authentication, attribute, and authorization decision <see cref="Saml2Statement"/> require a <see cref="Saml2Subject"/>.</exception>
        /// <exception cref="CryptographicException">Token encrypting credentials must have a Symmetric Key specified.</exception>
        protected virtual void WriteAssertion(XmlWriter writer, Saml2Assertion data)
        {
            if (null == writer)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer");
            }

            if (null == data)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("data");
            }

            XmlWriter originalWriter = writer;
            MemoryStream plaintextStream = null;
            XmlDictionaryWriter plaintextWriter = null;

            // If an EncryptingCredentials is present then check if this is not of type ReceivedEncryptinCredentials.
            // ReceivedEncryptingCredentials mean that it was credentials that were hydrated from a token received
            // on the wire. We should not directly use this while re-serializing a token.
            if ((null != data.EncryptingCredentials) && !(data.EncryptingCredentials is ReceivedEncryptingCredentials))
            {
                plaintextStream = new MemoryStream();
                writer = plaintextWriter = XmlDictionaryWriter.CreateTextWriter(plaintextStream, Encoding.UTF8, false);
            }
            else if (data.ExternalEncryptedKeys == null || data.ExternalEncryptedKeys.Count > 0)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID4173)));
            }

            // If we've saved off the token stream, re-emit it.
            if (data.CanWriteSourceData)
            {
                data.WriteSourceData(writer);
            }
            else
            {
                // Wrap the writer if necessary for a signature
                // We do not dispose this writer, since as a delegating writer it would
                // dispose the inner writer, which we don't properly own.
                EnvelopedSignatureWriter signatureWriter = null;
                if (null != data.SigningCredentials)
                {
#pragma warning suppress 56506
                    writer = signatureWriter = new EnvelopedSignatureWriter(writer, data.SigningCredentials, data.Id.Value, new WrappedSerializer(this, data));
                }

                if (null == data.Subject)
                {
                    // An assertion with no statements MUST contain a <Subject> element. [Saml2Core, line 585]
                    if (data.Statements == null || 0 == data.Statements.Count)
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID4106)));
                    }

                    // Furthermore, the built-in statement types all require the presence of a subject.
                    // [Saml2Core, lines 1050, 1168, 1280]
                    foreach (Saml2Statement statement in data.Statements)
                    {
                        if (statement is Saml2AuthenticationStatement
                            || statement is Saml2AttributeStatement
                            || statement is Saml2AuthorizationDecisionStatement)
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                                new InvalidOperationException(SR.GetString(SR.ID4119)));
                        }
                    }
                }

                // <Assertion>
                writer.WriteStartElement(Saml2Constants.Elements.Assertion, Saml2Constants.Namespace);

                // @ID - required
                writer.WriteAttributeString(Saml2Constants.Attributes.ID, data.Id.Value);

                // @IssueInstant - required
                writer.WriteAttributeString(Saml2Constants.Attributes.IssueInstant, XmlConvert.ToString(data.IssueInstant.ToUniversalTime(), DateTimeFormats.Generated));

                // @Version - required
                writer.WriteAttributeString(Saml2Constants.Attributes.Version, data.Version);

                // <Issuer> 1
                this.WriteIssuer(writer, data.Issuer);

                // <ds:Signature> 0-1
                if (null != signatureWriter)
                {
                    signatureWriter.WriteSignature();
                }

                // <Subject> 0-1
                if (null != data.Subject)
                {
                    this.WriteSubject(writer, data.Subject);
                }

                // <Conditions> 0-1
                if (null != data.Conditions)
                {
                    this.WriteConditions(writer, data.Conditions);
                }

                // <Advice> 0-1
                if (null != data.Advice)
                {
                    this.WriteAdvice(writer, data.Advice);
                }

                // <Statement|AuthnStatement|AuthzDecisionStatement|AttributeStatement>, 0-OO
                foreach (Saml2Statement statement in data.Statements)
                {
                    this.WriteStatement(writer, statement);
                }

                writer.WriteEndElement();
            }

            // Finish off the encryption
            if (null != plaintextWriter)
            {
                ((IDisposable)plaintextWriter).Dispose();
                plaintextWriter = null;

                EncryptedDataElement encryptedData = new EncryptedDataElement();
                encryptedData.Type = XmlEncryptionConstants.EncryptedDataTypes.Element;
                encryptedData.Algorithm = data.EncryptingCredentials.Algorithm;
                encryptedData.KeyIdentifier = data.EncryptingCredentials.SecurityKeyIdentifier;

                // Get the encryption key, which must be symmetric
                SymmetricSecurityKey encryptingKey = data.EncryptingCredentials.SecurityKey as SymmetricSecurityKey;
                if (encryptingKey == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CryptographicException(SR.GetString(SR.ID3064)));
                }

                // Do the actual encryption
                SymmetricAlgorithm symmetricAlgorithm = encryptingKey.GetSymmetricAlgorithm(data.EncryptingCredentials.Algorithm);
                encryptedData.Encrypt(symmetricAlgorithm, plaintextStream.GetBuffer(), 0, (int)plaintextStream.Length);
                ((IDisposable)plaintextStream).Dispose();

                originalWriter.WriteStartElement(Saml2Constants.Elements.EncryptedAssertion, Saml2Constants.Namespace);
                encryptedData.WriteXml(originalWriter, this.KeyInfoSerializer);
                foreach (EncryptedKeyIdentifierClause clause in data.ExternalEncryptedKeys)
                {
                    this.KeyInfoSerializer.WriteKeyIdentifierClause(originalWriter, clause);
                }

                originalWriter.WriteEndElement();
            }
        }
        /// <summary>
        /// Reads the &lt;saml:Assertion> element.
        /// </summary>
        /// <param name="reader">A <see cref="XmlReader"/> positioned at a <see cref="Saml2Assertion"/> element.</param>
        /// <returns>A <see cref="Saml2Assertion"/> instance.</returns>
        protected virtual Saml2Assertion ReadAssertion(XmlReader reader)
        {
            if (null == reader)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
            }

            if (this.Configuration == null)
            {
                throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4274));
            }

            if (this.Configuration.IssuerTokenResolver == null)
            {
                throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4275));
            }

            if (this.Configuration.ServiceTokenResolver == null)
            {
                throw DiagnosticUtility.ThrowHelperInvalidOperation(SR.GetString(SR.ID4276));
            }

            XmlDictionaryReader plaintextReader = XmlDictionaryReader.CreateDictionaryReader(reader);

            Saml2Assertion assertion = new Saml2Assertion(new Saml2NameIdentifier("__TemporaryIssuer__"));

            // If it's an EncryptedAssertion, we need to retrieve the plaintext 
            // and repoint our reader
            if (reader.IsStartElement(Saml2Constants.Elements.EncryptedAssertion, Saml2Constants.Namespace))
            {
                EncryptingCredentials encryptingCredentials = null;
                plaintextReader = CreatePlaintextReaderFromEncryptedData(
                                    plaintextReader,
                                    Configuration.ServiceTokenResolver,
                                    this.KeyInfoSerializer,
                                    assertion.ExternalEncryptedKeys,
                                    out encryptingCredentials);

                assertion.EncryptingCredentials = encryptingCredentials;
            }

            // Throw if wrong element
            if (!plaintextReader.IsStartElement(Saml2Constants.Elements.Assertion, Saml2Constants.Namespace))
            {
                plaintextReader.ReadStartElement(Saml2Constants.Elements.Assertion, Saml2Constants.Namespace);
            }

            // disallow empty
            if (plaintextReader.IsEmptyElement)
            {
#pragma warning suppress 56504 // bogus - thinks plaintextReader.LocalName, plaintextReader.NamespaceURI need validation
                throw DiagnosticUtility.ThrowHelperXml(plaintextReader, SR.GetString(SR.ID3061, plaintextReader.LocalName, plaintextReader.NamespaceURI));
            }

            // Construct a wrapped serializer so that the EnvelopedSignatureReader's 
            // attempt to read the <ds:KeyInfo> will hit our ReadKeyInfo virtual.
            WrappedSerializer wrappedSerializer = new WrappedSerializer(this, assertion);

            // SAML supports enveloped signature, so we need to wrap our reader.
            // We do not dispose this reader, since as a delegating reader it would
            // dispose the inner reader, which we don't properly own.
            EnvelopedSignatureReader realReader = new EnvelopedSignatureReader(plaintextReader, wrappedSerializer, this.Configuration.IssuerTokenResolver, false, false, false);
            try
            {
                // Process @attributes
                string value;

                // @xsi:type
                XmlUtil.ValidateXsiType(realReader, Saml2Constants.Types.AssertionType, Saml2Constants.Namespace);

                // @Version - required - must be "2.0"
                string version = realReader.GetAttribute(Saml2Constants.Attributes.Version);
                if (string.IsNullOrEmpty(version))
                {
                    throw DiagnosticUtility.ThrowHelperXml(realReader, SR.GetString(SR.ID0001, Saml2Constants.Attributes.Version, Saml2Constants.Elements.Assertion));
                }

                if (!StringComparer.Ordinal.Equals(assertion.Version, version))
                {
                    throw DiagnosticUtility.ThrowHelperXml(realReader, SR.GetString(SR.ID4100, version));
                }

                // @ID - required
                value = realReader.GetAttribute(Saml2Constants.Attributes.ID);
                if (string.IsNullOrEmpty(value))
                {
                    throw DiagnosticUtility.ThrowHelperXml(realReader, SR.GetString(SR.ID0001, Saml2Constants.Attributes.ID, Saml2Constants.Elements.Assertion));
                }

                assertion.Id = new Saml2Id(value);

                // @IssueInstant - required
                value = realReader.GetAttribute(Saml2Constants.Attributes.IssueInstant);
                if (string.IsNullOrEmpty(value))
                {
                    throw DiagnosticUtility.ThrowHelperXml(realReader, SR.GetString(SR.ID0001, Saml2Constants.Attributes.IssueInstant, Saml2Constants.Elements.Assertion));
                }

                assertion.IssueInstant = XmlConvert.ToDateTime(value, DateTimeFormats.Accepted);

                // Process <elements>
                realReader.Read();

                // <Issuer> 1
                assertion.Issuer = this.ReadIssuer(realReader);

                // <ds:Signature> 0-1
                realReader.TryReadSignature();

                // <Subject> 0-1
                if (realReader.IsStartElement(Saml2Constants.Elements.Subject, Saml2Constants.Namespace))
                {
                    assertion.Subject = this.ReadSubject(realReader);
                }

                // <Conditions> 0-1
                if (realReader.IsStartElement(Saml2Constants.Elements.Conditions, Saml2Constants.Namespace))
                {
                    assertion.Conditions = this.ReadConditions(realReader);
                }

                // <Advice> 0-1
                if (realReader.IsStartElement(Saml2Constants.Elements.Advice, Saml2Constants.Namespace))
                {
                    assertion.Advice = this.ReadAdvice(realReader);
                }

                // <Statement|AuthnStatement|AuthzDecisionStatement|AttributeStatement>, 0-OO
                while (realReader.IsStartElement())
                {
                    Saml2Statement statement;

                    if (realReader.IsStartElement(Saml2Constants.Elements.Statement, Saml2Constants.Namespace))
                    {
                        statement = this.ReadStatement(realReader);
                    }
                    else if (realReader.IsStartElement(Saml2Constants.Elements.AttributeStatement, Saml2Constants.Namespace))
                    {
                        statement = this.ReadAttributeStatement(realReader);
                    }
                    else if (realReader.IsStartElement(Saml2Constants.Elements.AuthnStatement, Saml2Constants.Namespace))
                    {
                        statement = this.ReadAuthenticationStatement(realReader);
                    }
                    else if (realReader.IsStartElement(Saml2Constants.Elements.AuthzDecisionStatement, Saml2Constants.Namespace))
                    {
                        statement = this.ReadAuthorizationDecisionStatement(realReader);
                    }
                    else
                    {
                        break;
                    }

                    assertion.Statements.Add(statement);
                }

                realReader.ReadEndElement();

                if (null == assertion.Subject)
                {
                    // An assertion with no statements MUST contain a <Subject> element. [Saml2Core, line 585]
                    if (0 == assertion.Statements.Count)
                    {
                        throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID4106));
                    }

                    // Furthermore, the built-in statement types all require the presence of a subject.
                    // [Saml2Core, lines 1050, 1168, 1280]
                    foreach (Saml2Statement statement in assertion.Statements)
                    {
                        if (statement is Saml2AuthenticationStatement
                            || statement is Saml2AttributeStatement
                            || statement is Saml2AuthorizationDecisionStatement)
                        {
                            throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID4119));
                        }
                    }
                }

                // Reading the end element will complete the signature; 
                // capture the signing creds
                assertion.SigningCredentials = realReader.SigningCredentials;

                // Save the captured on-the-wire data, which can then be used
                // to re-emit this assertion, preserving the same signature.
                assertion.CaptureSourceData(realReader);

                return assertion;
            }
            catch (Exception e)
            {
                if (System.Runtime.Fx.IsFatal(e))
                    throw;
                
                Exception wrapped = TryWrapReadException(realReader, e);
                if (null == wrapped)
                {
                    throw;
                }
                else
                {
                    throw wrapped;
                }
            }
        }
        private Saml2Assertion NewAssertion(X509Certificate2 x509Certificate2 = null, ClaimsIdentity id = null)
        {
            var cert = x509Certificate2 ?? certificate;
            var assertion = new Saml2Assertion(new Saml2NameIdentifier("b"));
            assertion.Id = new Saml2Id();
            assertion.IssueInstant = DateTime.Now;

            assertion.Subject = new Saml2Subject(new Saml2NameIdentifier("CPS") { Value = "id3" });
            assertion.Statements.Add(new Saml2AttributeStatement(new Saml2Attribute("identifiantFacturation", "id1")));
            assertion.Statements.Add(new Saml2AttributeStatement(new Saml2Attribute("codeSpecialiteAMO", "id2")));
            if (id != null)
            foreach (var claim in id.Claims)
            {
                assertion.Statements.Add(new Saml2AttributeStatement(new Saml2Attribute(claim.Type, claim.Value)));
            }


            var saml2SubjectConfirmation = new Saml2SubjectConfirmation(new Uri("urn:oasis:names:tc:SAML:2.0:cm:bearer"));
            saml2SubjectConfirmation.SubjectConfirmationData = new Saml2SubjectConfirmationData();
            saml2SubjectConfirmation.SubjectConfirmationData.Recipient = new Uri("http://allowed_recipient1");
            saml2SubjectConfirmation.SubjectConfirmationData.NotOnOrAfter = DateTime.UtcNow.AddHours(1); // valid for 1 hour

            assertion.Subject.SubjectConfirmations.Add(saml2SubjectConfirmation);

            assertion.Conditions = new Saml2Conditions();
            assertion.Conditions.AudienceRestrictions.Add(new Saml2AudienceRestriction(new Uri("http://audience")));

            assertion.SigningCredentials = new X509SigningCredentials(cert);
            return assertion;
        }
        // Looks like this is called for HOK tokens, so why it is called for the SV token?????
        // This is called by ReadToken and this will be needed in order to support other confirmation methods
        protected override ReadOnlyCollection<SecurityKey> ResolveSecurityKeys(Saml2Assertion assertion, SecurityTokenResolver resolver)
        {
            CustomTextTraceSource ts = new CustomTextTraceSource("CommercialVehicleCollisionWebservice.CustomSaml2SecurityTokenHandler.ResolveSecurityKeys",
                   "MyTraceSource", SourceLevels.Information);

            // In model 2, the SAML assertion is , by design, always using the 
            // sender-vouches confirmation method so we always return an empty collection
            return new ReadOnlyCollection<SecurityKey>(new SecurityKey[0]);

            #region Modify to include Holder-of-Key and Bearer
            //Saml2Subject subject = assertion.Subject;
            //if (subject == null)
            //{
            //    throw new SecurityTokenException("null Saml2Subject");
            //}
            //if (subject.SubjectConfirmations.Count == 0)
            //{
            //    throw new SecurityTokenException("Empty SubjectConfirmations");
            //}
            //if (subject.SubjectConfirmations.Count > 1)
            //{
            //    throw new SecurityTokenException("More than 1 SubjectConfirmations");
            //}

            //Saml2SubjectConfirmation confirmation = subject.SubjectConfirmations[0];

            //// enable sender-vouches confirmation method 
            //if (Saml2Constants.ConfirmationMethods.Bearer == confirmation.Method || Saml2Constants.ConfirmationMethods.SenderVouches == confirmation.Method)
            //{
            //    if ((confirmation.SubjectConfirmationData != null) && (confirmation.SubjectConfirmationData.KeyIdentifiers.Count != 0))
            //    {
            //        throw DiagnosticUtil.ExceptionUtil.ThrowHelperError(new SecurityTokenException("A Saml2SecurityToken cannot be created from the Saml2Assertion because it specifies the Bearer confirmation method but identifies keys in the SubjectConfirmationData."));
            //    }
            //    return Common.EmptyReadOnlyCollection<SecurityKey>.Instance;
            //}
            ////if (!(Saml2Constants.ConfirmationMethods.HolderOfKey == confirmation.Method))
            ////{
            ////    throw DiagnosticUtil.ExceptionUtil.ThrowHelperError(new SecurityTokenException(SR.GetString("ID4136", new object[] { confirmation.Method })));
            ////}
            ////if ((confirmation.SubjectConfirmationData == null) || (confirmation.SubjectConfirmationData.KeyIdentifiers.Count == 0))
            ////{
            ////    throw DiagnosticUtil.ExceptionUtil.ThrowHelperError(new SecurityTokenException(SR.GetString("ID4134", new object[0])));
            ////}
            //List<SecurityKey> list = new List<SecurityKey>();

            //if (confirmation.SubjectConfirmationData != null)
            //{
            //    foreach (SecurityKeyIdentifier identifier in confirmation.SubjectConfirmationData.KeyIdentifiers)
            //    {
            //        SecurityKey key = null;
            //        foreach (SecurityKeyIdentifierClause clause in identifier)
            //        {
            //            if ((resolver != null) && resolver.TryResolveSecurityKey(clause, out key))
            //            {
            //                list.Add(key);
            //                break;
            //            }
            //        }
            //        if (key == null)
            //        {
            //            if (identifier.CanCreateKey)
            //            {
            //                key = identifier.CreateKey();
            //                list.Add(key);
            //                continue;
            //            }
            //            list.Add(new SecurityKeyElement(identifier, resolver));
            //        }
            //    }
            //}

            //return list.AsReadOnly();
            #endregion
        }
 private ValidatedTokenRequest Request(Saml2Assertion saml)
 {
     var serialized = serializer.ToXml(saml);
     //Console.WriteLine(serialized);
     return Request(serialized.ToBase64Url());
 }
Esempio n. 25
0
 /// <summary>
 /// Initializes an instance of <see cref="Saml2SecurityToken"/> from a <see cref="Saml2Assertion"/>.
 /// </summary>
 /// <param name="assertion">A <see cref="Saml2Assertion"/> to initialize from.</param>
 public Saml2SecurityToken(Saml2Assertion assertion)
     : this(assertion, EmptyReadOnlyCollection <SecurityKey> .Instance, null)
 {
 }
 public DerivedSaml2SecurityToken(Saml2Assertion samlAssertion)
     : base(samlAssertion)
 {
 }
        // TODO: The WSP and ADS incoming SAML token handlers share code. Extract base class
        protected override ReadOnlyCollection<SecurityKey> ResolveSecurityKeys(Saml2Assertion assertion, SecurityTokenResolver resolver)
        {
            Saml2Subject subject = assertion.Subject;

            Saml2SubjectConfirmation confirmation = subject.SubjectConfirmations[0];

            if (Saml2Constants.ConfirmationMethods.SenderVouches == confirmation.Method)
            {
                // empty ReadOnlyCollection
                return new ReadOnlyCollection<SecurityKey>(new SecurityKey[0]);
            }

            // let the base class handle assertion with the bearer or 
            // holder-of-key confirmation methods
            return base.ResolveSecurityKeys(assertion, resolver);
        }
        /// <summary>
        /// Resolves the Signing Key Identifier to a SecurityToken.
        /// </summary>
        /// <param name="assertion">The Assertion for which the Issuer token is to be resolved.</param>
        /// <param name="issuerResolver">The current SecurityTokenResolver associated with this handler.</param>
        /// <param name="token">Resolved token.</param>
        /// <returns>True if token is resolved.</returns>
        protected virtual bool TryResolveIssuerToken(Saml2Assertion assertion, SecurityTokenResolver issuerResolver, out SecurityToken token)
        {
            if (null == assertion)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("assertion");
            }

            if (assertion.SigningCredentials != null
                && assertion.SigningCredentials.SigningKeyIdentifier != null
                && issuerResolver != null)
            {
                SecurityKeyIdentifier keyIdentifier = assertion.SigningCredentials.SigningKeyIdentifier;
                return issuerResolver.TryResolveToken(keyIdentifier, out token);
            }
            else
            {
                token = null;
                return false;
            }
        }
        /// <summary>
        /// Creates a <see cref="SecurityToken"/> based on a information contained in the <see cref="SecurityTokenDescriptor"/>.
        /// </summary>
        /// <param name="tokenDescriptor">The <see cref="SecurityTokenDescriptor"/> that has creation information.</param>
        /// <returns>A <see cref="SecurityToken"/> instance.</returns>
        /// <exception cref="ArgumentNullException">Thrown if 'tokenDescriptor' is null.</exception>
        public override SecurityToken CreateToken(SecurityTokenDescriptor tokenDescriptor)
        {
            if (null == tokenDescriptor)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("tokenDescriptor");
            }

            // Assertion/issuer
            Saml2Assertion assertion = new Saml2Assertion(this.CreateIssuerNameIdentifier(tokenDescriptor));

            // Subject
            assertion.Subject = this.CreateSamlSubject(tokenDescriptor);

            // Signature
            assertion.SigningCredentials = this.GetSigningCredentials(tokenDescriptor);

            // Conditions
            assertion.Conditions = this.CreateConditions(tokenDescriptor.Lifetime, tokenDescriptor.AppliesToAddress, tokenDescriptor);

            // Advice
            assertion.Advice = this.CreateAdvice(tokenDescriptor);

            // Statements
            IEnumerable<Saml2Statement> statements = this.CreateStatements(tokenDescriptor);
            if (null != statements)
            {
                foreach (Saml2Statement statement in statements)
                {
                    assertion.Statements.Add(statement);
                }
            }

            // encrypting credentials
            assertion.EncryptingCredentials = this.GetEncryptingCredentials(tokenDescriptor);

            SecurityToken token = new Saml2SecurityToken(assertion);

            return token;
        }
        /// <summary>
        /// Resolves the collection of <see cref="SecurityKey"/> referenced in a <see cref="Saml2Assertion"/>.
        /// </summary>
        /// <param name="assertion"><see cref="Saml2Assertion"/> to process.</param>
        /// <param name="resolver"><see cref="SecurityTokenResolver"/> to use in resolving the <see cref="SecurityKey"/>.</param>
        /// <returns>A read only collection of <see cref="SecurityKey"/> contained in the assertion.</returns>
        protected virtual ReadOnlyCollection<SecurityKey> ResolveSecurityKeys(Saml2Assertion assertion, SecurityTokenResolver resolver)
        {
            if (null == assertion)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("assertion");
            }

            // Must have Subject
            Saml2Subject subject = assertion.Subject;
            if (null == subject)
            {
                // No Subject
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4130)));
            }

            // Must have one SubjectConfirmation
            if (0 == subject.SubjectConfirmations.Count)
            {
                // No SubjectConfirmation
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4131)));
            }

            if (subject.SubjectConfirmations.Count > 1)
            {
                // More than one SubjectConfirmation
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4132)));
            }

            // Extract the keys for the given method
            ReadOnlyCollection<SecurityKey> securityKeys;

            Saml2SubjectConfirmation subjectConfirmation = subject.SubjectConfirmations[0];

            // For bearer, ensure there are no keys, set the collection to empty
            // For HolderOfKey, ensure there is at least one key, resolve and create collection
            if (Saml2Constants.ConfirmationMethods.Bearer == subjectConfirmation.Method)
            {
                if (null != subjectConfirmation.SubjectConfirmationData
                    && 0 != subjectConfirmation.SubjectConfirmationData.KeyIdentifiers.Count)
                {
                    // Bearer but has keys
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4133)));
                }

                securityKeys = EmptyReadOnlyCollection<SecurityKey>.Instance;
            }
            else if (Saml2Constants.ConfirmationMethods.HolderOfKey == subjectConfirmation.Method)
            {
                if (null == subjectConfirmation.SubjectConfirmationData
                    || 0 == subjectConfirmation.SubjectConfirmationData.KeyIdentifiers.Count)
                {
                    // Holder-of-key but no keys
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4134)));
                }

                List<SecurityKey> holderKeys = new List<SecurityKey>();
                SecurityKey key;

                foreach (SecurityKeyIdentifier keyIdentifier in subjectConfirmation.SubjectConfirmationData.KeyIdentifiers)
                {
                    key = null;

                    // Try the resolver first
                    foreach (SecurityKeyIdentifierClause clause in keyIdentifier)
                    {
                        if (null != resolver
                            && resolver.TryResolveSecurityKey(clause, out key))
                        {
                            holderKeys.Add(key);
                            break;
                        }
                    }

                    // If that doesn't work, try to create the key (e.g. bare RSA or X509 raw)
                    if (null == key)
                    {
                        if (keyIdentifier.CanCreateKey)
                        {
                            key = keyIdentifier.CreateKey();
                            holderKeys.Add(key);
                        }
                        else
                        {
                            holderKeys.Add(new SecurityKeyElement(keyIdentifier, resolver));
                        }
                    }
                }

                securityKeys = holderKeys.AsReadOnly();
            }
            else
            {
                // SenderVouches, as well as other random things, aren't accepted
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4136, subjectConfirmation.Method)));
            }

            return securityKeys;
        }
 private void ValidateMethod(Saml2Assertion assertion)
 {
     // TODO - not covereted, see ValidateAsync_3_5_Given_SAML_With_Unsupported_Method_Throw unit test
     var method = assertion.Subject.SubjectConfirmations[0].Method;
     if (method != ConfirmationMethods.Bearer)
         throw new SecurityTokenException(string.Format("Message=Unsupported method, Expected={0}, Actual={1}",
             ConfirmationMethods.Bearer, method));
 }
        public void Saml2AssertionExtensions_ToXElement_Issuer()
        {
            var issuer = "http://idp.example.com";
            var assertion = new Saml2Assertion(new Saml2NameIdentifier(issuer));

            var subject = assertion.ToXElement();

            subject.Element(Saml2Namespaces.Saml2 + "Issuer").Value.Should().Be(issuer);
        }