saml2 1.0.5 → 1.0.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b77541aa53787757d03865855dbbb84da27edaba
4
- data.tar.gz: f53032507b4c09f95e1e0f2def917e8760a5f41a
3
+ metadata.gz: 102b176691a071893741f0bf750836e0bc72e8f0
4
+ data.tar.gz: afac3ee0941535c504f75c7b24137f55a1021f27
5
5
  SHA512:
6
- metadata.gz: 2658dc70caec44d8a6b2d8b3e014f419a2887a82a43dc6e2280c1f43437d5d162bc86b9197f144d386709317f4f39b1d692d8bb03d0bd340943fd460ec8d430f
7
- data.tar.gz: 5fcd948501794284e79ba05f8296c4d5e9492f4624210b80fafde2edd760f47de26476bed1f67b8f6e8607c682e5f6e732b40a796ba03a47503c324c8d037cfc
6
+ metadata.gz: 2a982caa3e5e5ac9ad4a392f8b6a680f85e330b0a3ed898a2b9dccf2896f4a282a1aba14e5743466aaac7f4b368ff8b40e75ccb03ef2e89b35c658c9a90b1a16
7
+ data.tar.gz: 251540ba69cc06316961865d9333b5d4da0a8ebcb3c9622039483c87ce222f9e221280087bcfedc36669c77f6539a27716f228fb0218083c6a590c0b7ed51b75
@@ -24,7 +24,7 @@ module SAML2
24
24
 
25
25
  def from_xml(node)
26
26
  # pass through for subclasses
27
- super unless self == Attribute
27
+ return super unless self == Attribute
28
28
 
29
29
  # look for an appropriate subclass
30
30
  klass = class_for(node)
@@ -76,7 +76,6 @@ module SAML2
76
76
  when 1; values.first
77
77
  else; values
78
78
  end
79
- super
80
79
  end
81
80
 
82
81
  private
@@ -128,8 +127,6 @@ module SAML2
128
127
  @attributes = node.xpath('saml:Attribute', Namespaces::ALL).map do |attr|
129
128
  Attribute.from_xml(attr)
130
129
  end
131
-
132
- super
133
130
  end
134
131
 
135
132
  def build(builder)
@@ -12,8 +12,8 @@ module SAML2
12
12
  end
13
13
 
14
14
  def from_xml(node)
15
- @is_required = node['isRequired'] && node['isRequired'] == 'true'
16
15
  super
16
+ @is_required = node['isRequired'] && node['isRequired'] == 'true'
17
17
  end
18
18
 
19
19
  def required?
@@ -47,13 +47,13 @@ module SAML2
47
47
  attr_reader :name, :requested_attributes
48
48
 
49
49
  def initialize(name = nil, requested_attributes = [])
50
+ super()
50
51
  @name, @requested_attributes = name, requested_attributes
51
52
  end
52
53
 
53
54
  def from_xml(node)
54
55
  @name = node['ServiceName']
55
56
  @requested_attributes = load_object_array(node, "md:RequestedAttribute", RequestedAttribute)
56
- super
57
57
  end
58
58
 
59
59
  def create_statement(attributes)
@@ -4,11 +4,12 @@ module SAML2
4
4
  class Base
5
5
  def self.from_xml(node)
6
6
  return nil unless node
7
- new.from_xml(node)
7
+ result = new
8
+ result.from_xml(node)
9
+ result
8
10
  end
9
11
 
10
- def from_xml(node)
11
- self
12
+ def from_xml(_node)
12
13
  end
13
14
 
14
15
  def to_s
@@ -17,7 +18,7 @@ module SAML2
17
18
  end
18
19
 
19
20
  def to_xml
20
- unless @document
21
+ unless instance_variable_defined?(:@document)
21
22
  builder = Nokogiri::XML::Builder.new
22
23
  build(builder)
23
24
  @document = builder.doc
@@ -11,7 +11,7 @@ module SAML2
11
11
 
12
12
  attr_reader :location, :binding
13
13
 
14
- def initialize(location, binding = Bindings::HTTP_POST)
14
+ def initialize(location = nil, binding = Bindings::HTTP_POST)
15
15
  @location, @binding = location, binding
16
16
  end
17
17
 
@@ -22,7 +22,6 @@ module SAML2
22
22
  def from_xml(node)
23
23
  @location = node['Location']
24
24
  @binding = node['Binding']
25
- self
26
25
  end
27
26
 
28
27
  def build(builder, element)
@@ -28,44 +28,91 @@ module SAML2
28
28
 
29
29
  class Group < Array
30
30
  def self.from_xml(node)
