Commit 9e2bf2b
Changed files (11)
lib
saml
kit
exe/saml-kit-decode-http-post
@@ -3,6 +3,6 @@ require 'saml/kit'
saml = STDIN.read
-binding = Saml::Kit::HttpPostBinding.new(location: '')
+binding = Saml::Kit::Bindings::HttpPost.new(location: '')
xml = binding.deserialize('SAMLRequest' => saml).to_xml
puts Nokogiri::XML(xml).to_xml(indent: 2)
lib/saml/kit/bindings/binding.rb
@@ -1,38 +1,40 @@
module Saml
module Kit
- class Binding
- attr_reader :binding, :location
+ module Bindings
+ class Binding
+ attr_reader :binding, :location
- def initialize(binding:, location:)
- @binding = binding
- @location = location
- end
+ def initialize(binding:, location:)
+ @binding = binding
+ @location = location
+ end
- def binding?(other)
- binding == other
- end
+ def binding?(other)
+ binding == other
+ end
- def serialize(builder, relay_state: nil)
- []
- end
+ def serialize(builder, relay_state: nil)
+ []
+ end
- def deserialize(params)
- raise ArgumentError.new("Unsupported binding")
- end
+ def deserialize(params)
+ raise ArgumentError.new("Unsupported binding")
+ end
- def to_h
- { binding: binding, location: location }
- end
+ def to_h
+ { binding: binding, location: location }
+ end
- protected
+ protected
- def saml_param_from(params)
- if params['SAMLRequest'].present?
- params['SAMLRequest']
- elsif params['SAMLResponse'].present?
- params['SAMLResponse']
- else
- raise ArgumentError.new("SAMLRequest or SAMLResponse parameter is required.")
+ def saml_param_from(params)
+ if params['SAMLRequest'].present?
+ params['SAMLRequest']
+ elsif params['SAMLResponse'].present?
+ params['SAMLResponse']
+ else
+ raise ArgumentError.new("SAMLRequest or SAMLResponse parameter is required.")
+ end
end
end
end
lib/saml/kit/bindings/http_post.rb
@@ -1,26 +1,28 @@
module Saml
module Kit
- class HttpPostBinding < Binding
- include Serializable
+ module Bindings
+ class HttpPost < Binding
+ include Serializable
- def initialize(location:)
- super(binding: Saml::Kit::Namespaces::HTTP_POST, location: location)
- end
+ def initialize(location:)
+ super(binding: Saml::Kit::Namespaces::HTTP_POST, location: location)
+ end
- def serialize(builder, relay_state: nil)
- builder.sign = true
- builder.destination = location
- document = builder.build
- saml_params = {
- document.query_string_parameter => Base64.strict_encode64(document.to_xml),
- }
- saml_params['RelayState'] = relay_state if relay_state.present?
- [location, saml_params]
- end
+ def serialize(builder, relay_state: nil)
+ builder.sign = true
+ builder.destination = location
+ document = builder.build
+ saml_params = {
+ document.query_string_parameter => Base64.strict_encode64(document.to_xml),
+ }
+ saml_params['RelayState'] = relay_state if relay_state.present?
+ [location, saml_params]
+ end
- def deserialize(params)
- xml = decode(saml_param_from(params))
- Saml::Kit::Document.to_saml_document(xml)
+ def deserialize(params)
+ xml = decode(saml_param_from(params))
+ Saml::Kit::Document.to_saml_document(xml)
+ end
end
end
end
lib/saml/kit/bindings/http_redirect.rb
@@ -1,57 +1,59 @@
module Saml
module Kit
- class HttpRedirectBinding < Binding
- include Serializable
+ module Bindings
+ class HttpRedirect < Binding
+ include Serializable
- def initialize(location:)
- super(binding: Saml::Kit::Namespaces::HTTP_REDIRECT, location: location)
- end
+ def initialize(location:)
+ super(binding: Saml::Kit::Namespaces::HTTP_REDIRECT, location: location)
+ end
- def serialize(builder, relay_state: nil)
- builder.sign = false
- builder.destination = location
- document = builder.build
- [UrlBuilder.new.build(document, relay_state: relay_state), {}]
- end
+ def serialize(builder, relay_state: nil)
+ builder.sign = false
+ builder.destination = location
+ document = builder.build
+ [UrlBuilder.new.build(document, relay_state: relay_state), {}]
+ end
- def deserialize(params)
- document = deserialize_document_from!(params)
- ensure_valid_signature!(params, document)
- document.signature_verified!
- document
- end
+ def deserialize(params)
+ document = deserialize_document_from!(params)
+ ensure_valid_signature!(params, document)
+ document.signature_verified!
+ document
+ end
- private
+ private
- def deserialize_document_from!(params)
- xml = inflate(decode(unescape(saml_param_from(params))))
- Saml::Kit.logger.debug(xml)
- Saml::Kit::Document.to_saml_document(xml)
- end
+ def deserialize_document_from!(params)
+ xml = inflate(decode(unescape(saml_param_from(params))))
+ Saml::Kit.logger.debug(xml)
+ Saml::Kit::Document.to_saml_document(xml)
+ end
- def ensure_valid_signature!(params, document)
- return if params['Signature'].blank? || params['SigAlg'].blank?
+ def ensure_valid_signature!(params, document)
+ return if params['Signature'].blank? || params['SigAlg'].blank?
- signature = decode(params['Signature'])
- canonical_form = ['SAMLRequest', 'SAMLResponse', 'RelayState', 'SigAlg'].map do |key|
- value = params[key]
- value.present? ? "#{key}=#{value}" : nil
- end.compact.join('&')
+ signature = decode(params['Signature'])
+ canonical_form = ['SAMLRequest', 'SAMLResponse', 'RelayState', 'SigAlg'].map do |key|
+ value = params[key]
+ value.present? ? "#{key}=#{value}" : nil
+ end.compact.join('&')
- valid = document.provider.verify(algorithm_for(params['SigAlg']), signature, canonical_form)
- raise ArgumentError.new("Invalid Signature") unless valid
- end
+ valid = document.provider.verify(algorithm_for(params['SigAlg']), signature, canonical_form)
+ raise ArgumentError.new("Invalid Signature") unless valid
+ end
- def algorithm_for(algorithm)
- case algorithm =~ /(rsa-)?sha(.*?)$/i && $2.to_i
- when 256
- OpenSSL::Digest::SHA256.new
- when 384
- OpenSSL::Digest::SHA384.new
- when 512
- OpenSSL::Digest::SHA512.new
- else
- OpenSSL::Digest::SHA1.new
+ def algorithm_for(algorithm)
+ case algorithm =~ /(rsa-)?sha(.*?)$/i && $2.to_i
+ when 256
+ OpenSSL::Digest::SHA256.new
+ when 384
+ OpenSSL::Digest::SHA384.new
+ when 512
+ OpenSSL::Digest::SHA512.new
+ else
+ OpenSSL::Digest::SHA1.new
+ end
end
end
end
lib/saml/kit/bindings/url_builder.rb
@@ -1,37 +1,39 @@
module Saml
module Kit
- class UrlBuilder
- include Serializable
+ module Bindings
+ class UrlBuilder
+ include Serializable
- def initialize(private_key: Saml::Kit.configuration.signing_private_key)
- @private_key = private_key
- end
+ def initialize(private_key: Saml::Kit.configuration.signing_private_key)
+ @private_key = private_key
+ end
- def build(saml_document, relay_state: nil)
- payload = canonicalize(saml_document, relay_state)
- "#{saml_document.destination}?#{payload}&Signature=#{signature_for(payload)}"
- end
+ def build(saml_document, relay_state: nil)
+ payload = canonicalize(saml_document, relay_state)
+ "#{saml_document.destination}?#{payload}&Signature=#{signature_for(payload)}"
+ end
- private
+ private
- attr_reader :private_key
+ attr_reader :private_key
- def signature_for(payload)
- encode(private_key.sign(OpenSSL::Digest::SHA256.new, payload))
- end
+ def signature_for(payload)
+ encode(private_key.sign(OpenSSL::Digest::SHA256.new, payload))
+ end
- def canonicalize(saml_document, relay_state)
- {
- saml_document.query_string_parameter => serialize(saml_document.to_xml),
- 'RelayState' => relay_state,
- 'SigAlg' => Saml::Kit::Namespaces::SHA256,
- }.map do |(key, value)|
- value.present? ? "#{key}=#{escape(value)}" : nil
- end.compact.join('&')
- end
+ def canonicalize(saml_document, relay_state)
+ {
+ saml_document.query_string_parameter => serialize(saml_document.to_xml),
+ 'RelayState' => relay_state,
+ 'SigAlg' => Saml::Kit::Namespaces::SHA256,
+ }.map do |(key, value)|
+ value.present? ? "#{key}=#{escape(value)}" : nil
+ end.compact.join('&')
+ end
- def serialize(value)
- encode(deflate(value))
+ def serialize(value)
+ encode(deflate(value))
+ end
end
end
end
lib/saml/kit/metadata.rb
@@ -160,11 +160,11 @@ module Saml
def binding_for(binding, location)
case binding
when Namespaces::HTTP_REDIRECT
- Saml::Kit::HttpRedirectBinding.new(location: location)
+ Saml::Kit::Bindings::HttpRedirect.new(location: location)
when Namespaces::POST
- Saml::Kit::HttpPostBinding.new(location: location)
+ Saml::Kit::Bindings::HttpPost.new(location: location)
else
- Saml::Kit::Binding.new(binding: binding, location: location)
+ Saml::Kit::Bindings::Binding.new(binding: binding, location: location)
end
end
end
spec/saml/bindings/binding_spec.rb
@@ -1,8 +1,8 @@
require 'spec_helper'
-RSpec.describe Saml::Kit::Binding do
+RSpec.describe Saml::Kit::Bindings::Binding do
let(:location) { FFaker::Internet.http_url }
- subject { Saml::Kit::Binding.new(binding: Saml::Kit::Namespaces::HTTP_ARTIFACT, location: location) }
+ subject { described_class.new(binding: Saml::Kit::Namespaces::HTTP_ARTIFACT, location: location) }
describe "#serialize" do
it 'ignores other bindings' do
spec/saml/bindings/http_post_spec.rb
@@ -1,8 +1,8 @@
require 'spec_helper'
-RSpec.describe Saml::Kit::HttpPostBinding do
+RSpec.describe Saml::Kit::Bindings::HttpPost do
let(:location) { FFaker::Internet.http_url }
- subject { Saml::Kit::HttpPostBinding.new(location: location) }
+ subject { described_class.new(location: location) }
describe "#serialize" do
let(:relay_state) { "ECHO" }
spec/saml/bindings/http_redirect_spec.rb
@@ -1,8 +1,8 @@
require 'spec_helper'
-RSpec.describe Saml::Kit::HttpRedirectBinding do
+RSpec.describe Saml::Kit::Bindings::HttpRedirect do
let(:location) { FFaker::Internet.http_url }
- subject { Saml::Kit::HttpRedirectBinding.new(location: location) }
+ subject { described_class.new(location: location) }
describe "#serialize" do
let(:relay_state) { "ECHO" }
spec/saml/bindings/url_builder_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-RSpec.describe Saml::Kit::UrlBuilder do
+RSpec.describe Saml::Kit::Bindings::UrlBuilder do
describe "#build" do
let(:xml) { "<xml></xml>" }
let(:destination) { FFaker::Internet.http_url }
spec/saml/logout_request_spec.rb
@@ -38,7 +38,7 @@ RSpec.describe Saml::Kit::LogoutRequest do
allow(registry).to receive(:metadata_for).and_return(metadata)
allow(metadata).to receive(:matches?).and_return(true)
allow(metadata).to receive(:single_logout_services).and_return([
- Saml::Kit::HttpPostBinding.new(location: FFaker::Internet.http_url)
+ Saml::Kit::Bindings::HttpPost.new(location: FFaker::Internet.http_url)
])
end
@@ -94,7 +94,7 @@ RSpec.describe Saml::Kit::LogoutRequest do
allow(registry).to receive(:metadata_for).with(builder.issuer).and_return(metadata)
allow(metadata).to receive(:matches?).and_return(true)
allow(metadata).to receive(:single_logout_services).and_return([
- Saml::Kit::HttpPostBinding.new(location: FFaker::Internet.http_url)
+ Saml::Kit::Bindings::HttpPost.new(location: FFaker::Internet.http_url)
])
expect(builder.build).to be_valid