saml2 1.0.1 → 1.0.2

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