saml2 1.0.1 → 1.0.2

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: 5b7d46d26e196c43de38dbea14bf3be6bbd0e212
4
- data.tar.gz: 4eb34e5bec906dff3f6ebb748ec13f4aeee113da
3
+ metadata.gz: 314105963831ad59d852c507bdd5a6d5e9144735
4
+ data.tar.gz: 6b913cac8cf8b4df318e3896a11f1ef583325a36
5
5
  SHA512:
6
- metadata.gz: 22b0948988e9aa48b0919f9df1e1831e84bc6f15cedd8a820e3e844232302e1a7e538b4a576d067048c3bb5ba8ec314a6eec54422eb80d76c5c2aa050da7f311
7
- data.tar.gz: 4564507cda91f5aea94e4b7102ac433c27b80de8b889416e0a8c5b9f94ed1c99aab5dc87880a6b289e84ba86249bb7d89d2d4669eae8ad7797175134c7d34f8d
6
+ metadata.gz: c8483963f3dde271d6a61dbfb812a1a91dc5054296eac2aa69369f6148b228b1283031fac1dc17e6131fecbd97ceade0e2a826a50b49a22a15b0dab47e83e4ea
7
+ data.tar.gz: 0602173e8d090329e2d9b950affde276c20e409914c99f7a0ddae878b25352682fa33b0538269897865fc765de668016036e104e4c8f2727f9fc7187f365a118
@@ -1,12 +1,15 @@
1
+ require 'saml2/conditions'
2
+
1
3
  module SAML2
2
4
  class Assertion
3
- attr_reader :id, :issue_instant, :statements
5
+ attr_reader :id, :issue_instant, :conditions, :statements
4
6
  attr_accessor :issuer, :subject
5
7
 
6
8
  def initialize
7
9
  @id = "_#{SecureRandom.uuid}"
8
10
  @issue_instant = Time.now.utc
9
11
  @statements = []
12
+ @conditions = Conditions.new
10
13
  end
11
14
 
12
15
  def sign(x509_certificate, private_key, algorithm_name = :sha256)
@@ -33,6 +36,7 @@ module SAML2
33
36
 
34
37
  subject.build(builder)
35
38
 
39
+ conditions.build(builder)
36
40
  statements.each { |stmt| stmt.build(builder) }
37
41
  end
38
42
  end.doc.root
@@ -0,0 +1,74 @@
1
+ module SAML2
2
+ class Conditions < Array
3
+ attr_accessor :not_before, :not_on_or_after
4
+
5
+ def valid?(options = {})
6
+ now = options[:now] || Time.now
7
+ return :invalid if not_before && now < not_before
8
+ return :invalid if not_on_or_after && now >= not_on_or_after
9
+
10
+ result = :valid
11
+ each do |condition|
12
+ this_result = condition.valid?(options)
13
+ case this_result
14
+ when :invalid
15
+ return :invalid
16
+ when :indeterminate
17
+ result = :indeterminate
18
+ when :valid
19
+ else
20
+ raise "unknown validity of #{condition}"
21
+ end
22
+ end
23
+ result
24
+ end
25
+
26
+ def build(builder)
27
+ builder['saml'].Conditions do |builder|
28
+ builder.parent['NotBefore'] = not_before.iso8601 if not_before
29
+ builder.parent['NotOnOrAfter'] = not_on_or_after.iso8601 if not_on_or_after
30
+
31
+ each do |condition|
32
+ condition.build(builder)
33
+ end
34
+ end
35
+ end
36
+
37
+ # Any unknown condition
38
+ class Condition
39
+ def valid?(_)
40
+ :indeterminate
41
+ end
42
+ end
43
+
44
+ class AudienceRestriction < Condition
45
+ attr_accessor :audience
46
+
47
+ def initialize(audience)
48
+ @audience = audience
49
+ end
50
+
51
+ def valid?(options)
52
+ Array(audience).include?(options[:audience]) ? :valid : :invalid
53
+ end
54
+
55
+ def build(builder)
56
+ builder['saml'].AudienceRestriction do |builder|
57
+ Array(audience).each do |single_audience|
58
+ builder['saml'].Audience(single_audience)
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ class OneTimeUse < Condition
65
+ def valid?(_)
66
+ :valid
67
+ end
68
+
69
+ def build(builder)
70
+ builder['saml'].OneTimeUse
71
+ end
72
+ end
73
+ end
74
+ end
@@ -27,6 +27,8 @@ module SAML2
27
27
  statement = authn_request.attribute_consuming_service.create_statement(attributes)
28
28
  response.assertions.first.statements << statement if statement
29
29
  end
30
+ response.assertions.first.conditions << Conditions::AudienceRestriction.new(authn_request.issuer.id)
31
+
30
32
  response
31
33
  end
32
34
 
