ruby-saml-mod 0.1.5 → 0.1.6
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.
- data/lib/onelogin/saml.rb +2 -1
- data/lib/onelogin/saml/auth_request.rb +27 -15
- data/lib/onelogin/saml/log_out_request.rb +22 -10
- data/lib/onelogin/saml/logout_response.rb +30 -0
- data/lib/onelogin/saml/response.rb +19 -4
- data/ruby-saml-mod.gemspec +2 -1
- metadata +4 -3
data/lib/onelogin/saml.rb
CHANGED
@@ -19,4 +19,5 @@ require 'onelogin/saml/settings'
|
|
19
19
|
require 'onelogin/saml/name_identifiers'
|
20
20
|
require 'onelogin/saml/status_codes'
|
21
21
|
require 'onelogin/saml/meta_data'
|
22
|
-
require 'onelogin/saml/log_out_request'
|
22
|
+
require 'onelogin/saml/log_out_request'
|
23
|
+
require 'onelogin/saml/logout_response'
|
@@ -1,27 +1,39 @@
|
|
1
1
|
module Onelogin::Saml
|
2
2
|
class AuthRequest
|
3
|
+
|
4
|
+
attr_reader :settings, :id, :request_xml, :forward_url
|
5
|
+
|
6
|
+
def initialize(settings)
|
7
|
+
@settings = settings
|
8
|
+
end
|
9
|
+
|
3
10
|
def self.create(settings)
|
4
|
-
|
5
|
-
|
11
|
+
ar = AuthRequest.new(settings)
|
12
|
+
ar.generate_request
|
13
|
+
end
|
14
|
+
|
15
|
+
def generate_request
|
16
|
+
@id = Onelogin::Saml::AuthRequest.generate_unique_id(42)
|
17
|
+
issue_instant = Onelogin::Saml::AuthRequest.get_timestamp
|
6
18
|
|
7
|
-
|
8
|
-
"<samlp:AuthnRequest xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" ID=\"#{id}\" Version=\"2.0\" IssueInstant=\"#{issue_instant}\" ProtocolBinding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST\" AssertionConsumerServiceURL=\"#{settings.assertion_consumer_service_url}\">" +
|
9
|
-
"<saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">#{settings.issuer}</saml:Issuer>\n" +
|
10
|
-
"<samlp:NameIDPolicy xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" Format=\"#{settings.name_identifier_format}\" AllowCreate=\"true\"></samlp:NameIDPolicy>\n"
|
19
|
+
@request_xml =
|
20
|
+
"<samlp:AuthnRequest xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" ID=\"#{@id}\" Version=\"2.0\" IssueInstant=\"#{issue_instant}\" ProtocolBinding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST\" AssertionConsumerServiceURL=\"#{settings.assertion_consumer_service_url}\">" +
|
21
|
+
"<saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">#{@settings.issuer}</saml:Issuer>\n" +
|
22
|
+
"<samlp:NameIDPolicy xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" Format=\"#{@settings.name_identifier_format}\" AllowCreate=\"true\"></samlp:NameIDPolicy>\n"
|
11
23
|
|
12
|
-
if settings.requested_authn_context
|
13
|
-
|
14
|
-
|
15
|
-
|
24
|
+
if @settings.requested_authn_context
|
25
|
+
@request_xml += "<samlp:RequestedAuthnContext xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" Comparison=\"exact\">"
|
26
|
+
@request_xml += "<saml:AuthnContextClassRef xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">#{@settings.requested_authn_context}</saml:AuthnContextClassRef>"
|
27
|
+
@request_xml += "</samlp:RequestedAuthnContext>\n"
|
16
28
|
end
|
17
29
|
|
18
|
-
|
30
|
+
@request_xml += "</samlp:AuthnRequest>"
|
19
31
|
|
20
|
-
deflated_request = Zlib::Deflate.deflate(
|
32
|
+
deflated_request = Zlib::Deflate.deflate(@request_xml, 9)[2..-5]
|
21
33
|
base64_request = Base64.encode64(deflated_request)
|
22
|
-
encoded_request = CGI.escape(base64_request)
|
23
|
-
|
24
|
-
settings.idp_sso_target_url + "?SAMLRequest=" + encoded_request
|
34
|
+
encoded_request = CGI.escape(base64_request)
|
35
|
+
|
36
|
+
@forward_url = @settings.idp_sso_target_url + "?SAMLRequest=" + encoded_request
|
25
37
|
end
|
26
38
|
|
27
39
|
private
|
@@ -1,22 +1,34 @@
|
|
1
1
|
module Onelogin::Saml
|
2
2
|
class LogOutRequest
|
3
|
+
attr_reader :settings, :id, :request_xml, :forward_url
|
4
|
+
|
5
|
+
def initialize(settings, session)
|
6
|
+
@settings = settings
|
7
|
+
@session = session
|
8
|
+
end
|
9
|
+
|
3
10
|
def self.create(settings, session)
|
4
|
-
|
5
|
-
|
11
|
+
ar = LogOutRequest.new(settings, session)
|
12
|
+
ar.generate_request
|
13
|
+
end
|
14
|
+
|
15
|
+
def generate_request
|
16
|
+
@id = Onelogin::Saml::AuthRequest.generate_unique_id(42)
|
17
|
+
issue_instant = Onelogin::Saml::AuthRequest.get_timestamp
|
6
18
|
|
7
|
-
|
8
|
-
"<saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">#{settings.issuer}</saml:Issuer>" +
|
9
|
-
"<saml:NameID xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" NameQualifier=\"#{session[:name_qualifier]}\" SPNameQualifier=\"#{settings.issuer}\" Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:transient\">#{session[:name_id]}</saml:NameID>" +
|
10
|
-
"<samlp:SessionIndex xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\">#{session[:session_index]}</samlp:SessionIndex>" +
|
11
|
-
"</samlp:LogoutRequest>"
|
19
|
+
@request_xml = "<samlp:LogoutRequest xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" ID=\"#{@id}\" Version=\"2.0\" IssueInstant=\"#{issue_instant}\"> " +
|
20
|
+
"<saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">#{@settings.issuer}</saml:Issuer>" +
|
21
|
+
"<saml:NameID xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" NameQualifier=\"#{@session[:name_qualifier]}\" SPNameQualifier=\"#{@settings.issuer}\" Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:transient\">#{@session[:name_id]}</saml:NameID>" +
|
22
|
+
"<samlp:SessionIndex xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\">#{@session[:session_index]}</samlp:SessionIndex>" +
|
23
|
+
"</samlp:LogoutRequest>"
|
12
24
|
|
13
|
-
deflated_logout_request = Zlib::Deflate.deflate(
|
25
|
+
deflated_logout_request = Zlib::Deflate.deflate(@request_xml, 9)[2..-5]
|
14
26
|
base64_logout_request = Base64.encode64(deflated_logout_request)
|
15
27
|
encoded_logout_request = CGI.escape(base64_logout_request)
|
16
28
|
|
17
|
-
|
29
|
+
@forward_url = @settings.idp_slo_target_url + "?SAMLRequest=" + encoded_logout_request
|
18
30
|
|
19
|
-
|
31
|
+
@forward_url
|
20
32
|
end
|
21
33
|
end
|
22
34
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Onelogin::Saml
|
2
|
+
class LogoutResponse
|
3
|
+
|
4
|
+
attr_reader :settings, :document, :xml, :response
|
5
|
+
attr_reader :status_code, :status_message
|
6
|
+
attr_reader :in_response_to, :destination
|
7
|
+
def initialize(response, settings)
|
8
|
+
@response = response
|
9
|
+
@settings = settings
|
10
|
+
|
11
|
+
@xml = Base64.decode64(@response)
|
12
|
+
zlib = Zlib::Inflate.new(-Zlib::MAX_WBITS)
|
13
|
+
@xml = zlib.inflate(@xml)
|
14
|
+
@document = XMLSecurity::SignedDocument.new(@xml)
|
15
|
+
|
16
|
+
@in_response_to = REXML::XPath.first(@document, "/samlp:LogoutResponse", Onelogin::NAMESPACES).attributes['InResponseTo'] rescue nil
|
17
|
+
@destination = REXML::XPath.first(@document, "/samlp:LogoutResponse", Onelogin::NAMESPACES).attributes['Destination'] rescue nil
|
18
|
+
@status_code = REXML::XPath.first(@document, "/samlp:LogoutResponse/samlp:Status/samlp:StatusCode", Onelogin::NAMESPACES).attributes["Value"] rescue nil
|
19
|
+
@status_message = REXML::XPath.first(@document, "/samlp:LogoutResponse/samlp:Status/samlp:StatusCode", Onelogin::NAMESPACES).text rescue nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def logger=(val)
|
23
|
+
@logger = val
|
24
|
+
end
|
25
|
+
|
26
|
+
def success_status?
|
27
|
+
@status_code == Onelogin::Saml::StatusCodes::SUCCESS_URI
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -1,9 +1,10 @@
|
|
1
1
|
module Onelogin::Saml
|
2
2
|
class Response
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
attr_reader :settings, :document, :xml, :response
|
5
|
+
attr_reader :name_id, :name_qualifier, :session_index
|
6
|
+
attr_reader :status_code, :status_message
|
7
|
+
attr_reader :in_response_to, :destination
|
7
8
|
def initialize(response, settings)
|
8
9
|
@response = response
|
9
10
|
@settings = settings
|
@@ -12,6 +13,8 @@ module Onelogin::Saml
|
|
12
13
|
@document = XMLSecurity::SignedDocument.new(@xml)
|
13
14
|
@document.decrypt(@settings)
|
14
15
|
|
16
|
+
@in_response_to = REXML::XPath.first(@document, "/samlp:Response", Onelogin::NAMESPACES).attributes['InResponseTo'] rescue nil
|
17
|
+
@destination = REXML::XPath.first(@document, "/samlp:Response", Onelogin::NAMESPACES).attributes['Destination'] rescue nil
|
15
18
|
@name_id = REXML::XPath.first(@document, "/samlp:Response/saml:Assertion/saml:Subject/saml:NameID", Onelogin::NAMESPACES).text rescue nil
|
16
19
|
@name_qualifier = REXML::XPath.first(@document, "/samlp:Response/saml:Assertion/saml:Subject/saml:NameID", Onelogin::NAMESPACES).attributes["NameQualifier"] rescue nil
|
17
20
|
@session_index = REXML::XPath.first(@document, "/samlp:Response/saml:Assertion/saml:AuthnStatement", Onelogin::NAMESPACES).attributes["SessionIndex"] rescue nil
|
@@ -24,8 +27,10 @@ module Onelogin::Saml
|
|
24
27
|
end
|
25
28
|
|
26
29
|
def is_valid?
|
27
|
-
|
30
|
+
if !@response.blank? && @document.elements["//ds:X509Certificate"]
|
28
31
|
@document.validate(@settings.idp_cert_fingerprint, @logger) unless !@settings.idp_cert_fingerprint
|
32
|
+
else
|
33
|
+
false
|
29
34
|
end
|
30
35
|
end
|
31
36
|
|
@@ -40,5 +45,15 @@ module Onelogin::Saml
|
|
40
45
|
def no_authn_context?
|
41
46
|
@status_code == Onelogin::Saml::StatusCodes::NO_AUTHN_CONTEXT_URI
|
42
47
|
end
|
48
|
+
|
49
|
+
def fingerprint_from_idp
|
50
|
+
if base64_cert = @document.elements["//ds:X509Certificate"]
|
51
|
+
cert_text = Base64.decode64(base64_cert.text)
|
52
|
+
cert = OpenSSL::X509::Certificate.new(cert_text)
|
53
|
+
Digest::SHA1.hexdigest(cert.to_der)
|
54
|
+
else
|
55
|
+
nil
|
56
|
+
end
|
57
|
+
end
|
43
58
|
end
|
44
59
|
end
|
data/ruby-saml-mod.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
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.6"
|
4
4
|
|
5
5
|
s.authors = ["OneLogin LLC", "Bracken", "Zach"]
|
6
6
|
s.date = %q{2012-01-26}
|
@@ -14,6 +14,7 @@ Gem::Specification.new do |s|
|
|
14
14
|
"lib/onelogin/saml/auth_request.rb",
|
15
15
|
"lib/onelogin/saml/authn_contexts.rb",
|
16
16
|
"lib/onelogin/saml/log_out_request.rb",
|
17
|
+
"lib/onelogin/saml/logout_response.rb",
|
17
18
|
"lib/onelogin/saml/meta_data.rb",
|
18
19
|
"lib/onelogin/saml/name_identifiers.rb",
|
19
20
|
"lib/onelogin/saml/response.rb",
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-saml-mod
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 6
|
10
|
+
version: 0.1.6
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- OneLogin LLC
|
@@ -35,6 +35,7 @@ files:
|
|
35
35
|
- lib/onelogin/saml/auth_request.rb
|
36
36
|
- lib/onelogin/saml/authn_contexts.rb
|
37
37
|
- lib/onelogin/saml/log_out_request.rb
|
38
|
+
- lib/onelogin/saml/logout_response.rb
|
38
39
|
- lib/onelogin/saml/meta_data.rb
|
39
40
|
- lib/onelogin/saml/name_identifiers.rb
|
40
41
|
- lib/onelogin/saml/response.rb
|