31
- node && new(node)
31
+ node && new.from_xml(node)
32
32
  end
33
33
 
34
- def initialize(root)
35
- @root = root
34
+ def initialize
35
+ @valid_until = nil
36
+ end
37
+
38
+ def from_xml(node)
39
+ @root = node
40
+ remove_instance_variable(:@valid_until)
36
41
  replace(Base.load_object_array(@root, "md:EntityDescriptor|md:EntitiesDescriptor",
37
42
  'EntityDescriptor' => Entity,
38
43
  'EntitiesDescriptor' => Group))
39
44
  end
40
45
 
41
46
  def valid_schema?
42
- Schemas.metadata.valid?(@root.document)
47
+ Schemas.federation.valid?(@root.document)
48
+ end
49
+
50
+ def signature
51
+ unless instance_variable_defined?(:@signature)
52
+ @signature = @root.at_xpath('dsig:Signature', Namespaces::ALL)
53
+ signed_node = @signature.at_xpath('dsig:SignedInfo/dsig:Reference', Namespaces::ALL)['URI']
54
+ @root.set_id_attribute('ID')
55
+ @signature = nil unless signed_node == "##{@root['ID']}"
56
+ end
57
+ @signature
58
+ end
59
+
60
+ def signed?
61
+ !!signature
62
+ end
63
+
64
+ def valid_signature?(*args)
65
+ signature.verify_with(*args)
66
+ end
67
+
68
+ def valid_until
69
+ unless instance_variable_defined?(:@valid_until)
70
+ @valid_until = @root['validUntil'] && Time.parse(@root['validUntil'])
71
+ end
72
+ @valid_until
43
73
  end
44
74
  end
45
75
 
46
- def self.from_xml(node)
47
- node && new(node)
76
+ def initialize
77
+ super
78
+ @valid_until = nil
79
+ @entity_id = nil
80
+ @roles = []
48
81
  end
49
82
 
50
- def initialize(root = nil)
83
+ def from_xml(node)
84
+ @root = node
85
+ remove_instance_variable(:@valid_until)
86
+ @roles = nil
51
87
  super
52
- @root = root
53
- unless @root
54
- @roles = []
55
- end
56
88
  end
57
89
 
58
90
  def valid_schema?
59
- Schemas.metadata.valid?(@root.document)
91
+ Schemas.federation.valid?(@root.document)
60
92
  end
61
93
 
62
94
  def entity_id
63
95
  @entity_id || @root && @root['entityID']
64
96
  end
65
97
 
98
+ def valid_until
99
+ unless instance_variable_defined?(:@valid_until)
100
+ @valid_until = @root['validUntil'] && Time.parse(@root['validUntil'])
101
+ end
102
+ @valid_until
103
+ end
104
+
105
+ def identity_providers
106
+ roles.select { |r| r.is_a?(IdentityProvider) }
107
+ end
108
+
109
+ def service_providers
110
+ roles.select { |r| r.is_a?(ServiceProvider) }
111
+ end
112
+
66
113
  def roles
67
- # TODO: load IdPSSODescriptors as well
68
- @roles ||= load_object_array(@root, 'md:SPSSODescriptor', ServiceProvider)
114
+ @roles ||= load_object_array(@root, 'md:IDPSSODescriptor', IdentityProvider) +
115
+ load_object_array(@root, 'md:SPSSODescriptor', ServiceProvider)
69
116
  end
70
117
 
71
118
  def build(builder)
@@ -5,14 +5,20 @@ module SAML2
5
5
  class IdentityProvider < SSO
6
6
  attr_writer :want_authn_requests_signed, :single_sign_on_services, :attribute_profiles, :attributes
7
7
 
8
- def initialize(node = nil)
9
- super(node)
10
- unless node
11
- @want_authn_requests_signed = nil
12
- @single_sign_on_services = []
13
- @attribute_profiles = []
14
- @attributes = []
15
- end
8
+ def initialize
9
+ super
10
+ @want_authn_requests_signed = nil
11
+ @single_sign_on_services = []
12
+ @attribute_profiles = []
13
+ @attributes = []
14
+ end
15
+
16
+ def from_xml(node)
17
+ super
18
+ remove_instance_variable(:@want_authn_requests_signed)
19
+ @single_sign_on_services = nil
20
+ @attribute_profiles = nil
21
+ @attributes = nil
16
22
  end
17
23
 
18
24
  def want_authn_requests_signed?
@@ -4,6 +4,11 @@ module SAML2
4
4
  module IndexedObject
5
5
  attr_reader :index
6
6
 
7
+ def initialize(*args)
8
+ @is_default = nil
9
+ super
10
+ end
11
+
7
12
  def eql?(rhs)
