Commit 4bf714a
Changed files (8)
lib/saml/kit/logout_request.rb
@@ -19,6 +19,10 @@ module Saml
@xml_hash = Hash.from_xml(xml)
end
+ def id
+ to_h[name]['ID']
+ end
+
def issuer
to_h[name]['Issuer']
end
@@ -85,6 +89,10 @@ module Saml
Saml::Kit::Content.encode_raw_saml(to_xml)
end
+ def response_for(user)
+ LogoutResponse::Builder.new(user, self).build
+ end
+
private
def registry
lib/saml/kit/logout_response.rb
@@ -0,0 +1,95 @@
+
+module Saml
+ module Kit
+ class LogoutResponse
+ attr_reader :content, :name
+
+ def initialize(xml)
+ @content = xml
+ @name = 'LogoutResponse'
+ @xml_hash = Hash.from_xml(xml)
+ end
+
+ def id
+ to_h[name]['ID']
+ end
+
+ def issue_instant
+ to_h[name]['IssueInstant']
+ end
+
+ def version
+ to_h[name]['Version']
+ end
+
+ def issuer
+ to_h[name]['Issuer']
+ end
+
+ def status_code
+ to_h[name]['Status']['StatusCode']['Value']
+ end
+
+ def in_response_to
+ to_h[name]['InResponseTo']
+ end
+
+ def destination
+ to_h[name]['Destination']
+ end
+
+ def to_h
+ @xml_hash
+ end
+
+ def to_xml
+ content
+ end
+
+ class Builder
+ attr_accessor :id, :issuer, :version, :status_code, :sign, :now
+ attr_reader :request
+
+ def initialize(user, request, configuration: Saml::Kit.configuration, sign: true)
+ @user = user
+ @now = Time.now.utc
+ @request = request
+ @id = SecureRandom.uuid
+ @version = "2.0"
+ @status_code = Namespaces::SUCCESS
+ @sign = sign
+ @issuer = configuration.issuer
+ end
+
+ def to_xml
+ Signature.sign(id, sign: sign) do |xml, signature|
+ xml.LogoutResponse logout_response_options do
+ xml.Issuer(issuer, xmlns: Namespaces::ASSERTION)
+ signature.template(xml)
+ xml.Status do
+ xml.StatusCode Value: status_code
+ end
+ end
+ end
+ end
+
+ def build
+ LogoutResponse.new(to_xml)
+ end
+
+ private
+
+ def logout_response_options
+ {
+ xmlns: Namespaces::PROTOCOL,
+ ID: "_#{id}",
+ Version: "2.0",
+ IssueInstant: now.utc.iso8601,
+ Destination: "",
+ InResponseTo: request.id,
+ }
+ end
+ end
+ end
+ end
+end
lib/saml/kit/response.rb
@@ -56,7 +56,7 @@ module Saml
end].with_indifferent_access
end
- def acs_url
+ def destination
to_h.fetch(name, {}).fetch('Destination', nil)
end
lib/saml/kit.rb
@@ -18,6 +18,7 @@ require "saml/kit/configuration"
require "saml/kit/content"
require "saml/kit/default_registry"
require "saml/kit/fingerprint"
+require "saml/kit/logout_response"
require "saml/kit/logout_request"
require "saml/kit/namespaces"
require "saml/kit/metadata"
spec/saml/authentication_request_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Saml::Kit::AuthenticationRequest do
let(:raw_xml) do
builder = described_class::Builder.new
builder.id = id
- builder.issued_at = Time.now.utc
+ builder.now = Time.now.utc
builder.issuer = issuer
builder.acs_url = acs_url
builder.name_id_format = name_id_format
spec/saml/logout_request_spec.rb
@@ -157,4 +157,11 @@ RSpec.describe Saml::Kit::LogoutRequest do
expect(result.to_xml).to eql(subject.to_xml)
end
end
+
+ describe "#response_for" do
+ it 'returns a logout response for a particular user' do
+ user = double(:user)
+ expect(subject.response_for(user)).to be_instance_of(Saml::Kit::LogoutResponse)
+ end
+ end
end
spec/saml/logout_response_spec.rb
@@ -0,0 +1,26 @@
+require 'spec_helper'
+
+RSpec.describe Saml::Kit::LogoutResponse do
+ describe described_class::Builder do
+ subject { described_class.new(user, request, configuration: configuration) }
+ let(:configuration) { double(issuer: issuer) }
+ let(:user) { double(:user, name_id_for: SecureRandom.uuid) }
+ let(:request) { Saml::Kit::LogoutRequest::Builder.new(user).build }
+ let(:issuer) { FFaker::Internet.http_url }
+
+ describe "#build" do
+ it 'builds a logout response' do
+ travel_to 1.second.from_now
+
+ result = subject.build
+ expect(result.id).to be_present
+ expect(result.issue_instant).to eql(Time.now.utc.iso8601)
+ expect(result.version).to eql("2.0")
+ expect(result.issuer).to eql(issuer)
+ expect(result.status_code).to eql(Saml::Kit::Namespaces::SUCCESS)
+ expect(result.in_response_to).to eql(request.id)
+ expect(result.destination).to be_present
+ end
+ end
+ end
+end
spec/saml/response_spec.rb
@@ -1,14 +1,14 @@
require 'spec_helper'
RSpec.describe Saml::Kit::Response do
- describe "#acs_url" do
+ describe "#destination" do
let(:acs_url) { "https://#{FFaker::Internet.domain_name}/acs" }
let(:user) { double(:user, name_id_for: SecureRandom.uuid, assertion_attributes_for: { }) }
let(:request) { instance_double(Saml::Kit::AuthenticationRequest, id: SecureRandom.uuid, acs_url: acs_url, issuer: FFaker::Movie.title, name_id_format: Saml::Kit::Namespaces::EMAIL_ADDRESS, provider: nil) }
subject { described_class::Builder.new(user, request).build }
it 'returns the acs_url' do
- expect(subject.acs_url).to eql(acs_url)
+ expect(subject.destination).to eql(acs_url)
end
end