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 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