@@ -42,6 +44,8 @@ module SAML2
42
44
  assertion.subject.confirmation.not_on_or_after = Time.now.utc + 30
43
45
  assertion.subject.confirmation.recipient = response.destination if response.destination
44
46
  assertion.issuer = issuer
47
+ assertion.conditions.not_before = Time.now.utc - 5
48
+ assertion.conditions.not_on_or_after = Time.now.utc + 30
45
49
  authn_statement = AuthnStatement.new
46
50
  authn_statement.authn_instant = response.issue_instant
47
51
  authn_statement.authn_context_class_ref = AuthnStatement::Classes::UNSPECIFIED
@@ -1,3 +1,3 @@
1
1
  module SAML2
2
- VERSION = '1.0.1'
2
+ VERSION = '1.0.2'
3
3
  end
@@ -9,15 +9,15 @@
9
9
  <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
10
10
  </Transforms>
11
11
  <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
12
- <DigestValue>dRjiJ4yQ4ujjWB87gOoYZ5sYaUVJc0SSH2YzWwH+Z4Y=</DigestValue>
12
+ <DigestValue>HFJ1RMKtE+J23K/mQqdClLWsdjwboU9M+uTX+PcN/LU=</DigestValue>
13
13
  </Reference>
14
14
  </SignedInfo>
15
- <SignatureValue>jJYv2J8bXQSnDT48bb3/K2iV/gIUDGC5w+Q4HJ9MAPBuyhupHDTCb1XwrjJHurx0
16
- QLxo8RqgIeZKDj0bKiy8zdVn2+9SX6bHYOl4Ca0lNVHE0vum2nlZwsfLALf2oBpo
17
- fr11sln9SXlHbI+6tcd9j49uUjIj5jpPWdY6jEwoOTLMcsVdrxwpxAF1USDSGEpI
18
- omFtlxj0sdfo+0VwjPkdlDL3Cl66uTa2t1ZXJxY4dXqzyFyuRsfEBe4FtXYvo0g9
19
- GuAW2UCuMhXzGl+CJHAfIG9yYPe+YTE7HOy8t+OteHkN6ZalI5CW53zmGQs3oMWQ
20
- QOgTrVgJMSDhFZqpoIvVLg==</SignatureValue>
15
+ <SignatureValue>oRUU3idevSgM2QCidYqLAL5Ki2H8qxvkIVw9yNrbv9Mg2D7126wPMerWyKeP+ops
16
+ 6ploHMV0MQRyEFA+4PJ3ZsBU1daVSt3plh+6Szm5zIhWUEc3HhvQirv5IP1lfcxQ
17
+ IopKnpiZkH9QMLolCLMIfCbOIuIfmssmsEagU/S3aoRVgZLA/x15z2hNEiB+tMqr
18
+ Elc7i5V81ztnEx47yJhf/mAiZcnLqpnbpJ9XN4NF43QSgkRNU4vCQsx0zA6gj9MB
19
+ D5h/CKy7KMn+LtaLkHIfv6Y//xN+61PrQ7sr5FIsCGg9XBvXC3PrwEVdADx4/dZO
20
+ JrJ/DBFeEc8K1KSMXm5qrQ==</SignatureValue>
21
21
  <KeyInfo>
22
22
  <X509Data>
23
23
  <X509Certificate>MIID+jCCAuKgAwIBAgIJAIz/He5UafnhMA0GCSqGSIb3DQEBBQUAMFsxCzAJBgNV
@@ -44,4 +44,4 @@ Cg8Yo62X9vWW6PaKXHs3N+g1Ig16NwjdVIYvcxLc2KY0vrqu/R5c8RbmCxMZyss9
44
44
  ZtltN+yN40INHGRWnHc=</X509Certificate>
45
45
  </X509Data>
46
46
  </KeyInfo>
47
- </Signature><saml:Subject><saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">jacob</saml:NameID><saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData NotOnOrAfter="2015-02-12T22:54:29Z" Recipient="https://siteadmin.test.instructure.com/saml_consume" InResponseTo="_bec424fa5103428909a30ff1e31168327f79474984"/></saml:SubjectConfirmation></saml:Subject><saml:AuthnStatement AuthnInstant="2015-02-12T22:51:29Z"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement></saml:Assertion></samlp:Response>
47
+ </Signature><saml:Subject><saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">jacob</saml:NameID><saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData NotOnOrAfter="2015-02-12T22:54:29Z" Recipient="https://siteadmin.test.instructure.com/saml_consume" InResponseTo="_bec424fa5103428909a30ff1e31168327f79474984"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore="2015-02-12T22:51:24Z" NotOnOrAfter="2015-02-12T22:51:59Z"><saml:AudienceRestriction><saml:Audience>http://siteadmin.instructure.com/saml2</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant="2015-02-12T22:51:29Z"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement></saml:Assertion></samlp:Response>
@@ -9,15 +9,15 @@
9
9
  <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
