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.
@@ -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
- id = Onelogin::Saml::AuthRequest.generate_unique_id(42)
5
- issue_instant = Onelogin::Saml::AuthRequest.get_timestamp
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
- request =
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
- request += "<samlp:RequestedAuthnContext xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" Comparison=\"exact\">"
14
- request += "<saml:AuthnContextClassRef xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">#{settings.requested_authn_context}</saml:AuthnContextClassRef>"
15
- request += "</samlp:RequestedAuthnContext>\n"
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
- request += "</samlp:AuthnRequest>"
30
+ @request_xml += "</samlp:AuthnRequest>"
19
31
 
20
- deflated_request = Zlib::Deflate.deflate(request, 9)[2..-5]
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
- id = Onelogin::Saml::AuthRequest.generate_unique_id(42)
5
- issue_instant = Onelogin::Saml::AuthRequest.get_timestamp
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
- logout_request = "<samlp:LogoutRequest xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" ID=\"#{id}\" Version=\"2.0\" IssueInstant=\"#{issue_instant}\"> " +
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(logout_request, 9)[2..-5]
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
- redirect_url = settings.idp_slo_target_url + "?SAMLRequest=" + encoded_logout_request
29
+ @forward_url = @settings.idp_slo_target_url + "?SAMLRequest=" + encoded_logout_request
18
30
 
19
- return redirect_url
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
- attr_accessor :settings, :document, :xml, :response
5
- attr_accessor :name_id, :name_qualifier, :session_index
6
- attr_accessor :status_code, :status_message
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
- unless @response.blank?
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
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = %q{ruby-saml-mod}
3
- s.version = "0.1.5"
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: 17
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 5
10
- version: 0.1.5
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