8
13
  index == rhs.index &&
9
14
  default? == rhs.default? &&
@@ -11,7 +16,7 @@ module SAML2
11
16
  end
12
17
 
13
18
  def default?
14
- @is_default
19
+ !!@is_default
15
20
  end
16
21
 
17
22
  def from_xml(node)
@@ -29,6 +29,14 @@ module SAML2
29
29
  use.nil? || use == Type::SIGNING
30
30
  end
31
31
 
32
+ def certificate
33
+ @certificate ||= OpenSSL::X509::Certificate.new(Base64.decode64(x509))
34
+ end
35
+
36
+ def fingerprint
37
+ @fingerprint ||= Digest::SHA1.hexdigest(certificate.to_der).gsub(/(\h{2})(?=\h)/, '\1:')
38
+ end
39
+
32
40
  def build(builder)
33
41
  builder['md'].KeyDescriptor do |builder|
34
42
  builder.parent['use'] = use if use
@@ -5,11 +5,15 @@ module SAML2
5
5
  module OrganizationAndContacts
6
6
  attr_writer :organization, :contacts
7
7
 
8
- def initialize(node = nil)
9
- unless node
10
- @organization = nil
11
- @contacts = []
12
- end
8
+ def initialize
9
+ @organization = nil
10
+ @contacts = []
11
+ end
12
+
13
+ def from_xml(node)
14
+ remove_instance_variable(:@organization)
15
+ @contacts = nil
16
+ super
13
17
  end
14
18
 
15
19
  def organization
@@ -14,14 +14,18 @@ module SAML2
14
14
 
15
15
  attr_writer :supported_protocols, :keys
16
16
 
17
- def initialize(node = nil)
17
+ def initialize
18
+ super
19
+ @supported_protocols = Set.new
20
+ @supported_protocols << Protocols::SAML2
21
+ @keys = []
22
+ end
23
+
24
+ def from_xml(node)
18
25
  super
19
26
  @root = node
20
- unless @root
21
- @supported_protocols = Set.new
22
- @supported_protocols << Protocols::SAML2
23
- @keys = []
24
- end
27
+ @supported_protocols = nil
28
+ @keys = nil
25
29
  end
26
30
 
27
31
  def supported_protocols
@@ -1,5 +1,9 @@
1
1
  module SAML2
2
2
  module Schemas
3
+ def self.federation
4
+ @federation ||= schema('ws-federation.xsd')
5
+ end
6
+
3
7
  def self.metadata
4
8
  @metadata ||= schema('saml-schema-metadata-2.0.xsd')
5
9
  end
@@ -5,14 +5,6 @@ require 'saml2/sso'
5
5
 
6
6
  module SAML2
7
7
  class ServiceProvider < SSO
8
- class << self
9
- alias_method :from_xml, :new
10
- end
11
-
12
- def initialize(root)
13
- @root = root
14
- end
15
-
16
8
  def assertion_consumer_services
17
9
  @assertion_consumer_services ||= begin
18
10
  nodes = @root.xpath('md:AssertionConsumerService', Namespaces::ALL)
@@ -4,12 +4,16 @@ module SAML2
4
4
  class SSO < Role
5
5
  attr_reader :single_logout_services, :name_id_formats
6
6
 
7
- def initialize(node = nil)
7
+ def initialize
8
8
  super
9
- unless node
10
- @single_logout_services = []
11
- @name_id_formats = []
12
- end
9
+ @single_logout_services = []
10
+ @name_id_formats = []
11
+ end
12
+
13
+ def from_xml(node)
14
+ super
15
+ @single_logout_services = nil
16
+ @name_id_formats = nil
13
17
  end
14
18
 
15
19
  def single_logout_services
@@ -1,3 +1,3 @@
1
1
  module SAML2
2
- VERSION = '1.0.5'
2
+ VERSION = '1.0.6'
3
3
  end
