information_card 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +2 -0
- data/LICENSE +27 -0
- data/README +45 -0
- data/Rakefile +35 -0
- data/lib/information_card.rb +10 -0
- data/lib/information_card/certificate_util.rb +17 -0
- data/lib/information_card/claim_types.rb +43 -0
- data/lib/information_card/config.rb +52 -0
- data/lib/information_card/decrypter.rb +53 -0
- data/lib/information_card/identity_token.rb +23 -0
- data/lib/information_card/invalid_token.rb +8 -0
- data/lib/information_card/namespaces.rb +7 -0
- data/lib/information_card/processor.rb +15 -0
- data/lib/information_card/saml_token.rb +212 -0
- data/lib/information_card/xml_canonicalizer.rb +95 -0
- data/test/certificate_util_test.rb +21 -0
- data/test/claim_types_test.rb +39 -0
- data/test/decrypter_test.rb +12 -0
- data/test/fixtures/certificates/test.crt +14 -0
- data/test/fixtures/certificates/test.key +15 -0
- data/test/fixtures/encrypted_information_cards/jack_deer.xml +1 -0
- data/test/fixtures/encrypted_information_cards/john_smith.xml +1 -0
- data/test/fixtures/saml_tokens/jack_deer.xml +1 -0
- data/test/fixtures/saml_tokens/john_smith.xml +1 -0
- data/test/processor_test.rb +34 -0
- data/test/saml_token_test.rb +165 -0
- data/test/test_helper.rb +73 -0
- data/test/xml_canonicalizer_test.rb +188 -0
- metadata +78 -0
@@ -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
|
data/test/test_helper.rb
ADDED
@@ -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
|