Skip to content

Commit

Permalink
More progress
Browse files Browse the repository at this point in the history
  • Loading branch information
johnnyshields committed Jul 10, 2024
1 parent d163dfd commit e055168
Show file tree
Hide file tree
Showing 3 changed files with 377 additions and 357 deletions.
1 change: 1 addition & 0 deletions test/logoutrequest_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ class RequestTest < Minitest::Test
end

it "raises error when no valid certs and :check_sp_cert_expiration is true" do
settings.certificate, settings.private_key = CertificateHelper.generate_pem_array(algorithm, not_after: Time.now - 60)
settings.security[:check_sp_cert_expiration] = true

assert_raises(RubySaml::ValidationError, 'The SP certificate expired.') do
Expand Down
313 changes: 160 additions & 153 deletions test/request_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -240,159 +240,6 @@ class RequestTest < Minitest::Test
assert_match(/<saml:AuthnContextDeclRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport<\/saml:AuthnContextDeclRef>/, auth_doc.to_s)
end

describe "#create_params signing with HTTP-POST binding" do
before do
settings.idp_sso_service_url = "http://example.com?field=value"
settings.idp_sso_service_binding = :post
settings.security[:authn_requests_signed] = true
settings.certificate = ruby_saml_cert_text
settings.private_key = ruby_saml_key_text
end

it "create a signed request" do
params = RubySaml::Authrequest.new.create_params(settings)
request_xml = Base64.decode64(params["SAMLRequest"])
assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], request_xml
assert_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'/>], request_xml
end

it "create a signed request with 256 digest and signature methods" do
settings.security[:signature_method] = RubySaml::XML::Document::RSA_SHA256
settings.security[:digest_method] = RubySaml::XML::Document::SHA512

params = RubySaml::Authrequest.new.create_params(settings)

request_xml = Base64.decode64(params["SAMLRequest"])
assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], request_xml
assert_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'/>], request_xml
assert_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2001/04/xmlenc#sha512'/>], request_xml
end

it "creates a signed request using the first certificate and key" do
settings.certificate = nil
settings.private_key = nil
settings.sp_cert_multi = {
signing: [
{ certificate: ruby_saml_cert_text, private_key: ruby_saml_key_text },
CertificateHelper.generate_pem_hash
]
}

params = RubySaml::Authrequest.new.create_params(settings)

request_xml = Base64.decode64(params["SAMLRequest"])
assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], request_xml
assert_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'/>], request_xml
end

it "creates a signed request using the first valid certificate and key when :check_sp_cert_expiration is true" do
settings.certificate = nil
settings.private_key = nil
settings.security[:check_sp_cert_expiration] = true
settings.sp_cert_multi = {
signing: [
{ certificate: ruby_saml_cert_text, private_key: ruby_saml_key_text },
CertificateHelper.generate_pem_hash
]
}

params = RubySaml::Authrequest.new.create_params(settings)

request_xml = Base64.decode64(params["SAMLRequest"])
assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], request_xml
assert_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'/>], request_xml
end

it "raises error when no valid certs and :check_sp_cert_expiration is true" do
settings.security[:check_sp_cert_expiration] = true

assert_raises(RubySaml::ValidationError, 'The SP certificate expired.') do
RubySaml::Authrequest.new.create_params(settings)
end
end
end

describe "#create_params signing with HTTP-Redirect binding" do
let(:cert) { OpenSSL::X509::Certificate.new(ruby_saml_cert_text) }

before do
settings.idp_sso_service_url = "http://example.com?field=value"
settings.idp_sso_service_binding = :redirect
settings.assertion_consumer_service_binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign"
settings.security[:authn_requests_signed] = true
settings.certificate = ruby_saml_cert_text
settings.private_key = ruby_saml_key_text
end

it "create a signature parameter with RSA_SHA1 and validate it" do
settings.security[:signature_method] = RubySaml::XML::Document::RSA_SHA1

params = RubySaml::Authrequest.new.create_params(settings, :RelayState => 'http://example.com')
assert params['SAMLRequest']
assert params[:RelayState]
assert params['Signature']
assert_equal params['SigAlg'], RubySaml::XML::Document::RSA_SHA1

query_string = "SAMLRequest=#{CGI.escape(params['SAMLRequest'])}"
query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"

