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.
@@ -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