@@ -0,0 +1,112 @@
1
+ <?xml version='1.0' encoding='UTF-8' ?>
2
+ <!--
3
+ (c) 2004-2006 BEA Systems Inc., Computer Associates International, Inc.,
4
+ International Business Machines Corporation, Microsoft Corporation,
5
+ Inc., SAP AG, Sun Microsystems, and webMethods. All rights reserved.
6
+
7
+ Permission to copy and display the WS-MetadataExchange Specification
8
+ (the "Specification"), in any medium without fee or royalty is hereby
9
+ granted, provided that you include the following on ALL copies of the
10
+ Specification that you make:
11
+
12
+ 1. A link or URL to the Specification at this location.
13
+ 2. The copyright notice as shown in the Specification.
14
+
15
+ BEA Systems, Computer Associates, IBM, Microsoft, SAP, Sun, and
16
+ webMethods (collectively, the "Authors") each agree to grant you a
17
+ license, under royalty-free and otherwise reasonable,
18
+ non-discriminatory terms and conditions, to their respective essential
19
+ patent claims that they deem necessary to implement the
20
+ WS-MetadataExchange Specification.
21
+
22
+ THE SPECIFICATION IS PROVIDED "AS IS," AND THE AUTHORS MAKE NO
23
+ REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT
24
+ LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
25
+ PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS OF THE
26
+ SPECIFICATION ARE SUITABLE FOR ANY PURPOSE; NOR THAT THE
27
+ IMPLEMENTATION OF SUCH CONTENTS WILL NOT INFRINGE ANY THIRD PARTY
28
+ PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
29
+
30
+ THE AUTHORS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL,
31
+ INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO ANY
32
+ USE OR DISTRIBUTION OF THE SPECIFICATIONS.
33
+
34
+ The name and trademarks of the Authors may NOT be used in any manner,
35
+ including advertising or publicity pertaining to the Specifications or
36
+ their contents without specific, written prior permission. Title to
37
+ copyright in the Specifications will at all times remain with the
38
+ Authors.
39
+
40
+ No other rights are granted by implication, estoppel or otherwise.
41
+ -->
42
+
43
+ <xs:schema
44
+ targetNamespace='http://schemas.xmlsoap.org/ws/2004/09/mex'
45
+ xmlns:tns='http://schemas.xmlsoap.org/ws/2004/09/mex'
46
+ xmlns:wsa10='http://www.w3.org/2005/08/addressing'
47
+ xmlns:wsa04='http://schemas.xmlsoap.org/ws/2004/08/addressing'
48
+ xmlns:xs='http://www.w3.org/2001/XMLSchema'
49
+ elementFormDefault='qualified'
50
+ blockDefault='#all' >
51
+
52
+ <!-- Get Metadata request -->
53
+ <xs:element name='GetMetadata' >
54
+ <xs:complexType>
55
+ <xs:sequence>
56
+ <xs:element ref='tns:Dialect' minOccurs='0' />
57
+ <xs:element ref='tns:Identifier' minOccurs='0' />
58
+ </xs:sequence>
59
+ <xs:anyAttribute namespace='##other' processContents='lax' />
60
+ </xs:complexType>
61
+ </xs:element>
62
+
63
+ <xs:element name='Dialect' type='xs:anyURI' />
64
+ <xs:element name='Identifier' type='xs:anyURI' />
65
+
66
+ <!-- Get Metadata response -->
67
+ <xs:element name='Metadata' >
68
+ <xs:complexType>
69
+ <xs:sequence>
70
+ <xs:element ref='tns:MetadataSection'
71
+ minOccurs='0'
72
+ maxOccurs='unbounded' />
73
+ <xs:any namespace='##other' processContents='lax'
74
+ minOccurs='0'
75
+ maxOccurs='unbounded' />
76
+ </xs:sequence>
77
+ <xs:anyAttribute namespace='##other' processContents='lax' />
78
+ </xs:complexType>
79
+ </xs:element>
80
+
81
+ <xs:element name='MetadataSection' >
82
+ <xs:complexType>
83
+ <xs:choice>
84
+ <xs:any namespace='##other' processContents='lax' />
85
+ <xs:element ref='tns:MetadataReference' />
86
+ <xs:element ref='tns:Location' />
87
+ </xs:choice>
88
+ <xs:attribute name='Dialect' type='xs:anyURI' use='required' />
89
+ <xs:attribute name='Identifier' type='xs:anyURI' />
90
+ <xs:anyAttribute namespace='##other' processContents='lax' />
91
+ </xs:complexType>
92
+ </xs:element>
93
+
94
+ <!--
95
+ Ideally, the type of the MetadataReference would have been
96
+ the union of wsa04:EndpointReferenceType and
97
+ wsa10:EndpointReferenceType but unfortunately xs:union only
98
+ works for simple types. As a result, we have to define
99
+ the mex:MetadataReference using xs:any.
100
+ -->
101
+
102
+ <xs:element name='MetadataReference'>
103
+ <xs:complexType>
104
+ <xs:sequence>
105
+ <xs:any minOccurs='1' maxOccurs='unbounded'
106
+ processContents='lax' namespace='##other' />
107
+ </xs:sequence>
108
+ </xs:complexType>
109
+ </xs:element>
110
+ <xs:element name='Location'
111
+ type='xs:anyURI' />
112
+ </xs:schema>