コード例 #1
0
        public void Saml2ConditionsExtensions_ToXElement_OnlyNotOnOrAfter()
        {
            var conditions = new Saml2Conditions()
            {
                NotOnOrAfter = new DateTime(2099, 07, 25, 19, 52, 42, DateTimeKind.Utc)
            };

            var actual = conditions.ToXElement();

            actual.Name.Should().Be(Saml2Namespaces.Saml2 + "Conditions");

            actual.Attribute("NotOnOrAfter").Value.Should().Be("2099-07-25T19:52:42Z");
        }
コード例 #2
0
        public void Saml2ConditionsExtensions_ToXElement_OnlyAudienceRestriction()
        {
            var conditions = new Saml2Conditions();
            conditions.AudienceRestrictions.Add(new Saml2AudienceRestriction(new[]
            {
                new Uri("http://foo1"),
                new Uri("http://foo2")
            }));

            conditions.AudienceRestrictions.Add(new Saml2AudienceRestriction(new Uri("http://bar")));

            var actual = conditions.ToXElement();

            var expected = new XElement(Saml2Namespaces.Saml2 + "Conditions",
                new XElement(Saml2Namespaces.Saml2 + "AudienceRestriction",
                    new XElement(Saml2Namespaces.Saml2 + "Audience", "http://foo1"),
                    new XElement(Saml2Namespaces.Saml2 + "Audience", "http://foo2")),
                new XElement(Saml2Namespaces.Saml2 + "AudienceRestriction",
                    new XElement(Saml2Namespaces.Saml2 + "Audience", "http://bar")));

            actual.Should().BeEquivalentTo(expected);
        }
コード例 #3
0
 protected override void ValidateConditions(Saml2Conditions conditions, bool enforceAudienceRestriction)
 {
     Saml2ConditionsDelegateWrapper delegateConditions = conditions as Saml2ConditionsDelegateWrapper;
     
     ValidateDelegates(delegateConditions.Delegates);
     
     base.ValidateConditions(conditions, enforceAudienceRestriction);
 }
コード例 #4
0
        /// <summary>
        /// Writes the &lt;saml:Conditions> element.
        /// </summary>
        /// <param name="writer">A <see cref="XmlWriter"/> to serialize the <see cref="Saml2Conditions"/>.</param>
        /// <param name="data">The <see cref="Saml2Conditions"/> to serialize.</param>
        protected virtual void WriteConditions(XmlWriter writer, Saml2Conditions data)
        {
            if (null == writer)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer");
            }

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

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

            // @NotBefore - optional
            if (null != data.NotBefore)
            {
                writer.WriteAttributeString(Saml2Constants.Attributes.NotBefore, XmlConvert.ToString(data.NotBefore.Value.ToUniversalTime(), DateTimeFormats.Generated));
            }

            // @NotOnOrAfter - optional
            if (null != data.NotOnOrAfter)
            {
                writer.WriteAttributeString(Saml2Constants.Attributes.NotOnOrAfter, XmlConvert.ToString(data.NotOnOrAfter.Value.ToUniversalTime(), DateTimeFormats.Generated));
            }

            // <AudienceRestriction> 0-OO
            foreach (Saml2AudienceRestriction audienceRestriction in data.AudienceRestrictions)
            {
                this.WriteAudienceRestriction(writer, audienceRestriction);
            }

            // <OneTimeUse> - limited to one in SAML spec
            if (data.OneTimeUse)
            {
                writer.WriteStartElement(Saml2Constants.Elements.OneTimeUse, Saml2Constants.Namespace);
                writer.WriteEndElement();
            }

            // <ProxyRestriction> - limited to one in SAML spec
            if (null != data.ProxyRestriction)
            {
                this.WriteProxyRestriction(writer, data.ProxyRestriction);
            }

            // </Conditions>
            writer.WriteEndElement();
        }
