I am currently integrating SAML authentication into a Ruby on Rails application using the Devise SAML Authenticatable gem, and I’ve encountered a significant challenge regarding the signature verification of SAML messages.
While I have experience with Devise, the SAML integration part is quite new to me. My main issue arises with ensuring that my application can securely authenticate users via a SAML IdP and that all SAML messages are properly signed as required by the IdP.
Here is the relevant part of my SAML configuration:
config.saml_configure do |settings|
private_key_path = Rails.root.join('config', 'cert', 'private.pem')
certificate_path = Rails.root.join('config', 'cert', 'certificate.crt')
idp_cert_path = Rails.root.join('config', 'cert', 'sts_example.cer')
if File.exist?(private_key_path) && File.exist?(certificate_path) && File.exist?(idp_cert_path)
settings.private_key = File.read(private_key_path)
settings.certificate = File.read(certificate_path)
settings.idp_cert = File.read(idp_cert_path)
else
Rails.logger.error "SAML configuration error: One or more certificate files are missing."
end
settings.assertion_consumer_service_url = ENV.fetch('WSFED_REPLY_URL', 'https://dev.example.com/users/sso/auth')
settings.issuer = 'https://dev.example.com/users/sso/metadata'
settings.assertion_consumer_service_binding = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'
settings.name_identifier_format = 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
settings.sp_entity_id = ENV['WSFED_ISSUER']
settings.idp_slo_service_url = ENV['WSFED_SLO_URL']
settings.idp_slo_target_url = ENV['WSFED_SLO_URL']
settings.idp_sso_service_url = ENV['WSFED_SSO_URL']
settings.idp_sso_target_url = ENV['WSFED_SSO_URL']
settings.idp_cert_fingerprint_algorithm = 'http://www.w3.org/2000/09/xmldsig#sha256'
settings.authn_context = ""
settings.idp_cert_fingerprint = "HEX"
settings.security[:authn_requests_signed] = true
settings.security[:logout_requests_signed] = true
settings.security[:logout_responses_signed] = true
settings.security[:want_assertions_signed] = true
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256
end
Despite this configuration, I receive an error from the IdP (AD FS server) indicating that the SAML authentication request is not signed:
Détails de l'exception :
Microsoft.IdentityModel.Protocols.XmlSignature.SignatureVerificationFailedException: MSIS0038 : le message SAML a une signature erronée. Émetteur : « http://example.com/adfs/services/trust ».