saml2 1.0.4 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/saml2/attribute.rb +34 -14
- data/lib/saml2/attribute_consuming_service.rb +4 -2
- data/lib/saml2/base.rb +18 -0
- data/lib/saml2/conditions.rb +4 -2
- data/lib/saml2/namespaces.rb +9 -7
- data/lib/saml2/version.rb +1 -1
- data/spec/fixtures/response_with_attribute_signed.xml +8 -8
- data/spec/lib/attribute_spec.rb +67 -9
- metadata +22 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: b77541aa53787757d03865855dbbb84da27edaba
         | 
| 4 | 
            +
              data.tar.gz: f53032507b4c09f95e1e0f2def917e8760a5f41a
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 2658dc70caec44d8a6b2d8b3e014f419a2887a82a43dc6e2280c1f43437d5d162bc86b9197f144d386709317f4f39b1d692d8bb03d0bd340943fd460ec8d430f
         | 
| 7 | 
            +
              data.tar.gz: 5fcd948501794284e79ba05f8296c4d5e9492f4624210b80fafde2edd760f47de26476bed1f67b8f6e8607c682e5f6e732b40a796ba03a47503c324c8d037cfc
         | 
    
        data/lib/saml2/attribute.rb
    CHANGED
    
    | @@ -1,5 +1,7 @@ | |
| 1 1 | 
             
            require 'date'
         | 
| 2 2 |  | 
| 3 | 
            +
            require 'active_support/core_ext/array/wrap'
         | 
| 4 | 
            +
             | 
| 3 5 | 
             
            require 'saml2/base'
         | 
| 4 6 | 
             
            require 'saml2/namespaces'
         | 
| 5 7 |  | 
| @@ -53,7 +55,7 @@ module SAML2 | |
| 53 55 | 
             
                  builder['saml'].Attribute('Name' => name) do |builder|
         | 
| 54 56 | 
             
                    builder.parent['FriendlyName'] = friendly_name if friendly_name
         | 
| 55 57 | 
             
                    builder.parent['NameFormat'] = name_format if name_format
         | 
| 56 | 
            -
                    Array(value).each do | | 
| 58 | 
            +
                    Array.wrap(value).each do |value|
         | 
| 57 59 | 
             
                      xsi_type, val = convert_to_xsi(value)
         | 
| 58 60 | 
             
                      builder['saml'].AttributeValue(val) do |builder|
         | 
| 59 61 | 
             
                        builder.parent['xsi:type'] = xsi_type if xsi_type
         | 
| @@ -67,7 +69,7 @@ module SAML2 | |
| 67 69 | 
             
                  @friendly_name = node['FriendlyName']
         | 
| 68 70 | 
             
                  @name_format = node['NameFormat']
         | 
| 69 71 | 
             
                  values = node.xpath('saml:AttributeValue', Namespaces::ALL).map do |node|
         | 