コード例 #5
0
        /// <summary>
        /// Reads the &lt;saml:Conditions> element.
        /// </summary>
        /// <remarks>
        /// To handle custom &lt;saml:Condition> elements, override this 
        /// method.
        /// </remarks>
        /// <param name="reader">A <see cref="XmlReader"/> positioned at a <see cref="Saml2Conditions"/> element.</param>
        /// <returns>A <see cref="Saml2Conditions"/> instance.</returns>
        protected virtual Saml2Conditions ReadConditions(XmlReader reader)
        {
            if (null == reader)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
            }

            // throw if wrong element
            if (!reader.IsStartElement(Saml2Constants.Elements.Conditions, Saml2Constants.Namespace))
            {
                reader.ReadStartElement(Saml2Constants.Elements.Conditions, Saml2Constants.Namespace);
            }

            try
            {
                Saml2Conditions conditions = new Saml2Conditions();

                bool isEmpty = reader.IsEmptyElement;

                // @attributes
                string value;

                // @xsi:type
                XmlUtil.ValidateXsiType(reader, Saml2Constants.Types.ConditionsType, Saml2Constants.Namespace);

                // @NotBefore - optional
                value = reader.GetAttribute(Saml2Constants.Attributes.NotBefore);
                if (!string.IsNullOrEmpty(value))
                {
                    conditions.NotBefore = XmlConvert.ToDateTime(value, DateTimeFormats.Accepted);
                }

                // @NotOnOrAfter - optional
                value = reader.GetAttribute(Saml2Constants.Attributes.NotOnOrAfter);
                if (!string.IsNullOrEmpty(value))
                {
                    conditions.NotOnOrAfter = XmlConvert.ToDateTime(value, DateTimeFormats.Accepted);
                }

                // Content
                reader.ReadStartElement();
                if (!isEmpty)
                {
                    // <Condition|AudienceRestriction|OneTimeUse|ProxyRestriction>, 0-OO
                    while (reader.IsStartElement())
                    {
                        // <Condition> - 0-OO
                        if (reader.IsStartElement(Saml2Constants.Elements.Condition, Saml2Constants.Namespace))
                        {
                            // Since Condition is abstract, must process based on xsi:type
                            XmlQualifiedName declaredType = XmlUtil.GetXsiType(reader);

                            // No type, throw
                            if (null == declaredType
                                || XmlUtil.EqualsQName(declaredType, Saml2Constants.Types.ConditionAbstractType, Saml2Constants.Namespace))
                            {
                                throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID4104, reader.LocalName, reader.NamespaceURI));
                            }
                            else if (XmlUtil.EqualsQName(declaredType, Saml2Constants.Types.AudienceRestrictionType, Saml2Constants.Namespace))
                            {
                                conditions.AudienceRestrictions.Add(this.ReadAudienceRestriction(reader));
                            }
                            else if (XmlUtil.EqualsQName(declaredType, Saml2Constants.Types.OneTimeUseType, Saml2Constants.Namespace))
                            {
                                if (conditions.OneTimeUse)
                                {
                                    throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID4115, Saml2Constants.Elements.OneTimeUse));
                                }

                                ReadEmptyContentElement(reader);
                                conditions.OneTimeUse = true;
                            }
                            else if (XmlUtil.EqualsQName(declaredType, Saml2Constants.Types.ProxyRestrictionType, Saml2Constants.Namespace))
                            {
                                if (null != conditions.ProxyRestriction)
                                {
                                    throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID4115, Saml2Constants.Elements.ProxyRestricton));
                                }

                                conditions.ProxyRestriction = this.ReadProxyRestriction(reader);
                            }
                            else
                            {
                                // Unknown type - Instruct the user to override to handle custom <Condition>
                                throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID4113));
                            }
                        }
                        else if (reader.IsStartElement(Saml2Constants.Elements.AudienceRestriction, Saml2Constants.Namespace))
                        {
                            conditions.AudienceRestrictions.Add(this.ReadAudienceRestriction(reader));
                        }
                        else if (reader.IsStartElement(Saml2Constants.Elements.OneTimeUse, Saml2Constants.Namespace))
                        {
                            if (conditions.OneTimeUse)
                            {
                                throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID4115, Saml2Constants.Elements.OneTimeUse));
                            }

                            ReadEmptyContentElement(reader);
                            conditions.OneTimeUse = true;
                        }
                        else if (reader.IsStartElement(Saml2Constants.Elements.ProxyRestricton, Saml2Constants.Namespace))
                        {
                            if (null != conditions.ProxyRestriction)
                            {
                                throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID4115, Saml2Constants.Elements.ProxyRestricton));
                            }

                            conditions.ProxyRestriction = this.ReadProxyRestriction(reader);
                        }
                        else
                        {
                            break;
                        }
                    }

                    reader.ReadEndElement();
                }

                return conditions;
            }
            catch (Exception e)
            {
                if (System.Runtime.Fx.IsFatal(e))
                    throw;
                
                Exception wrapped = TryWrapReadException(reader, e);
                if (null == wrapped)
                {
                    throw;
                }
                else
                {
                    throw wrapped;
                }
            }
        }