signature_algorithm = RubySaml::XML::Crypto.hash_algorithm(params['SigAlg'])
assert_equal signature_algorithm, OpenSSL::Digest::SHA1
assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
end

it "create a signature parameter with RSA_SHA256 and validate it" do
settings.security[:signature_method] = RubySaml::XML::Document::RSA_SHA256

params = RubySaml::Authrequest.new.create_params(settings, :RelayState => 'http://example.com')
assert params['Signature']
assert_equal params['SigAlg'], RubySaml::XML::Document::RSA_SHA256

query_string = "SAMLRequest=#{CGI.escape(params['SAMLRequest'])}"
query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"

signature_algorithm = RubySaml::XML::Crypto.hash_algorithm(params['SigAlg'])
assert_equal signature_algorithm, OpenSSL::Digest::SHA256
assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
end

it "create a signature parameter using the first certificate and key" do
settings.security[:signature_method] = RubySaml::XML::Document::RSA_SHA1
settings.certificate = nil
settings.private_key = nil
settings.sp_cert_multi = {
signing: [
{ certificate: ruby_saml_cert_text, private_key: ruby_saml_key_text },
CertificateHelper.generate_pem_hash
]
}

params = RubySaml::Authrequest.new.create_params(settings, :RelayState => 'http://example.com')
assert params['SAMLRequest']
assert params[:RelayState]
assert params['Signature']
assert_equal params['SigAlg'], RubySaml::XML::Document::RSA_SHA1

query_string = "SAMLRequest=#{CGI.escape(params['SAMLRequest'])}"
query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"

signature_algorithm = RubySaml::XML::Crypto.hash_algorithm(params['SigAlg'])
assert_equal signature_algorithm, OpenSSL::Digest::SHA1
assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
end

it "raises error when no valid certs and :check_sp_cert_expiration is true" do
settings.security[:check_sp_cert_expiration] = true

assert_raises(RubySaml::ValidationError, 'The SP certificate expired.') do
RubySaml::Authrequest.new.create_params(settings, :RelayState => 'http://example.com')
end
end
end

it "create the saml:AuthnContextClassRef element correctly" do
settings.authn_context = 'secure/name/password/uri'
auth_doc = RubySaml::Authrequest.new.create_authentication_xml_doc(settings)
Expand Down Expand Up @@ -437,5 +284,165 @@ class RequestTest < Minitest::Test
assert_equal "new_uuid", authnrequest.request_id
end
end

with_each_key_algorithm do |algorithm|
describe "#create_params signing with HTTP-POST binding" do
before do
settings.idp_sso_service_url = "http://example.com?field=value"
settings.idp_sso_service_binding = :post
settings.security[:authn_requests_signed] = true
settings.certificate, settings.private_key = CertificateHelper.generate_pem_array(algorithm)
end

it "create a signed request" do
params = RubySaml::Authrequest.new.create_params(settings)
request_xml = Base64.decode64(params["SAMLRequest"])
assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], request_xml
assert_match signature_method_matcher(algorithm), request_xml
assert_match %r[<ds:DigestMethod Algorithm='http://www\.w3\.org/2001/04/xmlenc#sha256'/>], request_xml
end

it "create a signed request with 256 digest and signature methods" do
settings.security[:signature_method] = RubySaml::XML::Document::RSA_SHA256
settings.security[:digest_method] = RubySaml::XML::Document::SHA512

params = RubySaml::Authrequest.new.create_params(settings)

request_xml = Base64.decode64(params["SAMLRequest"])
assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], request_xml
assert_match signature_method_matcher(algorithm), request_xml
assert_match %r[<ds:DigestMethod Algorithm='http://www\.w3\.org/2001/04/xmlenc#sha512'/>], request_xml
end

it "creates a signed request using the first certificate and key" do
settings.certificate = nil
settings.private_key = nil
settings.sp_cert_multi = {
signing: [
CertificateHelper.generate_pem_hash(algorithm),
CertificateHelper.generate_pem_hash
]
}

params = RubySaml::Authrequest.new.create_params(settings)

request_xml = Base64.decode64(params["SAMLRequest"])
assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], request_xml
assert_match signature_method_matcher(algorithm), request_xml
assert_match %r[<ds:DigestMethod Algorithm='http://www\.w3\.org/2001/04/xmlenc#sha256'/>], request_xml
end