| 70 | 
            -
                    convert_from_xsi(node | 
| 72 | 
            +
                    convert_from_xsi(node.attribute_with_ns('type', Namespaces::XSI), node.content && node.content.strip)
         | 
| 71 73 | 
             
                  end
         | 
| 72 74 | 
             
                  @value = case values.length
         | 
| 73 75 | 
             
                           when 0; nil
         | 
| @@ -78,27 +80,36 @@ module SAML2 | |
| 78 80 | 
             
                end
         | 
| 79 81 |  | 
| 80 82 | 
             
                private
         | 
| 81 | 
            -
                 | 
| 82 | 
            -
             | 
| 83 | 
            -
                     | 
| 83 | 
            +
                XS_TYPES = {
         | 
| 84 | 
            +
                  lookup_qname('xs:boolean', Namespaces::ALL) =>
         | 
| 85 | 
            +
                    [[TrueClass, FalseClass], nil, ->(v) { %w{true 1}.include?(v) ? true : false }],
         | 
| 86 | 
            +
                  lookup_qname('xs:string', Namespaces::ALL) =>
         | 
| 87 | 
            +
                    [String, nil, nil],
         | 
| 88 | 
            +
                  lookup_qname('xs:date', Namespaces::ALL) =>
         | 
| 89 | 
            +
                    [Date, nil, ->(v) { Date.parse(v) if v }],
         | 
| 90 | 
            +
                  lookup_qname('xs:dateTime', Namespaces::ALL) =>
         | 
| 91 | 
            +
                    [Time, ->(v) { v.iso8601 }, ->(v) { Time.parse(v) if v }]
         | 
| 84 92 | 
             
                }.freeze
         | 
| 85 93 |  | 
| 86 94 | 
             
                def convert_to_xsi(value)
         | 
| 87 | 
            -
                   | 
| 95 | 
            +
                  xs_type = nil
         | 
| 88 96 | 
             
                  converter = nil
         | 
| 89 | 
            -
                   | 
| 90 | 
            -
                    if klass === value
         | 
| 91 | 
            -
                       | 
| 97 | 
            +
                  XS_TYPES.each do |type, (klasses, to_xsi, _from_xsi)|
         | 
| 98 | 
            +
                    if Array.wrap(klasses).any? { |klass| klass === value }
         | 
| 99 | 
            +
                      xs_type = "xs:#{type.last}"
         | 
| 92 100 | 
             
                      converter = to_xsi
         | 
| 93 101 | 
             
                      break
         | 
| 94 102 | 
             
                    end
         | 
| 95 103 | 
             
                  end
         | 
| 96 104 | 
             
                  value = converter.call(value) if converter
         | 
| 97 | 
            -
                  [ | 
| 105 | 
            +
                  [xs_type, value]
         | 
| 98 106 | 
             
                end
         | 
| 99 107 |  | 
| 100 108 | 
             
                def convert_from_xsi(type, value)
         | 
| 101 | 
            -
                   | 
| 109 | 
            +
                  return value unless type
         | 
| 110 | 
            +
                  qname = self.class.lookup_qname(type.value, type.namespaces)
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                  info = XS_TYPES[qname]
         | 
| 102 113 | 
             
                  if info && info.last
         | 
| 103 114 | 
             
                    value = info.last.call(value)
         | 
| 104 115 | 
             
                  end
         | 
| @@ -106,15 +117,24 @@ module SAML2 | |
| 106 117 | 
             
                end
         | 
| 107 118 | 
             
              end
         | 
| 108 119 |  | 
| 109 | 
            -
              class AttributeStatement
         | 
| 120 | 
            +
              class AttributeStatement < Base
         | 
| 110 121 | 
             
                attr_reader :attributes
         | 
| 111 122 |  | 
| 112 | 
            -
                def initialize(attributes)
         | 
| 123 | 
            +
                def initialize(attributes = [])
         | 
| 113 124 | 
             
                  @attributes = attributes
         | 
| 114 125 | 
             
                end
         | 
| 115 126 |  | 
| 127 | 
            +
                def from_xml(node)
         | 
| 128 | 
            +
                  @attributes = node.xpath('saml:Attribute', Namespaces::ALL).map do |attr|
         | 
| 129 | 
            +
                    Attribute.from_xml(attr)
         | 
| 130 | 
            +
                  end
         | 
| 131 | 
            +
             | 
| 132 | 
            +
                  super
         | 
| 133 | 
            +
                end
         | 
| 134 | 
            +
             | 
| 116 135 | 
             
                def build(builder)
         | 
| 117 | 
            -
                  builder['saml'].AttributeStatement('xmlns: | 
| 136 | 
            +
                  builder['saml'].AttributeStatement('xmlns:xs' => Namespaces::XS,
         | 
| 137 | 
            +
                                                     'xmlns:xsi' => Namespaces::XSI) do |builder|
         | 
| 118 138 | 
             
                    @attributes.each { |attr| attr.build(builder) }
         | 
| 119 139 | 
             
                  end
         | 
| 120 140 | 
             
                end
         | 
| @@ -1,3 +1,5 @@ | |
| 1 | 
            +
            require 'active_support/core_ext/array/wrap'
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            require 'saml2/attribute'
         | 
| 2 4 | 
             
            require 'saml2/indexed_object'
         | 
| 3 5 | 
             
            require 'saml2/namespaces'
         | 
| @@ -34,7 +36,7 @@ module SAML2 | |
| 34 36 | 
             
                def initialize(requested_attribute, provided_value)
         | 
| 35 37 | 
             
                  super("Attribute #{requested_attribute.name} is provided value " \
         | 
| 36 38 | 
             
                    "#{provided_value.inspect}, but only allows "                  \
         | 
| 37 | 
            -
                    "#{Array(requested_attribute.value).inspect}")
         | 
| 39 | 
            +
                    "#{Array.wrap(requested_attribute.value).inspect}")
         | 
| 38 40 | 
             
                  @requested_attribute, @provided_value = requested_attribute, provided_value
         | 
| 39 41 | 
             
                end
         | 
| 40 42 | 
             
              end
         | 
| @@ -76,7 +78,7 @@ module SAML2 | |
| 76 78 | 
             
                    end
         | 
| 77 79 | 
             
                    if attr
         | 
| 78 80 | 
             
                      if requested_attr.value &&
         | 
| 79 | 
            -
                        !Array(requested_attr.value).include?(attr.value)
         | 
| 81 | 
            +
                        !Array.wrap(requested_attr.value).include?(attr.value)
         | 
| 80 82 | 
             
                        raise InvalidAttributeValue.new(requested_attr, attr.value)
         | 
| 81 83 | 
             
                      end
         | 
| 82 84 | 
             
                      attributes << attr
         | 
    
        data/lib/saml2/base.rb
    CHANGED
    
    | @@ -41,6 +41,11 @@ module SAML2 | |
| 41 41 | 
             
                  end
         | 
| 42 42 | 
             
                end
         | 
| 43 43 |  | 
| 44 | 
            +
                def self.lookup_qname(qname, namespaces)
         | 
| 45 | 
            +
                  prefix, local_name = split_qname(qname)
         | 
| 46 | 
            +
                  [lookup_namespace(prefix, namespaces), local_name]
         | 
| 47 | 
            +
                end
         | 
| 48 | 
            +
             | 
| 44 49 | 
             
                protected
         | 
| 45 50 | 
             
                def load_string_array(node, element)
         | 
| 46 51 | 
             
                  self.class.load_string_array(node, element)
         | 
| @@ -49,5 +54,18 @@ module SAML2 | |
| 49 54 | 
             
                def load_object_array(node, element, klass)
         | 
| 50 55 | 
             
                  self.class.load_object_array(node, element, klass)
         | 
| 51 56 | 
             
                end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                def self.split_qname(qname)
         | 
| 59 | 
            +
                  if qname.include?(':')
         | 
| 60 | 
            +
                    qname.split(':', 2)
         | 
| 61 | 
            +
                  else
         | 
| 62 | 
            +
                    [nil, qname]
         | 
| 63 | 
            +
                  end
         | 
| 64 | 
            +
                end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                def self.lookup_namespace(prefix, namespaces)
         | 
| 67 | 
            +
                  return nil if namespaces.empty?
         | 
| 68 | 
            +
                  namespaces[prefix.empty? ? 'xmlns' : "xmlns:#{prefix}"]
         | 
| 69 | 
            +
                end
         | 
| 52 70 | 
             
              end
         | 
| 53 71 | 
             
            end
         | 
    
        data/lib/saml2/conditions.rb
    CHANGED
    
    | @@ -1,3 +1,5 @@ | |
| 1 | 
            +
            require 'active_support/core_ext/array/wrap'
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            module SAML2
         | 
| 2 4 | 
             
              class Conditions < Array
         | 
| 3 5 | 
             
                attr_accessor :not_before, :not_on_or_after
         | 
| @@ -49,12 +51,12 @@ module SAML2 | |
| 49 51 | 
             
                  end
         | 
| 50 52 |  | 
| 51 53 | 
             
                  def valid?(options)
         | 
| 52 | 
            -
                    Array(audience).include?(options[:audience]) ? :valid : :invalid
         | 
| 54 | 
            +
                    Array.wrap(audience).include?(options[:audience]) ? :valid : :invalid
         | 
| 53 55 | 
             
                  end
         | 
| 54 56 |  | 
| 55 57 | 
             
                  def build(builder)
         | 
| 56 58 | 
             
                    builder['saml'].AudienceRestriction do |builder|
         | 
| 57 | 
            -
                      Array(audience).each do |single_audience|
         | 
| 59 | 
            +
                      Array.wrap(audience).each do |single_audience|
         | 
| 58 60 | 
             
                        builder['saml'].Audience(single_audience)
         | 
| 59 61 | 
             
                      end
         | 
| 60 62 | 
             
                    end
         | 
    
        data/lib/saml2/namespaces.rb
    CHANGED
    
    | @@ -5,17 +5,19 @@ module SAML2 | |
| 5 5 | 
             
                SAML     = "urn:oasis:names:tc:SAML:2.0:assertion".freeze
         | 
| 6 6 | 
             
                SAMLP    = "urn:oasis:names:tc:SAML:2.0:protocol".freeze
         | 
| 7 7 | 
             
                XENC     = "http://www.w3.org/2001/04/xmlenc#".freeze
         | 
| 8 | 
            +
                XS       = "http://www.w3.org/2001/XMLSchema".freeze
         | 
| 8 9 | 
             
                XSI      = "http://www.w3.org/2001/XMLSchema-instance".freeze
         | 
| 9 10 | 
             
                X500     = "urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500".freeze
         | 
| 10 11 |  | 
| 11 12 | 
             
                ALL = {
         | 
| 12 | 
            -
                    'dsig'  => DSIG,
         | 
| 13 | 
            -
                    'md'    => METADATA,
         | 
| 14 | 
            -
                    'saml'  => SAML,
         | 
| 15 | 
            -
                    'samlp' => SAMLP,
         | 
| 16 | 
            -
                    'x500'  => X500,
         | 
| 17 | 
            -
                    'xenc'  => XENC,
         | 
| 18 | 
            -
                    ' | 
| 13 | 
            +
                    'xmlns:dsig'  => DSIG,
         | 
| 14 | 
            +
                    'xmlns:md'    => METADATA,
         | 
| 15 | 
            +
                    'xmlns:saml'  => SAML,
         | 
| 16 | 
            +
                    'xmlns:samlp' => SAMLP,
         | 
| 17 | 
            +
                    'xmlns:x500'  => X500,
         | 
| 18 | 
            +
                    'xmlns:xenc'  => XENC,
         | 
| 19 | 
            +
                    'xmlns:xs'    => XS,
         | 
| 20 | 
            +
                    'xmlns:xsi'   => XSI,
         | 
| 19 21 | 
             
                }.freeze
         | 
| 20 22 | 
             
              end
         | 
| 21 23 | 
             
            end
         | 
    
        data/lib/saml2/version.rb
    CHANGED
    
    
| @@ -9,15 +9,15 @@ | |
| 9 9 | 
             
            <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
         | 
| 10 10 | 
             
            </Transforms>
         | 
| 11 11 | 
             
            <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
         | 
| 12 | 
            -
            <DigestValue> | 
| 12 | 
            +
            <DigestValue>PTIbPIph/60z5i+AdxU32f7w2jiAD904pC3QNTs263E=</DigestValue>
         | 
| 13 13 | 
             
            </Reference>
         | 
| 14 14 | 
             
            </SignedInfo>
         | 
| 15 | 
            -
            <SignatureValue> | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 15 | 
            +
            <SignatureValue>BmxWVd1P+2L/qJgV5RYoktBkkXHamXHa4JAX7O2M6GSlCN9qwWaPe5fLqCcpNaMs
         | 
| 16 | 
            +
            HLQF/cNEsY0ntgKlxI231Q6p/+ZYUwzMXXBTixYHgMzwvtqMwRLIP60c/oI3pQTY
         | 
| 17 | 
            +
            420Psr3WmZMnpmouQB9fcSwO33BbppbMv2mwHaVp00BvQcnwS4SU1wr1XCSKr4kc
         | 
| 18 | 
            +
            TocP7R7zK+2FlVJB5wPzgUo9kIbjRTupVj6NOKjjp42Gv8GRg+fY02JZ98zaOnJk
         | 
| 19 | 
            +
            PCNICiQpxsN5XWYxfdtsHRpES/Y36lPYkIPDmJhuTxmKoTl0apq9Pg4m9oM6RRQW
         | 
| 20 | 
            +
            zI1YBtwCWrEjk8eW/Wrz3w==</SignatureValue>
         | 
| 21 21 | 
             
            <KeyInfo>
         | 
| 22 22 | 
             
            <X509Data>
         | 
| 23 23 | 
             
            <X509Certificate>MIID+jCCAuKgAwIBAgIJAIz/He5UafnhMA0GCSqGSIb3DQEBBQUAMFsxCzAJBgNV
         | 
| @@ -44,4 +44,4 @@ Cg8Yo62X9vWW6PaKXHs3N+g1Ig16NwjdVIYvcxLc2KY0vrqu/R5c8RbmCxMZyss9 | |
| 44 44 | 
             
            ZtltN+yN40INHGRWnHc=</X509Certificate>
         | 
| 45 45 | 
             
            </X509Data>
         | 
| 46 46 | 
             
            </KeyInfo>
         | 
| 47 | 
            -
            </Signature><saml:Subject><saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">jacob</saml:NameID><saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData NotOnOrAfter="2015-02-12T22:54:29Z" Recipient="https://siteadmin.test.instructure.com/saml_consume" InResponseTo="_bec424fa5103428909a30ff1e31168327f79474984"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore="2015-02-12T22:51:24Z" NotOnOrAfter="2015-02-12T22:51:59Z"><saml:AudienceRestriction><saml:Audience>http://siteadmin.instructure.com/saml2</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant="2015-02-12T22:51:29Z"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><saml:Attribute xmlns:x500="urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500" Name="urn:oid:2.5.4.42" FriendlyName="givenName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" x500:Encoding="LDAP"><saml:AttributeValue xsi:type=" | 
| 47 | 
            +
            </Signature><saml:Subject><saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">jacob</saml:NameID><saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData NotOnOrAfter="2015-02-12T22:54:29Z" Recipient="https://siteadmin.test.instructure.com/saml_consume" InResponseTo="_bec424fa5103428909a30ff1e31168327f79474984"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore="2015-02-12T22:51:24Z" NotOnOrAfter="2015-02-12T22:51:59Z"><saml:AudienceRestriction><saml:Audience>http://siteadmin.instructure.com/saml2</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant="2015-02-12T22:51:29Z"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><saml:Attribute xmlns:x500="urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500" Name="urn:oid:2.5.4.42" FriendlyName="givenName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" x500:Encoding="LDAP"><saml:AttributeValue xsi:type="xs:string">cody</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion></samlp:Response>
         | 
    
        data/spec/lib/attribute_spec.rb
    CHANGED
    
    | @@ -2,9 +2,19 @@ require_relative '../spec_helper' | |
| 2 2 |  | 
| 3 3 | 
             
            module SAML2
         | 
| 4 4 | 
             
              describe Attribute do
         | 
| 5 | 
            +
                def serialize(attribute)
         | 
| 6 | 
            +
                  doc = Nokogiri::XML::Builder.new do |builder|
         | 
| 7 | 
            +
                    builder['saml'].Root('xmlns:saml' => Namespaces::SAML) do |builder|
         | 
| 8 | 
            +
                      attribute.build(builder)
         | 
| 9 | 
            +
                      builder.parent.child['xmlns:saml'] = Namespaces::SAML
         | 
| 10 | 
            +
                    end
         | 
| 11 | 
            +
                  end.doc
         | 
| 12 | 
            +
                  doc.root.child.to_s
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 5 15 | 
             
                let(:eduPersonPrincipalNameXML) { <<XML.strip
         | 
| 6 16 | 
             
            <saml:Attribute xmlns:x500="urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500" Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.6" FriendlyName="eduPersonPrincipalName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" x500:Encoding="LDAP" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
         | 
| 7 | 
            -
              <saml:AttributeValue xsi:type=" | 
| 17 | 
            +
              <saml:AttributeValue xsi:type="xs:string">user@domain</saml:AttributeValue>
         | 
| 8 18 | 
             
            </saml:Attribute>
         | 
| 9 19 | 
             
            XML
         | 
| 10 20 | 
             
              }
         | 
| @@ -26,14 +36,62 @@ XML | |
| 26 36 | 
             
                  attr.friendly_name.must_equal 'eduPersonPrincipalName'
         | 
| 27 37 | 
             
                  attr.name_format.must_equal Attribute::NameFormats::URI
         | 
| 28 38 |  | 
| 29 | 
            -
                   | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 39 | 
            +
                  serialize(attr).must_equal eduPersonPrincipalNameXML
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                it "should parse and serialize boolean values" do
         | 
| 43 | 
            +
                  xml = <<XML.strip
         | 
| 44 | 
            +
            <saml:AttributeStatement xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
         | 
| 45 | 
            +
              <saml:Attribute Name="attr">
         | 
| 46 | 
            +
                <saml:AttributeValue xsi:type="xs:boolean">1</saml:AttributeValue>
         | 
| 47 | 
            +
              </saml:Attribute>
         | 
| 48 | 
            +
            </saml:AttributeStatement>
         | 
| 49 | 
            +
            XML
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                  stmt = AttributeStatement.from_xml(Nokogiri::XML(xml).root)
         | 
| 52 | 
            +
                  stmt.attributes.first.value.must_equal true
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                  # serializes canonically
         | 
| 55 | 
            +
                  serialize(stmt).must_equal(xml.sub('>1<', '>true<'))
         | 
| 37 56 | 
             
                end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                it "should parse and serialize dateTime values" do
         | 
| 59 | 
            +
                  xml = <<XML.strip
         | 
| 60 | 
            +
            <saml:AttributeStatement xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
         | 
| 61 | 
            +
              <saml:Attribute Name="attr">
         | 
| 62 | 
            +
                <saml:AttributeValue xsi:type="xs:dateTime">2015-06-29T18:37:03Z</saml:AttributeValue>
         | 
| 63 | 
            +
              </saml:Attribute>
         | 
| 64 | 
            +
            </saml:AttributeStatement>
         | 
| 65 | 
            +
            XML
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                  stmt = AttributeStatement.from_xml(Nokogiri::XML(xml).root)
         | 
| 68 | 
            +
                  stmt.attributes.first.value.must_equal Time.at(1435603023)
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                  # serializes canonically
         | 
| 71 | 
            +
                  serialize(stmt).must_equal(xml)
         | 
| 72 | 
            +
                end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                it "should parse values with different namespace prefixes" do
         | 
| 75 | 
            +
                  xml = <<XML.strip
         | 
| 76 | 
            +
            <saml:Attribute Name="attr" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xssi="http://www.w3.org/2001/XMLSchema-instance">
         | 
| 77 | 
            +
              <saml:AttributeValue xssi:type="xsd:boolean">0</saml:AttributeValue>
         | 
| 78 | 
            +
            </saml:Attribute>
         | 
| 79 | 
            +
            XML
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                  attr = Attribute.from_xml(Nokogiri::XML(xml).root)
         | 
| 82 | 
            +
                  attr.value.must_equal false
         | 
| 83 | 
            +
                end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                it "should parse untagged values" do
         | 
| 86 | 
            +
                  xml = <<XML.strip
         | 
| 87 | 
            +
            <saml:Attribute Name="attr" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
         | 
| 88 | 
            +
              <saml:AttributeValue>something</saml:AttributeValue>
         | 
| 89 | 
            +
            </saml:Attribute>
         | 
| 90 | 
            +
            XML
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                  attr = Attribute.from_xml(Nokogiri::XML(xml).root)
         | 
| 93 | 
            +
                  attr.value.must_equal "something"
         | 
| 94 | 
            +
                end
         | 
| 95 | 
            +
             | 
| 38 96 | 
             
              end
         | 
| 39 97 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: saml2
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1.0. | 
| 4 | 
            +
              version: 1.0.5
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Cody Cutrer
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2015- | 
| 11 | 
            +
            date: 2015-07-01 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: nokogiri
         | 
| @@ -50,6 +50,26 @@ dependencies: | |
| 50 50 | 
             
                - - ">="
         | 
| 51 51 | 
             
                  - !ruby/object:Gem::Version
         | 
| 52 52 | 
             
                    version: 0.9.2
         | 
| 53 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 54 | 
            +
              name: activesupport
         | 
| 55 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 56 | 
            +
                requirements:
         | 
| 57 | 
            +
                - - ">="
         | 
| 58 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 59 | 
            +
                    version: '3.2'
         | 
| 60 | 
            +
                - - "<"
         | 
| 61 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 62 | 
            +
                    version: '5.0'
         | 
| 63 | 
            +
              type: :runtime
         | 
| 64 | 
            +
              prerelease: false
         | 
| 65 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 66 | 
            +
                requirements:
         | 
| 67 | 
            +
                - - ">="
         | 
| 68 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 69 | 
            +
                    version: '3.2'
         | 
| 70 | 
            +
                - - "<"
         | 
| 71 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 72 | 
            +
                    version: '5.0'
         | 
| 53 73 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 54 74 | 
             
              name: rake
         | 
| 55 75 | 
             
              requirement: !ruby/object:Gem::Requirement
         |