10
10
  </Transforms>
11
11
  <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
12
- <DigestValue>cNsW8tqrcA6HB+H8gOA5bAswPLLyN8tH9j53exrhfjU=</DigestValue>
12
+ <DigestValue>b9jIvyyPEhWc/kHYHUA8LTCz4pwYSRCE+CL+SNqmiEk=</DigestValue>
13
13
  </Reference>
14
14
  </SignedInfo>
15
- <SignatureValue>JuL8PNrAiqNODwMa94qvvJMPEpjFG0yAbd58Rj7iUTeiAYE+26k9xRvYTsF3z3Va
16
- Xt3yOBZFoOt40AwKiZ3sqPnCM5GrBtrApcRcBoxBYwr/2bSGfhoIxO1Y51VHBOTM
17
- SoBkLUNJAPI6YJtJF2CZJA1Gv92/n/PMvQFDK2LHN/0Jbcy8ebvg1q/Wu9vJIgcY
18
- TIan4wrByBQHX16CNR+JDrdBIxe/GKI+6GzGsRr+V9CgLRdyvpevFLYFmmn1gOx7
19
- gLypwLteGo0eX5nclwVD0N6GjqUpW8eYGPFUiErgZp36DZBXy9sCT8Pz1h35daXs
20
- 8dfw7cO59iYT4vSDFqIE6A==</SignatureValue>
15
+ <SignatureValue>eHHTFNYA1VNbzFOtsoTGn4A+BXdKFXHfJNvWWU52L1kBUfCyeFNVLby03yQRw+CO
16
+ 71JomuTy/jpWU50h27sOfXjWjPkiULRHNPWuDIglrOgnUpu2HeD+i9IoA69/vF9J
17
+ Bmwm2IubzhBAxc70Dm/oXZ238bN0E+c2u4B9jp6MdVXSL7RDmfKAU19ABAZlYTmJ
18
+ 4xXlS0fjrGPOn+BszBR9BNLDvNST/MgaGmwAU0esP5dYzC0Pwi9lOGD5bO+MOxTp
19
+ TBx9e0KY3BTEVVOxl8G6M8w9nx5mnKMgHpPq5P/uMHv7m8gUVdMQ8lDvPqyEibPw
20
+ ABIureP4iKebJVl7JTeoYA==</SignatureValue>
21
21
  <KeyInfo>
22
22
  <X509Data>
23
23
  <X509Certificate>MIID+jCCAuKgAwIBAgIJAIz/He5UafnhMA0GCSqGSIb3DQEBBQUAMFsxCzAJBgNV
@@ -44,4 +44,4 @@ Cg8Yo62X9vWW6PaKXHs3N+g1Ig16NwjdVIYvcxLc2KY0vrqu/R5c8RbmCxMZyss9
44
44
  ZtltN+yN40INHGRWnHc=</X509Certificate>
45
45
  </X509Data>
46
46
  </KeyInfo>
