lib/saml/kit/builders/response.rb in saml-kit-0.2.2 vs lib/saml/kit/builders/response.rb in saml-kit-0.2.3
- old
+ new
@@ -1,15 +1,17 @@
module Saml
module Kit
module Builders
class Response
+ include Templatable
attr_reader :user, :request
attr_accessor :id, :reference_id, :now
attr_accessor :version, :status_code
attr_accessor :issuer, :sign, :destination, :encrypt
+ attr_reader :configuration
- def initialize(user, request)
+ def initialize(user, request, configuration: Saml::Kit.configuration)
@user = user
@request = request
@id = Id.generate
@reference_id = Id.generate
@now = Time.now.utc
@@ -17,164 +19,50 @@
@status_code = Namespaces::SUCCESS
@issuer = configuration.issuer
@destination = destination_for(request)
@sign = want_assertions_signed
@encrypt = false
+ @configuration = configuration
end
def want_assertions_signed
request.provider.want_assertions_signed
rescue => error
Saml::Kit.logger.error(error)
true
end
- def to_xml
- Signature.sign(sign: sign) do |xml, signature|
- xml.Response response_options do
- xml.Issuer(issuer, xmlns: Namespaces::ASSERTION)
- signature.template(id)
- xml.Status do
- xml.StatusCode Value: status_code
- end
- assertion(xml, signature)
- end
- end
- end
-
def build
Saml::Kit::Response.new(to_xml, request_id: request.id)
end
private
- def assertion(xml, signature)
- with_encryption(xml) do |xml|
- xml.Assertion(assertion_options) do
- xml.Issuer issuer
- signature.template(reference_id) unless encrypt
- xml.Subject do
- xml.NameID user.name_id_for(request.name_id_format), Format: request.name_id_format
- xml.SubjectConfirmation Method: Namespaces::BEARER do
- xml.SubjectConfirmationData "", subject_confirmation_data_options
- end
- end
- xml.Conditions conditions_options do
- xml.AudienceRestriction do
- xml.Audience request.issuer
- end
- end
- xml.AuthnStatement authn_statement_options do
- xml.AuthnContext do
- xml.AuthnContextClassRef Namespaces::PASSWORD
- end
- end
- assertion_attributes = user.assertion_attributes_for(request)
- if assertion_attributes.any?
- xml.AttributeStatement do
- assertion_attributes.each do |key, value|
- xml.Attribute Name: key, NameFormat: Namespaces::URI, FriendlyName: key do
- xml.AttributeValue value.to_s
- end
- end
- end
- end
- end
- end
+ def assertion
+ @assertion ||= Saml::Kit::Builders::Assertion.new(self)
end
- def with_encryption(xml)
- if encrypt
- temp = ::Builder::XmlMarkup.new
- yield temp
- raw_xml_to_encrypt = temp.target!
-
- encryption_certificate = request.provider.encryption_certificates.first
- public_key = encryption_certificate.public_key
-
- cipher = OpenSSL::Cipher.new('AES-256-CBC')
- cipher.encrypt
- key = cipher.random_key
- iv = cipher.random_iv
- encrypted = cipher.update(raw_xml_to_encrypt) + cipher.final
-
- Saml::Kit.logger.debug ['+iv', iv].inspect
- Saml::Kit.logger.debug ['+key', key].inspect
-
- xml.EncryptedAssertion xmlns: Namespaces::ASSERTION do
- xml.EncryptedData xmlns: Namespaces::XMLENC do
- xml.EncryptionMethod Algorithm: "http://www.w3.org/2001/04/xmlenc#aes256-cbc"
- xml.KeyInfo xmlns: Namespaces::XMLDSIG do
- xml.EncryptedKey xmlns: Namespaces::XMLENC do
- xml.EncryptionMethod Algorithm: "http://www.w3.org/2001/04/xmlenc#rsa-1_5"
- xml.CipherData do
- xml.CipherValue Base64.encode64(public_key.public_encrypt(key))
- end
- end
- end
- xml.CipherData do
- xml.CipherValue Base64.encode64(iv + encrypted)
- end
- end
- end
- else
- yield xml
- end
+ def encryption_certificate
+ request.provider.encryption_certificates.first
end
def destination_for(request)
if request.signed? && request.trusted?
request.assertion_consumer_service_url || request.provider.assertion_consumer_service_for(binding: :http_post).try(:location)
else
request.provider.assertion_consumer_service_for(binding: :http_post).try(:location)
end
end
- def configuration
- Saml::Kit.configuration
- end
-
def response_options
{
ID: id,
Version: version,
IssueInstant: now.iso8601,
Destination: destination,
Consent: Namespaces::UNSPECIFIED,
InResponseTo: request.id,
xmlns: Namespaces::PROTOCOL,
- }
- end
-
- def assertion_options
- {
- ID: reference_id,
- IssueInstant: now.iso8601,
- Version: "2.0",
- xmlns: Namespaces::ASSERTION,
- }
- end
-
- def subject_confirmation_data_options
- {
- InResponseTo: request.id,
- NotOnOrAfter: 3.hours.since(now).utc.iso8601,
- Recipient: request.assertion_consumer_service_url,
- }
- end
-
- def conditions_options
- {
- NotBefore: now.utc.iso8601,
- NotOnOrAfter: Saml::Kit.configuration.session_timeout.from_now.utc.iso8601,
- }
- end
-
- def authn_statement_options
- {
- AuthnInstant: now.iso8601,
- SessionIndex: assertion_options[:ID],
- SessionNotOnOrAfter: 3.hours.since(now).utc.iso8601,
}
end
end
end
end