saml2 1.0.5 → 1.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/saml2/attribute.rb +1 -4
- data/lib/saml2/attribute_consuming_service.rb +2 -2
- data/lib/saml2/base.rb +5 -4
- data/lib/saml2/endpoint.rb +1 -2
- data/lib/saml2/entity.rb +61 -14
- data/lib/saml2/identity_provider.rb +14 -8
- data/lib/saml2/indexed_object.rb +6 -1
- data/lib/saml2/key.rb +8 -0
- data/lib/saml2/organization_and_contacts.rb +9 -5
- data/lib/saml2/role.rb +10 -6
- data/lib/saml2/schemas.rb +4 -0
- data/lib/saml2/service_provider.rb +0 -8
- data/lib/saml2/sso.rb +9 -5
- data/lib/saml2/version.rb +1 -1
- data/schemas/MetadataExchange.xsd +112 -0
- data/schemas/oasis-200401-wss-wssecurity-secext-1.0.xsd +195 -0
- data/schemas/oasis-200401-wss-wssecurity-utility-1.0.xsd +108 -0
- data/schemas/ws-addr.xsd +137 -0
- data/schemas/ws-authorization.xsd +145 -0
- data/schemas/ws-federation.xsd +471 -0
- data/schemas/ws-securitypolicy-1.2.xsd +1205 -0
- data/spec/fixtures/FederationMetadata.xml +670 -0
- data/spec/fixtures/identity_provider.xml +45 -0
- data/spec/lib/entity_spec.rb +4 -0
- data/spec/lib/identity_provider_spec.rb +14 -0
- data/spec/lib/service_provider_spec.rb +1 -1
- metadata +18 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 102b176691a071893741f0bf750836e0bc72e8f0
|
4
|
+
data.tar.gz: afac3ee0941535c504f75c7b24137f55a1021f27
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2a982caa3e5e5ac9ad4a392f8b6a680f85e330b0a3ed898a2b9dccf2896f4a282a1aba14e5743466aaac7f4b368ff8b40e75ccb03ef2e89b35c658c9a90b1a16
|
7
|
+
data.tar.gz: 251540ba69cc06316961865d9333b5d4da0a8ebcb3c9622039483c87ce222f9e221280087bcfedc36669c77f6539a27716f228fb0218083c6a590c0b7ed51b75
|
data/lib/saml2/attribute.rb
CHANGED
@@ -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)
|
data/lib/saml2/base.rb
CHANGED
@@ -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
|
7
|
+
result = new
|
8
|
+
result.from_xml(node)
|
9
|
+
result
|
8
10
|
end
|
9
11
|
|
10
|
-
def from_xml(
|
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
|
21
|
+
unless instance_variable_defined?(:@document)
|
21
22
|
builder = Nokogiri::XML::Builder.new
|
22
23
|
build(builder)
|
23
24
|
@document = builder.doc
|
data/lib/saml2/endpoint.rb
CHANGED
@@ -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)
|
data/lib/saml2/entity.rb
CHANGED
@@ -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
|
35
|
-
@
|
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.
|
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
|
47
|
-
|
76
|
+
def initialize
|
77
|
+
super
|
78
|
+
@valid_until = nil
|
79
|
+
@entity_id = nil
|
80
|
+
@roles = []
|
48
81
|
end
|
49
82
|
|
50
|
-
def
|
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.
|
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
|
-
|
68
|
-
|
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
|
9
|
-
super
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
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?
|
data/lib/saml2/indexed_object.rb
CHANGED
@@ -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
|
-
|
19
|
+
!!@is_default
|
15
20
|
end
|
16
21
|
|
17
22
|
def from_xml(node)
|
data/lib/saml2/key.rb
CHANGED
@@ -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
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|
data/lib/saml2/role.rb
CHANGED
@@ -14,14 +14,18 @@ module SAML2
|
|
14
14
|
|
15
15
|
attr_writer :supported_protocols, :keys
|
16
16
|
|
17
|
-
def initialize
|
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
|
-
|
21
|
-
|
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
|
data/lib/saml2/schemas.rb
CHANGED
@@ -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)
|
data/lib/saml2/sso.rb
CHANGED
@@ -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
|
7
|
+
def initialize
|
8
8
|
super
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|
data/lib/saml2/version.rb
CHANGED
@@ -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>
|