it "creates a signed request using the first valid certificate and key when :check_sp_cert_expiration is true" do
settings.certificate = nil
settings.private_key = nil
settings.security[:check_sp_cert_expiration] = true
settings.sp_cert_multi = {
signing: [
CertificateHelper.generate_pem_hash(algorithm),
CertificateHelper.generate_pem_hash
]
}

params = RubySaml::Authrequest.new.create_params(settings)

request_xml = Base64.decode64(params["SAMLRequest"])
assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], request_xml
assert_match signature_method_matcher(algorithm), request_xml
assert_match %r[<ds:DigestMethod Algorithm='http://www\.w3\.org/2001/04/xmlenc#sha256'/>], request_xml
end

it "raises error when no valid certs and :check_sp_cert_expiration is true" do
settings.certificate, settings.private_key = CertificateHelper.generate_pem_array(algorithm, not_after: Time.now - 60)
settings.security[:check_sp_cert_expiration] = true

assert_raises(RubySaml::ValidationError, 'The SP certificate expired.') do
RubySaml::Authrequest.new.create_params(settings)
end
end
end

describe "#create_params signing with HTTP-Redirect binding" do
let(:cert) { OpenSSL::X509::Certificate.new(ruby_saml_cert_text) }

before do
settings.idp_sso_service_url = "http://example.com?field=value"
settings.idp_sso_service_binding = :redirect
settings.assertion_consumer_service_binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign"
settings.security[:authn_requests_signed] = true
settings.certificate = ruby_saml_cert_text
settings.private_key = ruby_saml_key_text
end

it "create a signature parameter with RSA_SHA1 and validate it" do
settings.security[:signature_method] = RubySaml::XML::Document::RSA_SHA1

params = RubySaml::Authrequest.new.create_params(settings, :RelayState => 'http://example.com')
assert params['SAMLRequest']
assert params[:RelayState]
assert params['Signature']
assert_equal params['SigAlg'], RubySaml::XML::Document::RSA_SHA1

query_string = "SAMLRequest=#{CGI.escape(params['SAMLRequest'])}"
query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"

signature_algorithm = RubySaml::XML::Crypto.hash_algorithm(params['SigAlg'])
assert_equal signature_algorithm, OpenSSL::Digest::SHA1
assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
end

it "create a signature parameter with RSA_SHA256 and validate it" do
settings.security[:signature_method] = RubySaml::XML::Document::RSA_SHA256

params = RubySaml::Authrequest.new.create_params(settings, :RelayState => 'http://example.com')
assert params['Signature']
assert_equal params['SigAlg'], RubySaml::XML::Document::RSA_SHA256

query_string = "SAMLRequest=#{CGI.escape(params['SAMLRequest'])}"
query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"

signature_algorithm = RubySaml::XML::Crypto.hash_algorithm(params['SigAlg'])
assert_equal signature_algorithm, OpenSSL::Digest::SHA256
assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
end

it "create a signature parameter using the first certificate and key" do
settings.security[:signature_method] = RubySaml::XML::Document::RSA_SHA1
settings.certificate = nil
settings.private_key = nil
cert, pkey = CertificateHelper.generate_pair(algorithm)
settings.sp_cert_multi = {
signing: [
{ certificate: cert.to_pem, private_key: pkey.to_pem },
CertificateHelper.generate_pem_hash
]
}

params = RubySaml::Authrequest.new.create_params(settings, :RelayState => 'http://example.com')
assert params['SAMLRequest']
assert params[:RelayState]
assert params['Signature']
assert_equal params['SigAlg'], signature_method(algorithm, :sha1)

query_string = "SAMLRequest=#{CGI.escape(params['SAMLRequest'])}"
query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"

signature_algorithm = RubySaml::XML::Crypto.hash_algorithm(params['SigAlg'])
assert_equal signature_algorithm, OpenSSL::Digest::SHA1
assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
end

it "raises error when no valid certs and :check_sp_cert_expiration is true" do
settings.certificate, settings.private_key = CertificateHelper.generate_pem_array(algorithm, not_after: Time.now - 60)
settings.security[:check_sp_cert_expiration] = true

assert_raises(RubySaml::ValidationError, 'The SP certificate expired.') do
RubySaml::Authrequest.new.create_params(settings, :RelayState => 'http://example.com')
end
end
end
end
end
end
Loading

0 comments on commit e055168

Please sign in to comment.