47
- </Signature><saml:Subject><saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">jacob</saml:NameID><saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData NotOnOrAfter="2015-02-12T22:54:29Z" Recipient="https://siteadmin.test.instructure.com/saml_consume" InResponseTo="_bec424fa5103428909a30ff1e31168327f79474984"/></saml:SubjectConfirmation></saml:Subject><saml:AuthnStatement AuthnInstant="2015-02-12T22:51:29Z"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><saml:Attribute xmlns:x500="urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500" Name="urn:oid:2.5.4.42" FriendlyName="givenName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" x500:Encoding="LDAP"><saml:AttributeValue xsi:type="xsd:string">cody</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion></samlp:Response>
47
+ </Signature><saml:Subject><saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">jacob</saml:NameID><saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData NotOnOrAfter="2015-02-12T22:54:29Z" Recipient="https://siteadmin.test.instructure.com/saml_consume" InResponseTo="_bec424fa5103428909a30ff1e31168327f79474984"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore="2015-02-12T22:51:24Z" NotOnOrAfter="2015-02-12T22:51:59Z"><saml:AudienceRestriction><saml:Audience>http://siteadmin.instructure.com/saml2</saml:Audience></saml:AudienceRestriction></saml:Conditions><saml:AuthnStatement AuthnInstant="2015-02-12T22:51:29Z"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement><saml:AttributeStatement xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><saml:Attribute xmlns:x500="urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500" Name="urn:oid:2.5.4.42" FriendlyName="givenName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri" x500:Encoding="LDAP"><saml:AttributeValue xsi:type="xsd:string">cody</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion></samlp:Response>
@@ -0,0 +1,69 @@
1
+ require_relative '../spec_helper'
2
+
3
+ module SAML2
4
+ describe Conditions do
5
+ it "empty should be valid" do
6
+ Conditions.new.valid?.must_equal :valid
7
+ end
8
+
9
+ it "should be valid with unknown condition" do
10
+ conditions = Conditions.new
11
+ conditions << Conditions::Condition.new
12
+ conditions.valid?.must_equal :indeterminate
13
+ end
14
+
15
+ it "should be valid with timestamps" do
16
+ conditions = Conditions.new
17
+ now = Time.now.utc
18
+ conditions.not_before = now - 5
19
+ conditions.not_on_or_after = now + 30
20
+ conditions.valid?.must_equal :valid
21
+ end
22
+
23
+ it "should be invalid with out of range timestamps" do
24
+ conditions = Conditions.new
25
+ now = Time.now.utc
26
+ conditions.not_before = now - 35
27
+ conditions.not_on_or_after = now - 5
28
+ conditions.valid?.must_equal :invalid
29
+ end
30
+
31
+ it "should allow passing now" do
32
+ conditions = Conditions.new
33
+ now = Time.now.utc
34
+ conditions.not_before = now - 35
35
+ conditions.not_on_or_after = now - 5
36
+ conditions.valid?(now: now - 10).must_equal :valid
37
+ end
38
+
39
+ it "should be invalid before indeterminate" do
40
+ conditions = Conditions.new
41
+ now = Time.now.utc
42
+ conditions.not_before = now + 5
43
+ conditions << Conditions::Condition.new
44
+ conditions.valid?.must_equal :invalid
45
+ end
46
+
47
+ it "should be invalid before indeterminate (actual conditions)" do
48
+ conditions = Conditions.new
49
+ conditions << Conditions::Condition.new
50
+ conditions << Conditions::AudienceRestriction.new('audience')
51
+ conditions.valid?.must_equal :invalid
52
+ end
53
+
54
+ end
55
+
56
+ describe Conditions::AudienceRestriction do
57
+ it "should be invalid" do
58
+ Conditions::AudienceRestriction.new('expected').valid?(audience: 'actual').must_equal :invalid
59
+ end
60
+
61
+ it "should be valid" do
62
+ Conditions::AudienceRestriction.new('expected').valid?(audience: 'expected').must_equal :valid
63
+ end
64
+
65
+ it "should be valid with an array" do
66
+ Conditions::AudienceRestriction.new(['expected', 'actual']).valid?(audience: 'actual').must_equal :valid
67
+ end
68
+ end
69
+ end
@@ -28,6 +28,8 @@ module SAML2
28
28
  assertion.instance_variable_set(:@id, "_cdfc3faf-90ad-462f-880d-677483210684")
29
29
  response.instance_variable_set(:@issue_instant, Time.parse("2015-02-12T22:51:29Z"))
30
30
  assertion.instance_variable_set(:@issue_instant, Time.parse("2015-02-12T22:51:29Z"))
31
+ assertion.conditions.not_before = Time.parse("2015-02-12T22:51:24Z")
32
+ assertion.conditions.not_on_or_after = Time.parse("2015-02-12T22:51:59Z")
31
33
  assertion.statements.first.authn_instant = Time.parse("2015-02-12T22:51:29Z")
32
34
  confirmation = assertion.subject.confirmation
33
35
  confirmation.not_on_or_after = Time.parse("2015-02-12T22:54:29Z")
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.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cody Cutrer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-24 00:00:00.000000000 Z
11
+ date: 2015-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -102,6 +102,7 @@ files:
102
102
  - lib/saml2/authn_request.rb
103
103
  - lib/saml2/authn_statement.rb
104
104
  - lib/saml2/base.rb
105
+ - lib/saml2/conditions.rb
105
106
  - lib/saml2/contact.rb
106
107
  - lib/saml2/endpoint.rb
107
108
  - lib/saml2/engine.rb
@@ -139,6 +140,7 @@ files:
139
140
  - spec/lib/attribute_consuming_service_spec.rb
140
141
  - spec/lib/attribute_spec.rb
141
142
  - spec/lib/authn_request_spec.rb
143
+ - spec/lib/conditions_spec.rb
142
144
  - spec/lib/entity_spec.rb
143
145
  - spec/lib/identity_provider_spec.rb
144
146
  - spec/lib/indexed_object_spec.rb
@@ -182,6 +184,7 @@ test_files:
182
184
  - spec/lib/attribute_consuming_service_spec.rb
183
185
  - spec/lib/attribute_spec.rb
184
186
  - spec/lib/authn_request_spec.rb
187
+ - spec/lib/conditions_spec.rb
185
188
  - spec/lib/entity_spec.rb
186
189
  - spec/lib/identity_provider_spec.rb
187
190
  - spec/lib/indexed_object_spec.rb