コード例 #6
0
        /// <summary>
        /// Rejects tokens that are not valid. 
        /// </summary>
        /// <remarks>
        /// The token may not be valid for a number of reasons. For example, the 
        /// current time may not be within the token's validity period, the 
        /// token may contain data that is contradictory or not valid, or the token 
        /// may contain unsupported SAML2 elements.
        /// </remarks>
        /// <param name="conditions">SAML 2.0 condition to be validated.</param>
        /// <param name="enforceAudienceRestriction">True to check for Audience Restriction condition.</param>
        protected virtual void ValidateConditions(Saml2Conditions conditions, bool enforceAudienceRestriction)
        {
            if (conditions != null)
            {
                DateTime now = DateTime.UtcNow;

                if (conditions.NotBefore != null
                    && DateTimeUtil.Add(now, Configuration.MaxClockSkew) < conditions.NotBefore.Value)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenNotYetValidException(SR.GetString(SR.ID4147, conditions.NotBefore.Value, now)));
                }

                if (conditions.NotOnOrAfter != null
                    && DateTimeUtil.Add(now, Configuration.MaxClockSkew.Negate()) >= conditions.NotOnOrAfter.Value)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenExpiredException(SR.GetString(SR.ID4148, conditions.NotOnOrAfter.Value, now)));
                }

                if (conditions.OneTimeUse)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenValidationException(SR.GetString(SR.ID4149)));
                }

                if (conditions.ProxyRestriction != null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenValidationException(SR.GetString(SR.ID4150)));
                }
            }

            if (enforceAudienceRestriction)
            {
                if (this.Configuration == null || this.Configuration.AudienceRestriction.AllowedAudienceUris.Count == 0)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ID1032)));
                }

                if (conditions == null || conditions.AudienceRestrictions.Count == 0)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new AudienceUriValidationFailedException(SR.GetString(SR.ID1035)));
                }
                else
                {
                    foreach (Saml2AudienceRestriction audienceRestriction in conditions.AudienceRestrictions)
                    {
                        SamlSecurityTokenRequirement.ValidateAudienceRestriction(this.Configuration.AudienceRestriction.AllowedAudienceUris, audienceRestriction.Audiences);
                    }
                }
            }
        }
コード例 #7
0
        /// <summary>
        /// Creates the conditions for the assertion.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Generally, conditions should be included in assertions to limit the 
        /// impact of misuse of the assertion. Specifying the NotBefore and 
        /// NotOnOrAfter conditions can limit the period of vulnerability in 
        /// the case of a compromised assertion. The AudienceRestrictionCondition
        /// can be used to explicitly state the intended relying party or parties
        /// of the assertion, which coupled with appropriate audience restriction
        /// enforcement at relying parties can help to mitigate spoofing attacks
        /// between relying parties.
        /// </para>
        /// <para>
        /// The default implementation creates NotBefore and NotOnOrAfter conditions
        /// based on the tokenDescriptor.Lifetime. It will also generate an 
        /// AudienceRestrictionCondition limiting consumption of the assertion to 
        /// tokenDescriptor.Scope.Address.
        /// </para>
        /// </remarks>
        /// <param name="tokenLifetime">Lifetime of the Token.</param>
        /// <param name="relyingPartyAddress">The endpoint address to who the token is created. The address
        /// is modeled as an AudienceRestriction condition.</param>
        /// <param name="tokenDescriptor">The token descriptor.</param>
        /// <returns>A Saml2Conditions object.</returns>
        protected virtual Saml2Conditions CreateConditions(Lifetime tokenLifetime, string relyingPartyAddress, SecurityTokenDescriptor tokenDescriptor)
        {
            bool hasLifetime = null != tokenLifetime;
            bool hasScope = !string.IsNullOrEmpty(relyingPartyAddress);
            if (!hasLifetime && !hasScope)
            {
                return null;
            }

            Saml2Conditions conditions = new Saml2Conditions();
            if (hasLifetime)
            {
                conditions.NotBefore = tokenLifetime.Created;
                conditions.NotOnOrAfter = tokenLifetime.Expires;
            }

            if (hasScope)
            {
                conditions.AudienceRestrictions.Add(new Saml2AudienceRestriction(new Uri(relyingPartyAddress)));
            }

            return conditions;
        }
