saml2 1.1.0 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/saml2/authn_request.rb +63 -17
- data/lib/saml2/name_id.rb +33 -11
- data/lib/saml2/requested_authn_context.rb +16 -0
- data/lib/saml2/subject.rb +9 -9
- data/lib/saml2/version.rb +1 -1
- data/spec/lib/authn_request_spec.rb +18 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 788b9842bac7051e976ef2a7360d488f2a0249e1
|
4
|
+
data.tar.gz: 4c654aedef625b8c7ac918775158174406b570cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 70b0409bc9a42a6c4786f5de2c3dfc09a18dc518e290fe450f3874695876c8f3ffb41e4baa59e0850c1af43a8f1aecc6a0978ec047f18c7d8b7d9407e5c6beb4
|
7
|
+
data.tar.gz: 802adedaadd6e2c033b4d6c7ec4e9d97fd7426bc8e7244ccd253cddbe89762466c03d59e0af98b7ca33f021abf42b8b1337ba537d703cd3e4e00bf4a2f78acf2
|
data/lib/saml2/authn_request.rb
CHANGED
@@ -7,6 +7,7 @@ require 'saml2/endpoint'
|
|
7
7
|
require 'saml2/name_id'
|
8
8
|
require 'saml2/namespaces'
|
9
9
|
require 'saml2/request'
|
10
|
+
require 'saml2/requested_authn_context'
|
10
11
|
require 'saml2/schemas'
|
11
12
|
require 'saml2/subject'
|
12
13
|
|
@@ -21,13 +22,14 @@ module SAML2
|
|
21
22
|
AuthnRequest.from_xml(Nokogiri::XML('<xml></xml>').root)
|
22
23
|
end
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
25
|
+
attr_writer :assertion_consumer_service_index,
|
26
|
+
:assertion_consumer_service_url,
|
27
|
+
:attribute_consuming_service_index,
|
28
|
+
:force_authn,
|
29
|
+
:name_id_policy,
|
30
|
+
:passive,
|
31
|
+
:protocol_binding
|
32
|
+
attr_accessor :requested_authn_context
|
31
33
|
|
32
34
|
def valid_web_browser_sso_profile?
|
33
35
|
return false unless issuer
|
@@ -64,37 +66,81 @@ module SAML2
|
|
64
66
|
end
|
65
67
|
|
66
68
|
def name_id_policy
|
67
|
-
|
69
|
+
if xml && !instance_variable_defined?(:@name_id_policy)
|
70
|
+
@name_id_policy = NameID::Policy.from_xml(xml.at_xpath('samlp:NameIDPolicy', Namespaces::ALL))
|
71
|
+
end
|
72
|
+
@name_id_policy
|
68
73
|
end
|
69
74
|
|
70
75
|
attr_reader :assertion_consumer_service, :attribute_consuming_service
|
71
76
|
|
72
|
-
def
|
73
|
-
xml
|
77
|
+
def assertion_consumer_service_index
|
78
|
+
if xml && !instance_variable_defined?(:@assertion_consumer_service_index)
|
79
|
+
@assertion_consumer_service_index = xml['AssertionConsumerServiceIndex']&.to_i
|
80
|
+
end
|
81
|
+
@assertion_consumer_service_index
|
74
82
|
end
|
75
83
|
|
76
|
-
def
|
77
|
-
xml
|
84
|
+
def assertion_consumer_service_url
|
85
|
+
if xml && !instance_variable_defined?(:@assertion_consumer_service_url)
|
86
|
+
@assertion_consumer_service_url = xml['AssertionConsumerServiceURL']
|
87
|
+
end
|
88
|
+
@assertion_consumer_service_url
|
78
89
|
end
|
79
90
|
|
80
91
|
def attribute_consuming_service_index
|
81
|
-
xml
|
92
|
+
if xml && !instance_variable_defined?(:@attribute_consuming_service_index)
|
93
|
+
@attribute_consuming_service_index = xml['AttributeConsumingServiceIndex']&.to_i
|
94
|
+
end
|
95
|
+
@attribute_consuming_service_index
|
82
96
|
end
|
83
97
|
|
84
98
|
def force_authn?
|
85
|
-
xml
|
99
|
+
if xml && !instance_variable_defined?(:@force_authn)
|
100
|
+
@force_authn = xml['ForceAuthn']&.== 'true'
|
101
|
+
end
|
102
|
+
@force_authn
|
86
103
|
end
|
87
104
|
|
88
105
|
def passive?
|
89
|
-
xml
|
106
|
+
if xml && !instance_variable_defined?(:@passive)
|
107
|
+
@passive = xml['IsPassive']&.== 'true'
|
108
|
+
end
|
109
|
+
@passive
|
90
110
|
end
|
91
111
|
|
92
112
|
def protocol_binding
|
93
|
-
xml
|
113
|
+
if xml && !instance_variable_defined?(:@protocol_binding)
|
114
|
+
@protocol_binding = xml['ProtocolBinding']
|
115
|
+
end
|
116
|
+
@protocol_binding
|
94
117
|
end
|
95
118
|
|
96
119
|
def subject
|
97
|
-
|
120
|
+
if xml && !instance_variable_defined?(:@subject)
|
121
|
+
@subject = Subject.from_xml(xml.at_xpath('saml:Subject', Namespaces::ALL))
|
122
|
+
end
|
123
|
+
@subject
|
124
|
+
end
|
125
|
+
|
126
|
+
def build(builder)
|
127
|
+
builder['samlp'].AuthnRequest(
|
128
|
+
'xmlns:samlp' => Namespaces::SAMLP,
|
129
|
+
'xmlns:saml' => Namespaces::SAML
|
130
|
+
) do |authn_request|
|
131
|
+
super(authn_request)
|
132
|
+
|
133
|
+
authn_request.parent['AssertionConsumerServiceIndex'] = assertion_consumer_service_index if assertion_consumer_service_index
|
134
|
+
authn_request.parent['AssertionConsumerServiceURL'] = assertion_consumer_service_url if assertion_consumer_service_url
|
135
|
+
authn_request.parent['AttributeConsumingServiceIndex'] = attribute_consuming_service_index if attribute_consuming_service_index
|
136
|
+
authn_request.parent['ForceAuthn'] = force_authn? unless force_authn?.nil?
|
137
|
+
authn_request.parent['IsPassive'] = passive? unless passive?.nil?
|
138
|
+
authn_request.parent['ProtocolBinding'] = protocol_binding if protocol_binding
|
139
|
+
|
140
|
+
subject.build(authn_request) if subject
|
141
|
+
name_id_policy.build(authn_request) if name_id_policy
|
142
|
+
requested_authn_context.build(authn_request) if requested_authn_context
|
143
|
+
end
|
98
144
|
end
|
99
145
|
end
|
100
146
|
end
|
data/lib/saml2/name_id.rb
CHANGED
@@ -13,26 +13,48 @@ module SAML2
|
|
13
13
|
X509_SUBJECT_NAME = "urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName".freeze
|
14
14
|
end
|
15
15
|
|
16
|
-
class Policy
|
17
|
-
|
16
|
+
class Policy < Base
|
17
|
+
attr_writer :allow_create, :format, :sp_name_qualifier
|
18
18
|
|
19
|
-
def
|
20
|
-
if
|
21
|
-
|
22
|
-
|
19
|
+
def initialize(allow_create = nil, format = nil, sp_name_qualifier = nil)
|
20
|
+
@allow_create = allow_create if allow_create
|
21
|
+
@format = format if format
|
22
|
+
@sp_name_qualifier = sp_name_qualifier if sp_name_qualifier
|
23
|
+
end
|
24
|
+
|
25
|
+
def allow_create?
|
26
|
+
if xml && !instance_variable_defined?(:@allow_create)
|
27
|
+
@allow_create = xml['AllowCreate']&.== 'true'
|
23
28
|
end
|
29
|
+
@allow_create
|
24
30
|
end
|
25
31
|
|
26
|
-
def
|
27
|
-
|
32
|
+
def format
|
33
|
+
if xml && !instance_variable_defined?(:@format)
|
34
|
+
@format = xml['Format']
|
35
|
+
end
|
36
|
+
@format
|
28
37
|
end
|
29
38
|
|
30
|
-
def
|
31
|
-
|
39
|
+
def sp_name_qualifier
|
40
|
+
if xml && !instance_variable_defined?(:@sp_name_qualifier)
|
41
|
+
@sp_name_qualifier = xml['SPNameQualifier']
|
42
|
+
end
|
43
|
+
@sp_name_qualifier
|
32
44
|
end
|
33
45
|
|
34
46
|
def ==(rhs)
|
35
|
-
|
47
|
+
allow_create? == rhs.allow_create? &&
|
48
|
+
format == rhs.format &&
|
49
|
+
sp_name_qualifier == rhs.sp_name_qualifier
|
50
|
+
end
|
51
|
+
|
52
|
+
def build(builder)
|
53
|
+
builder['samlp'].NameIDPolicy do |name_id_policy|
|
54
|
+
name_id_policy.parent['Format'] = format if format
|
55
|
+
name_id_policy.parent['SPNameQualifier'] = sp_name_qualifier if sp_name_qualifier
|
56
|
+
name_id_policy.parent['AllowCreate'] = allow_create? unless allow_create?.nil?
|
57
|
+
end
|
36
58
|
end
|
37
59
|
end
|
38
60
|
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'saml2/base'
|
2
|
+
|
3
|
+
module SAML2
|
4
|
+
class RequestedAuthnContext < Base
|
5
|
+
attr_accessor :comparison, :class_ref
|
6
|
+
|
7
|
+
def build(builder)
|
8
|
+
builder['samlp'].RequestedAuthnContext do |requested_authn_context|
|
9
|
+
requested_authn_context.parent['Comparison'] = comparison.to_s if comparison
|
10
|
+
Array(class_ref).each do |individual_class_ref|
|
11
|
+
requested_authn_context['saml'].AuthnContextClassRef(individual_class_ref)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/saml2/subject.rb
CHANGED
@@ -2,15 +2,15 @@ require 'saml2/name_id'
|
|
2
2
|
require 'saml2/namespaces'
|
3
3
|
|
4
4
|
module SAML2
|
5
|
-
class Subject
|
6
|
-
|
5
|
+
class Subject < Base
|
6
|
+
attr_writer :name_id
|
7
|
+
attr_accessor :confirmation
|
7
8
|
|
8
|
-
def
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
subject
|
9
|
+
def name_id
|
10
|
+
if xml && !instance_variable_defined?(:@name_id)
|
11
|
+
@name_id = NameID.from_xml(node.at_xpath('saml:NameID', Namespaces::ALL))
|
12
|
+
end
|
13
|
+
@name_id
|
14
14
|
end
|
15
15
|
|
16
16
|
def build(builder)
|
@@ -20,7 +20,7 @@ module SAML2
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
class Confirmation
|
23
|
+
class Confirmation < Base
|
24
24
|
module Methods
|
25
25
|
BEARER = 'urn:oasis:names:tc:SAML:2.0:cm:bearer'.freeze
|
26
26
|
HOLDER_OF_KEY = 'urn:oasis:names:tc:SAML:2.0:cm:holder-of-key'.freeze
|
data/lib/saml2/version.rb
CHANGED
@@ -42,7 +42,24 @@ module SAML2
|
|
42
42
|
end
|
43
43
|
|
44
44
|
it "should find the NameID policy" do
|
45
|
-
expect(request.name_id_policy).to eq NameID::Policy.new(true, NameID::Format::PERSISTENT)
|
45
|
+
expect(request.name_id_policy).to eq NameID::Policy.new(true, NameID::Format::PERSISTENT, "moodle.bridge.feide.no")
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'serializes valid XML' do
|
49
|
+
authn_request = AuthnRequest.new
|
50
|
+
authn_request.issuer = NameID.new("entity")
|
51
|
+
authn_request.protocol_binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
|
52
|
+
authn_request.assertion_consumer_service_url = 'https://somewhere/'
|
53
|
+
authn_request.name_id_policy = NameID::Policy.new(true, NameID::Format::UNSPECIFIED)
|
54
|
+
authn_request.requested_authn_context = RequestedAuthnContext.new
|
55
|
+
authn_request.requested_authn_context.class_ref = "urn:oasis:names:tc:SAML:2.0:ac:classes:Password"
|
56
|
+
authn_request.requested_authn_context.comparison = :exact
|
57
|
+
authn_request.passive = true
|
58
|
+
xml = authn_request.to_s
|
59
|
+
authn_request = AuthnRequest.parse(xml)
|
60
|
+
expect(authn_request).to be_valid_schema
|
61
|
+
expect(authn_request.force_authn?).to eq nil
|
62
|
+
expect(authn_request.passive?).to eq true
|
46
63
|
end
|
47
64
|
end
|
48
65
|
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.1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cody Cutrer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-06-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -59,7 +59,7 @@ dependencies:
|
|
59
59
|
version: '3.2'
|
60
60
|
- - "<"
|
61
61
|
- !ruby/object:Gem::Version
|
62
|
-
version: '5.
|
62
|
+
version: '5.2'
|
63
63
|
type: :runtime
|
64
64
|
prerelease: false
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -69,7 +69,7 @@ dependencies:
|
|
69
69
|
version: '3.2'
|
70
70
|
- - "<"
|
71
71
|
- !ruby/object:Gem::Version
|
72
|
-
version: '5.
|
72
|
+
version: '5.2'
|
73
73
|
- !ruby/object:Gem::Dependency
|
74
74
|
name: byebug
|
75
75
|
requirement: !ruby/object:Gem::Requirement
|
@@ -154,6 +154,7 @@ files:
|
|
154
154
|
- lib/saml2/organization.rb
|
155
155
|
- lib/saml2/organization_and_contacts.rb
|
156
156
|
- lib/saml2/request.rb
|
157
|
+
- lib/saml2/requested_authn_context.rb
|
157
158
|
- lib/saml2/response.rb
|
158
159
|
- lib/saml2/role.rb
|
159
160
|
- lib/saml2/schemas.rb
|