information_card 0.1.0

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.
@@ -0,0 +1,95 @@
1
+ # Portions of this class were inspired by the XML::Util::XmlCanonicalizer class written by Roland Schmitt
2
+
3
+ module InformationCard
4
+ include REXML
5
+
6
+ class XmlCanonicalizer
7
+ def initialize
8
+ @canonicalized_xml = ''
9
+ end
10
+
11
+ def canonicalize(element)
12
+ document = REXML::Document.new(element.to_s)
13
+
14
+ #TODO: Do we need this check?
15
+ if element.instance_of?(REXML::Element)
16
+ namespace = element.namespace(element.prefix)
17
+ if not namespace.empty?
18
+ if not element.prefix.empty?
19
+ document.root.add_namespace(element.prefix, namespace)
20
+ else
21
+ document.root.add_namespace(namespace)
22
+ end
23
+ end
24
+ end
25
+
26
+ document.each_child{ |node| write_node(node) }
27
+
28
+ @canonicalized_xml.strip
29
+ end
30
+
31
+ private
32
+
33
+ def write_node(node)
34
+ case node.node_type
35
+ when :text
36
+ write_text(node)
37
+ when :element
38
+ write_element(node)
39
+ end
40
+ end
41
+
42
+ def write_text(node)
43
+ if node.value.strip.empty?
44
+ @canonicalized_xml << node.value
45
+ else
46
+ @canonicalized_xml << normalize_whitespace(node.value)
47
+ end
48
+ end
49
+
50
+ def write_element(node)
51
+ @canonicalized_xml << "<#{node.expanded_name}"
52
+ write_namespaces(node)
53
+ write_attributes(node)
54
+ @canonicalized_xml << ">"
55
+ node.each_child{ |child| write_node(child) }
56
+ @canonicalized_xml << "</#{node.expanded_name}>"
57
+ end
58
+
59
+ def write_namespaces(node)
60
+ @processed_prefixes ||= []
61
+
62
+ prefixes = ["xmlns"] + node.prefixes.uniq
63
+
64
+ prefixes.sort!.each do |prefix|
65
+ namespace = node.namespace(prefix)
66
+
67
+ unless prefix.empty? or (prefix == 'xmlns' and namespace.empty?) or @processed_prefixes.include?(prefix)
68
+ @processed_prefixes << prefix
69
+
70
+ @canonicalized_xml << " "
71
+ @canonicalized_xml << "xmlns:" if not prefix == 'xmlns'
72
+ @canonicalized_xml << normalize_whitespace("#{prefix}=\"#{namespace}\"")
73
+ end
74
+ end
75
+ end
76
+
77
+ def write_attributes(node)
78
+ attributes = []
79
+
80
+ node.attributes.sort.each do |key, attribute|
81
+ attributes << attribute if not attribute.prefix =~ /^xmlns/
82
+ end
83
+
84
+ attributes.each do |attribute|
85
+ unless attribute.nil? or attribute.name == "xmlns"
86
+ @canonicalized_xml << " #{attribute.name}=\"#{normalize_whitespace(attribute.to_s)}\""
87
+ end
88
+ end
89
+ end
90
+
91
+ def normalize_whitespace(input)
92
+ input.gsub(/\s+/, ' ').strip
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,21 @@
1
+ require 'test_helper'
2
+
3
+ class CertificateUtilTest < Test::Unit::TestCase
4
+ include InformationCard
5
+
6
+ def setup
7
+ @cert_directory = File.join(File.dirname(__FILE__), "fixtures/certificates")
8
+ end
9
+
10
+ def test_private_key_from_certificate_subject
11
+ expected_private_key_content = File.read(File.join(@cert_directory, "test.key"))
12
+ private_key = CertificateUtil.lookup_private_key(@cert_directory, '/O=testinformationcardruby.com/CN=testinformationcardruby.com')
13
+ assert_equal expected_private_key_content, private_key.to_s
14
+ end
15
+
16
+ def test_should_raise_exception_if_certificate_not_found
17
+ assert_raises("No private key found in ./test/fixtures/certificates/ with subject not_exist") do
18
+ CertificateUtil.lookup_private_key(@cert_directory, 'not_exist')
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,39 @@
1
+ require 'test_helper'
2
+
3
+ class ClaimTypesTest < Test::Unit::TestCase
4
+ include InformationCard
5
+
6
+ def test_map_should_return_specified_claims
7
+ expected_claims = ["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mobilephone",
8
+ "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier"];
9
+ actual_claims = ClaimTypes.map([:mobile_phone, :ppid])
10
+ assert_equal_arrays(expected_claims, actual_claims) {|x,y| x <=> y}
11
+ end
12
+
13
+ def test_map_should_raise_exception_if_uknown_claim_specified
14
+ assert_raises("Undefined claim fraggles") do
15
+ ClaimTypes.map([:fraggles])
16
+ end
17
+ end
18
+
19
+ def test_map_should_throw_exception_when_no_claim_types_specified
20
+ expected_claims = [];
21
+ actual_claims = ClaimTypes.map([])
22
+ assert_equal_arrays(expected_claims, actual_claims) {|x,y| x <=> y}
23
+ end
24
+
25
+ def test_lookup_claim_by_attribute_name_and_namespace
26
+ assert_equal :given_name, ClaimTypes.lookup("http://schemas.xmlsoap.org/ws/2005/05/identity/claims", "givenname")
27
+ assert_equal :webpage, ClaimTypes.lookup("http://schemas.xmlsoap.org/ws/2005/05/identity/claims", "webpage")
28
+ end
29
+
30
+ def test_lookup_should_raise_exception_if_claim_not_found
31
+ assert_raises("Undefined claim http://schemas.xmlsoap.org/ws/2005/05/identity/claims/fraggles") do
32
+ ClaimTypes.lookup("http://schemas.xmlsoap.org/ws/2005/05/identity/claims", "fraggles")
33
+ end
34
+ end
35
+
36
+ def test_lookup_should_remove_attribute_name_from_namespace_if_present
37
+ assert_equal :email_address, ClaimTypes.lookup("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", "emailaddress")
38
+ end
39
+ end
@@ -0,0 +1,12 @@
1
+ require 'test_helper'
2
+
3
+ class DecrypterTest < Test::Unit::TestCase
4
+ include InformationCard
5
+
6
+ def test_should_decrypt_encrypted_xml_token_into_saml_token
7
+ decrypter = Decrypter.new(
8
+ load_encrypted_information_card('john_smith.xml'),certificates_directory,
9
+ '/O=testinformationcardruby.com/CN=testinformationcardruby.com')
10
+ assert_equal load_saml_token('john_smith.xml'), decrypter.decrypt
11
+ end
12
+ end
@@ -0,0 +1,14 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIICDzCCAXgCCQDTdQHNZKEURjANBgkqhkiG9w0BAQUFADBMMSQwIgYDVQQKExt0
3
+ ZXN0aW5mb3JtYXRpb25jYXJkcnVieS5jb20xJDAiBgNVBAMTG3Rlc3RpbmZvcm1h
4
+ dGlvbmNhcmRydWJ5LmNvbTAeFw0wNzA2MTgxNjA2MzZaFw0wODA2MTcxNjA2MzZa
5
+ MEwxJDAiBgNVBAoTG3Rlc3RpbmZvcm1hdGlvbmNhcmRydWJ5LmNvbTEkMCIGA1UE
6
+ AxMbdGVzdGluZm9ybWF0aW9uY2FyZHJ1YnkuY29tMIGfMA0GCSqGSIb3DQEBAQUA
7
+ A4GNADCBiQKBgQDkujMZdvOCE9EMyI/BJvqk5EpYdJlO+KFiROe0oDo3bdn0FtTl
8
+ pIPNoc7H1+eR5SR2LLsPnf2kw1KSfX+ZBZHvh8uqAdxl2VuxkUJv+5kIddHFB4pv
9
+ sGS6Nz4rb4sQAN1gWY4J1kE+/u3pJMuxX6rd9rnbHgpeV076tjkEoF6LcQIDAQAB
10
+ MA0GCSqGSIb3DQEBBQUAA4GBABX9MQuE96mRWw54qgID9LYYo//k3vE8NTQkjSQk
11
+ 6SYJdORS+dYb97SRV2Cs2y96SOixb1t3Cerjo6meMv9+rLeko4HNrujt8qqtvqYn
12
+ rqHVLxw5Htw532J39D9KvrZuFqbpWW9q8go5MvPT+fJDB2vkr13Jq6dpDkNdPbGa
13
+ IgLB
14
+ -----END CERTIFICATE-----
@@ -0,0 +1,15 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIICXAIBAAKBgQDkujMZdvOCE9EMyI/BJvqk5EpYdJlO+KFiROe0oDo3bdn0FtTl
3
+ pIPNoc7H1+eR5SR2LLsPnf2kw1KSfX+ZBZHvh8uqAdxl2VuxkUJv+5kIddHFB4pv
4
+ sGS6Nz4rb4sQAN1gWY4J1kE+/u3pJMuxX6rd9rnbHgpeV076tjkEoF6LcQIDAQAB
5
+ AoGALDq5YOY4pmGwnhk2ezJPa41dtwctEjFP+9G5QJtvRoKuj93OY23RsvTkKI7e
6
+ j77Qsy1pKtbxUmgW0o8EGpISKvLou7BsMk67gcO2YJmAL/8o058tdxUNWh1dO7J0
7
+ WoUb4Iyg6AtloZ8tCGPvYjEs+/SOKIoR0eEYiz43jEtb2PECQQD4QE6e8EU3W4Nu
8
+ Y+vG0yrVd3c5d51ukJi1GLXQiusAH4fGsCsEl325ew9qSr50iPH4Y7A0+fTfSKla
9
+ ZuGfczXdAkEA693iQvKJVUNWK0UMKFBE3R6D3HmD2U2INoyfLf+UVpsHARdY4lCX
10
+ BBEcAbwnXiFF1YeJGbMRHSeUwItdQ3TkpQJBALrJsB5YzMu1OLQzzLDCLIWHqRZ9
11
+ UOBjPfNtD0hFbkKedsvhu8xtq/SGinfAm4MVk3MAlxGVTVE/2+Ugaf1Oc6UCQH7G
12
+ NuvW4pvSYolFRoCQjELxONyS75wnwRPYx2H44ikekEg03VBfEpxb+dqw39QHPDrF
13
+ 65nFlmg+MwS+o3UzagUCQFxg/17Ld8cHjjRTUD0lcsFewNzRg05QkiY58kaAivr/
14
+ rCSTkz3ukcZ2C0bC+Gzd/1aPuETx4vmJ08dL+dkovfI=
15
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1 @@
1
+ <enc:EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns:enc="http://www.w3.org/2001/04/xmlenc#"><enc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" /><KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"><e:EncryptedKey xmlns:e="http://www.w3.org/2001/04/xmlenc#"><e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /></e:EncryptionMethod><KeyInfo><o:SecurityTokenReference xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><o:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#ThumbprintSHA1" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">RHQaUreXzrKAoZio1S+r1TWUyyQ=</o:KeyIdentifier></o:SecurityTokenReference></KeyInfo><e:CipherData><e:CipherValue>J81kk3TfEevZlnuB7mqDtM4ZnQuD8lLrd+rYrQa59fezvv90BqbQy0HU1Dd2Vbep1Dl3cTEUXUYpLV0FO2UL5c/SBKw4DfJr4avmxHZfnN7l2zrFykIUyNjjX2YnRWnXqXFUVLNKt3JCM3yZi2s2gxgd8F9nqOmiiNtarfm/1D0=</e:CipherValue></e:CipherData></e:EncryptedKey></KeyInfo><enc:CipherData><enc:CipherValue>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</enc:CipherValue></enc:CipherData></enc:EncryptedData>
@@ -0,0 +1 @@
1
+ <enc:EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns:enc="http://www.w3.org/2001/04/xmlenc#"><enc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" /><KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#"><e:EncryptedKey xmlns:e="http://www.w3.org/2001/04/xmlenc#"><e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /></e:EncryptionMethod><KeyInfo><o:SecurityTokenReference xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><o:KeyIdentifier ValueType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#ThumbprintSHA1" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">RHQaUreXzrKAoZio1S+r1TWUyyQ=</o:KeyIdentifier></o:SecurityTokenReference></KeyInfo><e:CipherData><e:CipherValue>w+M3gueh+TCDR8aT4YNZulkYH2DDOkazYlQoELJZKUzidcAptbdXZzy4Oxubmoxt8Q936vejwhv1G6d+8Vm26fsCH3+bqq3sTkmI1xVMR2t/9/7umlO+M6Eax5Hxn8rt9fNIzfF0pgPhIPBxoL51EHJbXc9+lheXN8/HPYRSGx0=</e:CipherValue></e:CipherData></e:EncryptedKey></KeyInfo><enc:CipherData><enc:CipherValue>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</enc:CipherValue></enc:CipherData></enc:EncryptedData>
@@ -0,0 +1 @@
1
+ <saml:Assertion MajorVersion="1" MinorVersion="1" AssertionID="uuid:1ae0b1c8-10f9-422c-9e96-cb41e963d892" Issuer="http://schemas.xmlsoap.org/ws/2005/05/identity/issuer/self" IssueInstant="2007-06-19T13:25:52.796Z" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion"><saml:Conditions NotBefore="2007-06-19T13:25:52.796Z" NotOnOrAfter="2007-06-19T14:25:52.796Z"><saml:AudienceRestrictionCondition><saml:Audience>https://testinformationcardruby.com/signup</saml:Audience></saml:AudienceRestrictionCondition></saml:Conditions><saml:AttributeStatement><saml:Subject><saml:SubjectConfirmation><saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:bearer</saml:ConfirmationMethod></saml:SubjectConfirmation></saml:Subject><saml:Attribute AttributeName="givenname" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims"><saml:AttributeValue>Jack</saml:AttributeValue></saml:Attribute><saml:Attribute AttributeName="surname" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims"><saml:AttributeValue>Deer</saml:AttributeValue></saml:Attribute><saml:Attribute AttributeName="emailaddress" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims"><saml:AttributeValue>jdeer@email.com</saml:AttributeValue></saml:Attribute><saml:Attribute AttributeName="streetaddress" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims"><saml:AttributeValue>33 Elk Street</saml:AttributeValue></saml:Attribute><saml:Attribute AttributeName="locality" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims"><saml:AttributeValue>Calgary</saml:AttributeValue></saml:Attribute><saml:Attribute AttributeName="stateorprovince" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims"><saml:AttributeValue>Alberta</saml:AttributeValue></saml:Attribute><saml:Attribute AttributeName="postalcode" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims"><saml:AttributeValue>T3H5R1</saml:AttributeValue></saml:Attribute><saml:Attribute AttributeName="country" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims"><saml:AttributeValue>Canada</saml:AttributeValue></saml:Attribute><saml:Attribute AttributeName="homephone" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims"><saml:AttributeValue>403-999-7300</saml:AttributeValue></saml:Attribute><saml:Attribute AttributeName="otherphone" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims"><saml:AttributeValue>403-999-7400</saml:AttributeValue></saml:Attribute><saml:Attribute AttributeName="mobilephone" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims"><saml:AttributeValue>403-999-7500</saml:AttributeValue></saml:Attribute><saml:Attribute AttributeName="dateofbirth" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims"><saml:AttributeValue>1980-06-19T06:00:00Z</saml:AttributeValue></saml:Attribute><saml:Attribute AttributeName="gender" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims"><saml:AttributeValue>1</saml:AttributeValue></saml:Attribute><saml:Attribute AttributeName="webpage" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims"><saml:AttributeValue>www.informationcardruby.com</saml:AttributeValue></saml:Attribute><saml:Attribute AttributeName="privatepersonalidentifier" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims"><saml:AttributeValue>NZnC7eVhrZ7DD5ZBp+Cks0JTSPV/nLF3qryWiAJz9G8=</saml:AttributeValue></saml:Attribute></saml:AttributeStatement><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></CanonicalizationMethod><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></SignatureMethod><Reference URI="#uuid:1ae0b1c8-10f9-422c-9e96-cb41e963d892"><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></Transform><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></Transform></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod><DigestValue>sAQmArKBqwihqm20Z/H0p7UEOTg=</DigestValue></Reference></SignedInfo><SignatureValue>BNrrDCKJWmEIXUjwQTaebmTDJrw4fR9kpg4QTt963NP3J9V5Y1+s7JrWQTx19Q5X136N71XRopWNUGmgSsNLWbBhj9Z7bywBAFLSSRMGsQsHbrmr8SWwNNFZ/yq76z44wGo8+JQ9SK4rY3T0Sel9iNAXwTLGCl0vnzf0AciV/4blrw0GJhOb9rhV/isVU1+TCsqLzYJdXIijWF4QR8iLEBwkYFy03c9Y2qls0UwXdOomQLCDB3B6WAjZvMoTFH5ZYRjU0653W1FcRQDHi7/ydlMiXDhzuuVB+R/Ie/GRs6/5/GpvT8iPvMXfQdFxt5ulp0/LUQhDY1wOEGI2XcGmng==</SignatureValue><KeyInfo><KeyValue><RSAKeyValue><Modulus>zGDnSrX1KR82cmSAiwyXJsrd/X4I/1TZfPcVSXldPZPE5BX8Qs9mx4y1nlQ/as60cyhLOU28ayXGumZmkwanOs7m16yQmLEdjG+N72jbadF355QcOciVFkI5sn2zstbDJW+9dW4hNIxjyJUtkTOBIH1Vs7f6eI7X5+0L6f88sRDT7siCnNflgAe1XG7HITtx5v88AJ3kA55CHW8j0dW/imiIl9rjA7wElC9yzs/z+I9eKezqssrrmZ8Bi9sNxgXaAkpO4caw7JIQA+bjlxShTur6+5VnlKu9XUCVzkBzVmtPb9N5HCiif5wc8/9Q0JXQ9effn0/ARTsJaJcAMeQgiw==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue></KeyValue></KeyInfo></Signature></saml:Assertion>
@@ -0,0 +1 @@
1
+ <saml:Assertion MajorVersion="1" MinorVersion="1" AssertionID="uuid:1ccdbaa7-eeca-4c1b-aacf-4622d08074b6" Issuer="http://schemas.xmlsoap.org/ws/2005/05/identity/issuer/self" IssueInstant="2007-06-19T05:48:52.906Z" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion"><saml:Conditions NotBefore="2007-06-19T05:48:52.906Z" NotOnOrAfter="2007-06-19T06:48:52.906Z"><saml:AudienceRestrictionCondition><saml:Audience>https://testinformationcardruby.com/signup</saml:Audience></saml:AudienceRestrictionCondition></saml:Conditions><saml:AttributeStatement><saml:Subject><saml:SubjectConfirmation><saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:bearer</saml:ConfirmationMethod></saml:SubjectConfirmation></saml:Subject><saml:Attribute AttributeName="givenname" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims"><saml:AttributeValue>John</saml:AttributeValue></saml:Attribute><saml:Attribute AttributeName="surname" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims"><saml:AttributeValue>Smith</saml:AttributeValue></saml:Attribute><saml:Attribute AttributeName="emailaddress" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims"><saml:AttributeValue>jsmith@email.com</saml:AttributeValue></saml:Attribute><saml:Attribute AttributeName="privatepersonalidentifier" AttributeNamespace="http://schemas.xmlsoap.org/ws/2005/05/identity/claims"><saml:AttributeValue>bwicndBxw/6YC029oPv0NWHBbPNMDMoJLQJ6qkofJIg=</saml:AttributeValue></saml:Attribute></saml:AttributeStatement><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></CanonicalizationMethod><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></SignatureMethod><Reference URI="#uuid:1ccdbaa7-eeca-4c1b-aacf-4622d08074b6"><Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></Transform><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></Transform></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod><DigestValue>VZkAevzI3Hj9YRG7hW5MD2n/mwg=</DigestValue></Reference></SignedInfo><SignatureValue>OV4K3XI9JvHO7ZZU6BwFpS31psaxqvj9VotrrEF68UewDbgovjJCFwB4KA50emiI/lE/urM40OaYlWy/XZflXAyMiYQJtOeSV1lXgohBZcsqgs98kXEaoHx3TN1R5y5uusZ16++Z3E3CobN6F8KS/kPP6ocDB7FhBR3rxeKqjDGRuecILONJR8pO/4jONEsG6OGEHVXYuhhH0IT+7PZNFYt5sB4NXKPfh8pEmYj37O4JvyZnvXeQ81fI4f+TRqap6Yg3DeeTxBNJ6YBHOPP7HT5juERSZHhU4rPPjUCggMq3JPCMcNZKKBTEYclE74aDJjImynWJhtpcdqpMs/k5Lw==</SignatureValue><KeyInfo><KeyValue><RSAKeyValue><Modulus>w9yuP4lSIcTT3i9VDll83AvNvsD8HpPpBSsYKH669ImXrpx7v2RzkRatn27Ebo14CA+91HNApYJ+IeshfgkHXJ0gZx5jTNJ7VsDCJ2YgdOh8J9kKx+GMLPgogm/z0KCTE41rtXB7QYHYoMvSXqn4B9y1Thb9qLvz1nQA7oLJW3j60FOF/IiujHdrFQ09NPqILnzHZpTT4/iqEFvGofPVBwjOnwEoV8PYhMjRNW+i3yKkf54LOaNta+KTQVGC26aXtDFBR4PEOXsmk7tOvEk9+mW2Zja7zWbhhElUR6EEwcqWHjHMXHVYdypPNvCaimHfDIJ3KAJXtYUMcNCHAIOHsQ==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue></KeyValue></KeyInfo></Signature></saml:Assertion>
@@ -0,0 +1,34 @@
1
+ require 'test_helper'
2
+
3
+ class ProcessorTest < Test::Unit::TestCase
4
+ include InformationCard
5
+
6
+ def setup
7
+ Config.certificate_location = 'test/fixtures/certificates'
8
+ Config.certificate_subject = '/O=testinformationcardruby.com/CN=testinformationcardruby.com'
9
+ Config.required_claims = [:given_name, :surname, :ppid, :email_address]
10
+ end
11
+
12
+ def test_should_take_encrypted_data_and_return_a_saml_token
13
+ claims = {:given_name => 'John',
14
+ :surname => 'Smith',
15
+ :ppid => 'bwicndBxw/6YC029oPv0NWHBbPNMDMoJLQJ6qkofJIg=',
16
+ :email_address => 'jsmith@email.com'}
17
+
18
+ setup_saml_environment('john_smith.xml')
19
+ processed_token = Processor.process(load_encrypted_information_card('john_smith.xml'))
20
+ assert processed_token.valid?
21
+ assert_equal claims, processed_token.claims
22
+ end
23
+
24
+ def test_should_return_invalid_token_if_exception_occurs_during_decryption
25
+ decrypter = Object.new
26
+ decrypter.stubs(:decrypt).raises('problem with decryption')
27
+ Decrypter.stubs(:new).returns(decrypter)
28
+
29
+ token = Processor.process('invalid token')
30
+ assert token.instance_of?(InvalidToken)
31
+ assert_equal token.errors[:decryption], 'problem with decryption'
32
+ end
33
+
34
+ end
@@ -0,0 +1,165 @@
1
+ require 'test_helper'
2
+
3
+ class SamlTokenTest < Test::Unit::TestCase
4
+ include InformationCard
5
+
6
+ def setup
7
+ @valid_saml_input = setup_saml_environment('john_smith.xml')
8
+ @not_before = Time.parse('2007-06-19T05:48:52.906Z')
9
+ @not_on_or_after = Time.parse('2007-06-19T06:48:52.906Z')
10
+ Config.required_claims = {}
11
+ Config.audience_scope = :page
12
+ end
13
+
14
+ def test_should_validate_a_valid_saml_token
15
+ saml_token = SamlToken.create(@valid_saml_input)
16
+ assert saml_token.errors.empty?
17
+ assert saml_token.valid?
18
+ end
19
+
20
+ def test_should_return_claims
21
+ saml_token = SamlToken.create(@valid_saml_input)
22
+ claims = saml_token.claims
23
+ expected_claims = {:given_name => 'John', :surname => 'Smith',
24
+ :ppid => 'bwicndBxw/6YC029oPv0NWHBbPNMDMoJLQJ6qkofJIg=',
25
+ :email_address => 'jsmith@email.com'}
26
+ assert_equal(expected_claims, claims)
27
+ end
28
+
29
+ def test_should_return_claims_for_user_with_full_set_of_claims
30
+ saml_token = SamlToken.create(setup_saml_environment('jack_deer.xml'))
31
+ claims = saml_token.claims
32
+ expected_claims = {:date_of_birth=>"1980-06-19T06:00:00Z", :given_name=>"Jack",
33
+ :postal_code=>"T3H5R1", :gender=>"1", :email_address=>"jdeer@email.com",
34
+ :country=>"Canada", :webpage=>"www.informationcardruby.com",
35
+ :surname=>"Deer", :home_phone=>"403-999-7300",
36
+ :ppid=>"NZnC7eVhrZ7DD5ZBp+Cks0JTSPV/nLF3qryWiAJz9G8=",
37
+ :street_address=>"33 Elk Street", :other_phone=>"403-999-7400",
38
+ :locality=>"Calgary", :mobile_phone=>"403-999-7500",
39
+ :state_province=>"Alberta"}
40
+ assert_equal(expected_claims, claims)
41
+ end
42
+
43
+ def test_should_not_return_claims_if_token_is_invalid
44
+ invalid_saml_input = input_with_xml_element_replaced(@valid_saml_input, "SignatureValue", "invalid signature value")
45
+ saml_token = SamlToken.create(invalid_saml_input)
46
+ assert_false saml_token.valid?
47
+ assert saml_token.claims.empty?
48
+ end
49
+
50
+ def test_should_detect_invalid_digest
51
+ valid_digest = "VZkAevzI3Hj9YRG7hW5MD2n/mwg="
52
+ saml_input_with_invalid_digest = input_with_xml_element_replaced(@valid_saml_input, "DigestValue", valid_digest.reverse)
53
+ saml_token = SamlToken.create(saml_input_with_invalid_digest)
54
+ assert_false saml_token.valid?
55
+ assert_equal ["Invalid Digest for #uuid:1ccdbaa7-eeca-4c1b-aacf-4622d08074b6. Expected #{valid_digest} but was #{valid_digest.reverse}"],
56
+ saml_token.errors[:digest]
57
+ end
58
+
59
+ def test_should_detect_invalid_signature
60
+ saml_input_with_invalid_signature = input_with_xml_element_replaced(@valid_saml_input, "SignatureValue", 'invalid signature value')
61
+ saml_token = SamlToken.create(saml_input_with_invalid_signature)
62
+ assert_false saml_token.valid?
63
+ assert_equal "Invalid Signature", saml_token.errors[:signature]
64
+ end
65
+
66
+ def test_should_return_hashed_ppid_for_unique_id_if_identity_claim_is_ppid
67
+ InformationCard::Config.identity_claim = :ppid
68
+ saml_token = SamlToken.create(@valid_saml_input)
69
+ assert_equal 'c3880b5491ae25aacedbeb5d9a40d5c966d8d84d', saml_token.unique_id
70
+ end
71
+
72
+ def test_should_return_identity_claim_value_for_unique_id_if_identity_claim_is_not_ppid
73
+ InformationCard::Config.identity_claim = :email_address
74
+ saml_token = SamlToken.create(@valid_saml_input)
75
+ assert_equal 'jsmith@email.com', saml_token.unique_id
76
+ end
77
+
78
+ def test_should_detect_when_current_time_is_before_not_before_condition
79
+ Time.stubs(:now).returns(@not_before - 1)
80
+
81
+ saml_token = SamlToken.create(@valid_saml_input)
82
+ assert_false saml_token.valid?
83
+ expected_error = {:not_before => "Time is before #{@not_before}"}
84
+ assert_equal expected_error, saml_token.errors[:conditions]
85
+ end
86
+
87
+ def test_should_detect_when_current_time_is_after_not_on_or_after_condition
88
+ Time.stubs(:now).returns(@not_on_or_after + 1)
89
+
90
+ saml_token = SamlToken.create(@valid_saml_input)
91
+ assert_false saml_token.valid?
92
+ expected_error = {:not_on_or_after => "Time is on or after #{@not_on_or_after}"}
93
+ assert_equal expected_error, saml_token.errors[:conditions]
94
+ end
95
+
96
+ def test_should_detect_when_current_time_is_on_not_on_or_after_condition
97
+ Time.stubs(:now).returns(@not_on_or_after)
98
+
99
+ saml_token = SamlToken.create(@valid_saml_input)
100
+ assert_false saml_token.valid?
101
+ expected_error = {:not_on_or_after => "Time is on or after #{@not_on_or_after}"}
102
+ assert_equal expected_error, saml_token.errors[:conditions]
103
+ end
104
+
105
+ def test_should_validate_page_level_audience_restriction
106
+ saml_token = SamlToken.create(@valid_saml_input)
107
+ assert saml_token.valid?
108
+ assert saml_token.errors[:audience].nil?
109
+ end
110
+
111
+ def test_should_detect_page_level_audience_restriction_error
112
+ InformationCard::Config.audiences = ['http://website.com/page1', 'http://website.com/page2']
113
+ saml_token = SamlToken.create(@valid_saml_input)
114
+ assert_false saml_token.valid?
115
+ expected_error = "AudienceRestriction is not valid"
116
+ assert_equal expected_error, saml_token.errors[:audience]
117
+ end
118
+
119
+ def test_should_validate_site_level_audience_restriction
120
+ InformationCard::Config.audience_scope = :site
121
+ InformationCard::Config.audiences = ['https://testinformationcardruby.com']
122
+ saml_token = SamlToken.create(@valid_saml_input)
123
+ assert saml_token.valid?
124
+ assert saml_token.errors[:audience].nil?
125
+ end
126
+
127
+ def test_should_detect_site_level_audience_restriction_error
128
+ InformationCard::Config.audience_scope = :site
129
+ InformationCard::Config.audiences = ['https://someothersite.com']
130
+ saml_token = SamlToken.create(@valid_saml_input)
131
+ assert_false saml_token.valid?
132
+ expected_error = "AudienceRestriction is not valid"
133
+ assert_equal expected_error, saml_token.errors[:audience]
134
+ end
135
+
136
+ def test_should_throw_error_if_audiences_are_not_configured
137
+ InformationCard::Config.audiences = []
138
+ saml_token = SamlToken.create(@valid_saml_input)
139
+ assert_false saml_token.valid?
140
+ expected_error = "AudienceRestriction is not valid"
141
+ assert_equal expected_error, saml_token.errors[:audience]
142
+
143
+ InformationCard::Config.audiences = nil
144
+ saml_token = SamlToken.create(@valid_saml_input)
145
+ assert_false saml_token.valid?
146
+ expected_error = "AudienceRestriction is not valid"
147
+ assert_equal expected_error, saml_token.errors[:audience]
148
+ end
149
+
150
+ def test_should_detect_missing_claim
151
+ Config.required_claims = [:ppid, :mobile_phone]
152
+ saml_token = SamlToken.create(@valid_saml_input)
153
+ assert_false saml_token.valid?
154
+ expected_error = [:mobile_phone]
155
+ assert_equal expected_error, saml_token.errors[:missing_claims]
156
+ end
157
+
158
+ def test_should_detect_missing_multiple_claims
159
+ Config.required_claims = [:ppid, :mobile_phone, :postal_code]
160
+ saml_token = SamlToken.create(@valid_saml_input)
161
+ assert_false saml_token.valid?
162
+ expected_error = [:mobile_phone, :postal_code]
163
+ assert_equal expected_error, saml_token.errors[:missing_claims]
164
+ end
165
+ end
@@ -0,0 +1,73 @@
1
+ require 'test/unit'
2
+ require "rexml/document"
3
+ require File.dirname(__FILE__) + '/../lib/information_card'
4
+
5
+ require 'rubygems'
6
+ gem 'mocha'
7
+ require 'stubba'
8
+
9
+ class Test::Unit::TestCase
10
+ include REXML
11
+
12
+ def assert_false(condition)
13
+ assert !condition
14
+ end
15
+
16
+ def load_encrypted_information_card(file_name)
17
+ File.read File.join(File.dirname(__FILE__), "fixtures/encrypted_information_cards", file_name)
18
+ end
19
+
20
+ def load_saml_token(file_name)
21
+ File.read File.join(File.dirname(__FILE__), "fixtures/saml_tokens", file_name)
22
+ end
23
+
24
+ def setup_saml_environment(file_name)
25
+ saml_token = load_saml_token(file_name)
26
+
27
+ saml_doc = REXML::Document.new(saml_token)
28
+ conditions = REXML::XPath.first(saml_doc, "//saml:Conditions", "saml" => "urn:oasis:names:tc:SAML:1.0:assertion")
29
+ not_before_time = Time.parse(conditions.attributes['NotBefore'])
30
+ Time.stubs(:now).returns(not_before_time)
31
+ audiences = REXML::XPath.match(saml_doc, "//saml:AudienceRestrictionCondition/saml:Audience", {"saml" => "urn:oasis:names:tc:SAML:1.0:assertion"})
32
+ InformationCard::Config.audiences = audiences.collect {|a| a.text}
33
+ InformationCard::Config.audience_scope = :page
34
+
35
+ saml_token
36
+ end
37
+
38
+ def certificates_directory
39
+ File.join(File.dirname(__FILE__), "fixtures/certificates")
40
+ end
41
+
42
+ def input_with_xml_element_replaced(xml_string, element, text)
43
+ doc = REXML::Document.new(xml_string)
44
+ node = doc.root.find_first_recursive {|node| node.kind_of? Element and node.name == element }
45
+ node.text = text
46
+ doc.to_s
47
+ end
48
+
49
+ def assert_equal_arrays(expected, actual)
50
+ actual.sort! {|a,b| yield a, b} if block_given?
51
+ msg = "#{expected.join(',')} expected, but was \n#{actual.join(',')}"
52
+ assert_equal expected.size, actual.size, msg
53
+ assert_equal expected, actual, msg
54
+ end
55
+
56
+ def assert_raises(arg1 = nil, arg2 = nil)
57
+ expected_error = arg1.is_a?(Exception) ? arg1 : nil
58
+ expected_class = arg1.is_a?(Class) ? arg1 : nil
59
+ expected_message = arg1.is_a?(String) ? arg1 : arg2
60
+ begin
61
+ yield
62
+ fail "expected error was not raised"
63
+ rescue Test::Unit::AssertionFailedError
64
+ raise
65
+ rescue => e
66
+ raise if e.message == "expected error was not raised"
67
+ assert_equal(expected_error, e) if expected_error
68
+ assert_equal(expected_class, e.class, "Unexpected error type raised") if expected_class
69
+ assert_equal(expected_message, e.message, "Unexpected error message") if expected_message.is_a? String
70
+ assert_matched(expected_message, e.message, "Unexpected error message") if expected_message.is_a? Regexp
71
+ end
72
+ end
73
+ end