コード例 #8
0
        private void WriteConditionDelegates(XmlWriter writer, Saml2Conditions data)
        {
            const string xsi = "http://www.w3.org/2001/XMLSchema-instance";

            writer.WriteStartElement("Condition", "urn:oasis:names:tc:SAML:2.0:assertion");
            writer.WriteAttributeString("xmlns", "del", "http://www.w3.org/2000/xmlns/", "urn:oasis:names:tc:SAML:2.0:conditions:delegation");
            writer.WriteAttributeString("xmlns", "xsi", "http://www.w3.org/2000/xmlns/", xsi);

            writer.WriteAttributeString("xsi", "type", xsi, "del:DelegationRestrictionType");

            // Check if there are delegates within an incoming assertion
            Saml2ConditionsDelegateWrapper delegateData = data as Saml2ConditionsDelegateWrapper;

            if (delegateData != null && delegateData.Delegates != null)
            {
                // Add the delegates in the DelegationRestrictionType
                foreach (DelegateType del in delegateData.Delegates.Delegate)
                {
                    writer.WriteStartElement("del", "Delegate", "urn:oasis:names:tc:SAML:2.0:conditions:delegation");
                    writer.WriteAttributeString("DelegationInstant", XmlConvert.ToString(del.DelegationInstant, DateTimeFormats.Generated));
                    writer.WriteElementString("NameID", "urn:oasis:names:tc:SAML:2.0:assertion", del.Item.ToString());

                    writer.WriteEndElement();
                }
            }
                    
            // Condition
            writer.WriteEndElement();
        }
コード例 #9
0
        protected override void WriteConditions(XmlWriter writer, Saml2Conditions data)
        {
            if (writer == null)
            {
                throw new ArgumentNullException("writer");
            }
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }

            writer.WriteStartElement("Conditions", "urn:oasis:names:tc:SAML:2.0:assertion");

            if (data.NotBefore.HasValue)
            {
                writer.WriteAttributeString("NotBefore", XmlConvert.ToString(data.NotBefore.Value.ToUniversalTime(), DateTimeFormats.Generated));
            }
            if (data.NotOnOrAfter.HasValue)
            {
                writer.WriteAttributeString("NotOnOrAfter", XmlConvert.ToString(data.NotOnOrAfter.Value.ToUniversalTime(), DateTimeFormats.Generated));
            }
            
            foreach (Saml2AudienceRestriction restriction in data.AudienceRestrictions)
            {
                this.WriteAudienceRestriction(writer, restriction);
            }

            if (data.OneTimeUse)
            {
                writer.WriteStartElement("OneTimeUse", "urn:oasis:names:tc:SAML:2.0:assertion");
                writer.WriteEndElement();
            }

            if (data.ProxyRestriction != null)
            {
                this.WriteProxyRestriction(writer, data.ProxyRestriction);
            }

            // GFIPM S2S 8.8.2.6.d Condition/Delegates
            WriteConditionDelegates(writer, data);

            writer.WriteEndElement();
        }
コード例 #10
0
 /// <summary>
 /// Validate the conditions of the token.
 /// </summary>
 /// <param name="conditions">Conditions to check</param>
 /// <param name="enforceAudienceRestriction">Should the audience restriction be enforced?</param>
 public new void ValidateConditions(Saml2Conditions conditions, bool enforceAudienceRestriction)
 {
     base.ValidateConditions(conditions, enforceAudienceRestriction);
 }