ruby-saml-mod 0.1.2 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/onelogin/saml.rb +6 -0
- data/lib/onelogin/saml/meta_data.rb +32 -12
- data/lib/onelogin/saml/response.rb +13 -14
- data/lib/onelogin/saml/settings.rb +15 -0
- data/lib/xml_sec.rb +25 -1
- data/ruby-saml-mod.gemspec +3 -3
- metadata +6 -10
data/lib/onelogin/saml.rb
CHANGED
@@ -4,6 +4,12 @@ require "rexml/document"
|
|
4
4
|
require "xml_sec"
|
5
5
|
|
6
6
|
module Onelogin
|
7
|
+
NAMESPACES = {
|
8
|
+
"samlp" => "urn:oasis:names:tc:SAML:2.0:protocol",
|
9
|
+
"saml" => "urn:oasis:names:tc:SAML:2.0:assertion",
|
10
|
+
"xenc" => "http://www.w3.org/2001/04/xmlenc#",
|
11
|
+
"ds" => "http://www.w3.org/2000/09/xmldsig#"
|
12
|
+
}
|
7
13
|
end
|
8
14
|
|
9
15
|
require 'onelogin/saml/auth_request'
|
@@ -1,17 +1,37 @@
|
|
1
1
|
module Onelogin::Saml
|
2
2
|
class MetaData
|
3
3
|
def self.create(settings)
|
4
|
-
|
5
|
-
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" entityID="#{settings.issuer}">
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
4
|
+
xml = %{<?xml version="1.0"?>
|
5
|
+
<EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" entityID="#{settings.issuer}">
|
6
|
+
<SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
|
7
|
+
}
|
8
|
+
if settings.encryption_configured?
|
9
|
+
xml += %{
|
10
|
+
<KeyDescriptor use="encryption">
|
11
|
+
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
|
12
|
+
<X509Data>
|
13
|
+
<X509Certificate>
|
14
|
+
#{File.read(settings.xmlsec_certificate).gsub(/\w*-+(BEGIN|END) CERTIFICATE-+\w*/, "").strip}
|
15
|
+
</X509Certificate>
|
16
|
+
</X509Data>
|
17
|
+
</KeyInfo>
|
18
|
+
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc">
|
19
|
+
<KeySize xmlns="http://www.w3.org/2001/04/xmlenc#">128</KeySize>
|
20
|
+
</EncryptionMethod>
|
21
|
+
</KeyDescriptor>
|
22
|
+
}
|
23
|
+
end
|
24
|
+
xml += %{
|
25
|
+
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="#{settings.sp_slo_url}"/>
|
26
|
+
<AssertionConsumerService index="0" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="#{settings.assertion_consumer_service_url}"/>
|
27
|
+
</SPSSODescriptor>
|
28
|
+
<ContactPerson contactType="technical">
|
29
|
+
<SurName>#{settings.tech_contact_name}</SurName>
|
30
|
+
<EmailAddress>mailto:#{settings.tech_contact_email}</EmailAddress>
|
31
|
+
</ContactPerson>
|
32
|
+
</EntityDescriptor>
|
33
|
+
}
|
34
|
+
xml
|
15
35
|
end
|
16
36
|
end
|
17
|
-
end
|
37
|
+
end
|
@@ -1,23 +1,22 @@
|
|
1
1
|
module Onelogin::Saml
|
2
2
|
class Response
|
3
3
|
|
4
|
-
attr_accessor :settings, :document, :response
|
4
|
+
attr_accessor :settings, :document, :xml, :response
|
5
5
|
attr_accessor :name_id, :name_qualifier, :session_index
|
6
6
|
attr_accessor :status_code, :status_message
|
7
|
-
def initialize(response)
|
7
|
+
def initialize(response, settings)
|
8
8
|
@response = response
|
9
|
-
@
|
10
|
-
|
11
|
-
@
|
12
|
-
@
|
13
|
-
@
|
14
|
-
|
15
|
-
|
16
|
-
@
|
17
|
-
@
|
18
|
-
@
|
19
|
-
@
|
20
|
-
@status_message ||= @document.elements["/saml2p:Response/saml2p:Status/saml2p:StatusCode"].text rescue nil
|
9
|
+
@settings = settings
|
10
|
+
|
11
|
+
@xml = Base64.decode64(@response)
|
12
|
+
@document = XMLSecurity::SignedDocument.new(@xml)
|
13
|
+
@document.decrypt(@settings)
|
14
|
+
|
15
|
+
@name_id = REXML::XPath.first(@document, "/samlp:Response/saml:Assertion/saml:Subject/saml:NameID", Onelogin::NAMESPACES).text rescue nil
|
16
|
+
@name_qualifier = REXML::XPath.first(@document, "/samlp:Response/saml:Assertion/saml:Subject/saml:NameID", Onelogin::NAMESPACES).attributes["NameQualifier"] rescue nil
|
17
|
+
@session_index = REXML::XPath.first(@document, "/samlp:Response/saml:Assertion/saml:AuthnStatement", Onelogin::NAMESPACES).attributes["SessionIndex"] rescue nil
|
18
|
+
@status_code = REXML::XPath.first(@document, "/samlp:Response/samlp:Status/samlp:StatusCode", Onelogin::NAMESPACES).attributes["Value"] rescue nil
|
19
|
+
@status_message = REXML::XPath.first(@document, "/samlp:Response/samlp:Status/samlp:StatusCode", Onelogin::NAMESPACES).text rescue nil
|
21
20
|
end
|
22
21
|
|
23
22
|
def logger=(val)
|
@@ -41,5 +41,20 @@ module Onelogin::Saml
|
|
41
41
|
|
42
42
|
# The email of the technical contact for your application
|
43
43
|
attr_accessor :tech_contact_email
|
44
|
+
|
45
|
+
## Attributes for xml encryption
|
46
|
+
|
47
|
+
# The path to the xmlsec1 binary used for xml decryption
|
48
|
+
attr_accessor :xmlsec1_path
|
49
|
+
|
50
|
+
# The PEM-encoded certificate
|
51
|
+
attr_accessor :xmlsec_certificate
|
52
|
+
|
53
|
+
# The PEM-encoded private key
|
54
|
+
attr_accessor :xmlsec_privatekey
|
55
|
+
|
56
|
+
def encryption_configured?
|
57
|
+
self.xmlsec1_path && self.xmlsec_certificate && self.xmlsec_privatekey
|
58
|
+
end
|
44
59
|
end
|
45
60
|
end
|
data/lib/xml_sec.rb
CHANGED
@@ -28,6 +28,8 @@ require "rexml/xpath"
|
|
28
28
|
require "openssl"
|
29
29
|
require "xmlcanonicalizer"
|
30
30
|
require "digest/sha1"
|
31
|
+
require "tempfile"
|
32
|
+
require "shellwords"
|
31
33
|
|
32
34
|
module XMLSecurity
|
33
35
|
|
@@ -86,6 +88,28 @@ module XMLSecurity
|
|
86
88
|
|
87
89
|
return valid_flag
|
88
90
|
end
|
89
|
-
|
91
|
+
|
92
|
+
def decrypt(settings)
|
93
|
+
if settings.encryption_configured?
|
94
|
+
REXML::XPath.each(self, "//xenc:EncryptedData", Onelogin::NAMESPACES) do |node|
|
95
|
+
Tempfile.open("ruby-saml-decrypt") do |f|
|
96
|
+
f.puts node.to_s
|
97
|
+
f.close
|
98
|
+
command = [ settings.xmlsec1_path, "decrypt", "--privkey-pem", settings.xmlsec_privatekey, f.path ].shelljoin
|
99
|
+
decrypted_xml = %x{#{command}}
|
100
|
+
if $?.exitstatus != 0
|
101
|
+
@logger.warn "Could not decrypt: #{decrypted_xml}" if @logger
|
102
|
+
return false
|
103
|
+
else
|
104
|
+
decrypted_doc = REXML::Document.new(decrypted_xml)
|
105
|
+
decrypted_node = decrypted_doc.root
|
106
|
+
node.parent.replace_with(decrypted_node)
|
107
|
+
end
|
108
|
+
f.unlink
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
true
|
113
|
+
end
|
90
114
|
end
|
91
115
|
end
|
data/ruby-saml-mod.gemspec
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = %q{ruby-saml-mod}
|
3
|
-
s.version = "0.1.
|
3
|
+
s.version = "0.1.4"
|
4
4
|
|
5
|
-
s.authors = ["OneLogin LLC", "Bracken"]
|
6
|
-
s.date = %q{2011-
|
5
|
+
s.authors = ["OneLogin LLC", "Bracken", "Zach"]
|
6
|
+
s.date = %q{2011-11-05}
|
7
7
|
s.extra_rdoc_files = [
|
8
8
|
"LICENSE"
|
9
9
|
]
|
metadata
CHANGED
@@ -1,22 +1,22 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-saml-mod
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
4
|
+
prerelease: false
|
6
5
|
segments:
|
7
6
|
- 0
|
8
7
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
8
|
+
- 4
|
9
|
+
version: 0.1.4
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- OneLogin LLC
|
14
13
|
- Bracken
|
14
|
+
- Zach
|
15
15
|
autorequire:
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2011-
|
19
|
+
date: 2011-11-05 00:00:00 -06:00
|
20
20
|
default_executable:
|
21
21
|
dependencies: []
|
22
22
|
|
@@ -51,27 +51,23 @@ rdoc_options: []
|
|
51
51
|
require_paths:
|
52
52
|
- lib
|
53
53
|
required_ruby_version: !ruby/object:Gem::Requirement
|
54
|
-
none: false
|
55
54
|
requirements:
|
56
55
|
- - ">="
|
57
56
|
- !ruby/object:Gem::Version
|
58
|
-
hash: 3
|
59
57
|
segments:
|
60
58
|
- 0
|
61
59
|
version: "0"
|
62
60
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
|
-
none: false
|
64
61
|
requirements:
|
65
62
|
- - ">="
|
66
63
|
- !ruby/object:Gem::Version
|
67
|
-
hash: 3
|
68
64
|
segments:
|
69
65
|
- 0
|
70
66
|
version: "0"
|
71
67
|
requirements: []
|
72
68
|
|
73
69
|
rubyforge_project:
|
74
|
-
rubygems_version: 1.6
|
70
|
+
rubygems_version: 1.3.6
|
75
71
|
signing_key:
|
76
72
|
specification_version: 3
|
77
73
|
summary: Ruby library for SAML service providers
|