ruby-saml-mod 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|