saml2 1.1.0 → 1.1.1

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: 382418cbc200bcf81a58ff09ebadd551d0c16101
4
- data.tar.gz: 0f7318a0d65eb9b80afbe0405d6dc768cc4e3f0d
3
+ metadata.gz: 788b9842bac7051e976ef2a7360d488f2a0249e1
4
+ data.tar.gz: 4c654aedef625b8c7ac918775158174406b570cd
5
5
  SHA512:
6
- metadata.gz: 0b0462631aa2d2c0208655bf85e8a104555034176df8825f42029f1356a745d07f561f15a5c78719e8a1400eb70063cc89c6014abaf226a3294d5a6a0aa319c1
7
- data.tar.gz: c1ad828d647e905e3e92e4e34c2e4856a370fe32abf9bfe337e344dd34e46a95b9d344f5c3cd7542a1636a068febad623af0a83ee2cc524d7c0e74eb7cb8a61e
6
+ metadata.gz: 70b0409bc9a42a6c4786f5de2c3dfc09a18dc518e290fe450f3874695876c8f3ffb41e4baa59e0850c1af43a8f1aecc6a0978ec047f18c7d8b7d9407e5c6beb4
7
+ data.tar.gz: 802adedaadd6e2c033b4d6c7ec4e9d97fd7426bc8e7244ccd253cddbe89762466c03d59e0af98b7ca33f021abf42b8b1337ba537d703cd3e4e00bf4a2f78acf2
@@ -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
- def valid_schema?
25
- return false unless super
26
- # Check for the correct root element
27
- return false unless xml.at_xpath('/samlp:AuthnRequest', Namespaces::ALL)
28
-
29
- true
30
- end
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
- @name_id_policy ||= NameID::Policy.from_xml(xml.at_xpath('samlp:NameIDPolicy', Namespaces::ALL))
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 assertion_consumer_service_url
73
- xml['AssertionConsumerServiceURL']
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 assertion_consumer_service_index
77
- xml['AssertionConsumerServiceIndex'] && xml['AssertionConsumerServiceIndex'].to_i
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['AttributeConsumerServiceIndex'] && xml['AttributeConsumerServiceIndex'].to_i
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['ForceAuthn']
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['IsPassive']
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['ProtocolBinding']
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
- @subject ||= Subject.from_xml(xml.at_xpath('saml:Subject', Namespaces::ALL))
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
@@ -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
- attr_reader :format
16
+ class Policy < Base
17
+ attr_writer :allow_create, :format, :sp_name_qualifier
18
18
 
19
- def self.from_xml(node)
20
- if node
21
- allow_create = node['AllowCreate'].nil? ? nil : node['AllowCreate'] == 'true'
22
- NameID::Policy.new(allow_create, node['Format'])
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 initialize(allow_create, format)
27
- @allow_create, @format = allow_create, format
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 allow_create?
31
- @allow_create
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
- format == rhs.format && allow_create? == rhs.allow_create?
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
@@ -2,15 +2,15 @@ require 'saml2/name_id'
2
2
  require 'saml2/namespaces'
3
3
 
4
4
  module SAML2
5
- class Subject
6
- attr_accessor :name_id, :confirmation
5
+ class Subject < Base
6
+ attr_writer :name_id
7
+ attr_accessor :confirmation
7
8
 
8
- def self.from_xml(node)
9
- return nil unless node
10
- subject = new
11
- subject.name_id = NameID.from_xml(node.at_xpath('saml:NameID', Namespaces::ALL))
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
@@ -1,3 +1,3 @@
1
1
  module SAML2
2
- VERSION = '1.1.0'
2
+ VERSION = '1.1.1'
3
3
  end
@@ -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.0
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-05-02 00:00:00.000000000 Z
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.1'
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.1'
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