saml-kit 1.0.14 → 1.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +8 -6
  3. data/lib/saml/kit.rb +4 -0
  4. data/lib/saml/kit/assertion.rb +13 -4
  5. data/lib/saml/kit/authentication_request.rb +4 -4
  6. data/lib/saml/kit/bindings.rb +3 -0
  7. data/lib/saml/kit/bindings/binding.rb +1 -0
  8. data/lib/saml/kit/bindings/http_post.rb +5 -0
  9. data/lib/saml/kit/bindings/http_redirect.rb +19 -14
  10. data/lib/saml/kit/bindings/url_builder.rb +8 -2
  11. data/lib/saml/kit/buildable.rb +3 -0
  12. data/lib/saml/kit/builders.rb +3 -0
  13. data/lib/saml/kit/builders/assertion.rb +1 -0
  14. data/lib/saml/kit/builders/encrypted_assertion.rb +1 -0
  15. data/lib/saml/kit/builders/metadata.rb +4 -4
  16. data/lib/saml/kit/builders/null.rb +13 -0
  17. data/lib/saml/kit/builders/response.rb +7 -2
  18. data/lib/saml/kit/builders/templates/null.builder +1 -0
  19. data/lib/saml/kit/builders/templates/response.builder +1 -0
  20. data/lib/saml/kit/composite_metadata.rb +8 -3
  21. data/lib/saml/kit/configuration.rb +5 -5
  22. data/lib/saml/kit/default_registry.rb +3 -0
  23. data/lib/saml/kit/document.rb +5 -4
  24. data/lib/saml/kit/identity_provider_metadata.rb +3 -3
  25. data/lib/saml/kit/invalid_document.rb +2 -0
  26. data/lib/saml/kit/logout_request.rb +2 -2
  27. data/lib/saml/kit/metadata.rb +7 -7
  28. data/lib/saml/kit/null_assertion.rb +3 -0
  29. data/lib/saml/kit/requestable.rb +4 -0
  30. data/lib/saml/kit/respondable.rb +8 -0
  31. data/lib/saml/kit/response.rb +2 -0
  32. data/lib/saml/kit/rspec/have_query_param.rb +1 -1
  33. data/lib/saml/kit/serializable.rb +1 -0
  34. data/lib/saml/kit/service_provider_metadata.rb +3 -0
  35. data/lib/saml/kit/signature.rb +11 -4
  36. data/lib/saml/kit/translatable.rb +3 -0
  37. data/lib/saml/kit/trustable.rb +3 -0
  38. data/lib/saml/kit/version.rb +1 -1
  39. data/lib/saml/kit/xml_templatable.rb +2 -0
  40. data/lib/saml/kit/xsd_validatable.rb +2 -0
  41. data/saml-kit.gemspec +1 -0
  42. metadata +18 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 722bb4a5e235e4a45f9c86d0ac1c8b30edc5a60a566505eb37444a0500a019cb
4
- data.tar.gz: 6f71d05bb0f8d45f98967310be6443b79af9e7ffa8a07847ed90500553ccc231
3
+ metadata.gz: 589e2c267c9eef495616d9ecac88c78b2961baee78ae9d8fa404f566260b3c9c
4
+ data.tar.gz: f9bbb3af185e370d62ffab5182801a110b436e7c13b93997536f5856642abbd0
5
5
  SHA512:
6
- metadata.gz: 76d07338515edd92a7a75f8d2a51f8657ed066883823d963371d057ad7ac5184ccdeed8321a2d23da469d31eb11138bc80784b59c3001c49fe9ac28eb6949bf7
7
- data.tar.gz: d122611de90c1bbc2636d7a3758cab04a4cc7e0d7ea4d7b87fa42d612714f49ec3672b775292e3bed5cc9bda431414213791cfd042719a03f937ef13d112831c
6
+ metadata.gz: b4931f06f5fc42b83dd0cdcb27485cce1bb85dac1973a97a47be244b7bbcbda9b2ecf33cd7055c7e9f035a00f0d81840cf6e224c1a7d12834bc7d9901de7cc44
7
+ data.tar.gz: b60f4263ffe6fb7804d5a708dab81e9168b14435929a2c3ec0c338c76854b5e73694bab32b51ef95f84dbecdc231f20a6285a153e15e9346facbf860bb4276cd
data/Rakefile CHANGED
@@ -1,15 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'bundler/audit/task'
3
4
  require 'bundler/gem_tasks'
5
+ require 'reek/rake/task'
4
6
  require 'rspec/core/rake_task'
7
+ require 'rubocop/rake_task'
5
8
 
6
9
  RSpec::Core::RakeTask.new(:spec)
7
- task default: :spec
8
-
9
- require 'rubocop/rake_task'
10
10
  RuboCop::RakeTask.new(:rubocop)
11
-
12
- require 'bundler/audit/task'
13
11
  Bundler::Audit::Task.new
12
+ Reek::Rake::Task.new(:reek) do |task|
13
+ task.config_file = '.reek'
14
+ end
14
15
 
15
- task lint: [:rubocop, 'bundle:audit']
16
+ task lint: [:rubocop, :reek, 'bundle:audit']
17
+ task default: :spec
@@ -48,7 +48,11 @@ I18n.load_path +=
48
48
  Dir[File.expand_path('kit/locales/*.yml', File.dirname(__FILE__))]
49
49
 
50
50
  module Saml
51
+ # This module is the container for all classes/modules in this gem.
51
52
  module Kit
53
+ # This class provides a global access to the
54
+ # default SAML configuration. This is useful
55
+ # for long running processes.
52
56
  class << self
53
57
  def configuration
54
58
  @configuration ||= Saml::Kit::Configuration.new
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Saml
4
4
  module Kit
5
+ # This class validates the Assertion
6
+ # element nested in a Response element
7
+ # of a SAML document.
5
8
  class Assertion
6
9
  include ActiveModel::Validations
7
10
  include Translatable
@@ -22,8 +25,10 @@ module Saml
22
25
  @node = node
23
26
  @configuration = configuration
24
27
  @occurred_at = Time.current
28
+ @cannot_decrypt = false
29
+ @encrypted = false
25
30
  private_keys = (configuration.private_keys(use: :encryption) + private_keys).uniq
26
- decrypt!(::Xml::Kit::Decryption.new(private_keys: private_keys))
31
+ decrypt(::Xml::Kit::Decryption.new(private_keys: private_keys))
27
32
  end
28
33
 
29
34
  def issuer
@@ -83,15 +88,19 @@ module Saml
83
88
  @node.present?
84
89
  end
85
90
 
86
- def to_xml(pretty: false)
87
- pretty ? @node.to_xml(indent: 2) : @node.to_s
91
+ def to_xml(pretty: nil)
92
+ pretty ? @node.to_xml(indent: 2) : to_s
93
+ end
94
+
95
+ def to_s
96
+ @node.to_s
88
97
  end
89
98
 
90
99
  private
91
100
 
92
101
  attr_reader :configuration
93
102
 
94
- def decrypt!(decryptor)
103
+ def decrypt(decryptor)
95
104
  encrypted_assertion = at_xpath('./xmlenc:EncryptedData')
96
105
  @encrypted = encrypted_assertion.present?
97
106
  return unless @encrypted
@@ -54,11 +54,11 @@ module Saml
54
54
  # @param configuration [Saml::Kit::Configuration] the configuration to use to build the response.
55
55
  def response_for(user, binding:, relay_state: nil, configuration: Saml::Kit.configuration)
56
56
  response_binding = provider.assertion_consumer_service_for(binding: binding)
57
- builder = Saml::Kit::Response.builder(user, self, configuration: configuration) do |x|
58
- x.embed_signature = provider.want_assertions_signed
59
- yield x if block_given?
57
+ response = Saml::Kit::Response.builder(user, self, configuration: configuration) do |builder|
58
+ builder.embed_signature = provider.want_assertions_signed
59
+ yield builder if block_given?
60
60
  end
61
- response_binding.serialize(builder, relay_state: relay_state)
61
+ response_binding.serialize(response, relay_state: relay_state)
62
62
  end
63
63
  end
64
64
  end
@@ -7,6 +7,9 @@ require 'saml/kit/bindings/url_builder'
7
7
 
8
8
  module Saml
9
9
  module Kit
10
+ # This module is responsible for exposing
11
+ # the different SAML bindings that are
12
+ # supported by this gem.
10
13
  module Bindings
11
14
  HTTP_ARTIFACT = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact'.freeze
12
15
  HTTP_POST = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'.freeze
@@ -3,6 +3,7 @@
3
3
  module Saml
4
4
  module Kit
5
5
  module Bindings
6
+ # This class is a base class for SAML bindings.
6
7
  # {include:file:spec/saml/kit/bindings/binding_spec.rb}
7
8
  class Binding
8
9
  attr_reader :binding, :location
@@ -3,6 +3,11 @@
3
3
  module Saml
4
4
  module Kit
5
5
  module Bindings
6
+ # This class is responsible for
7
+ # serializing/deserializing SAML
8
+ # documents using the HTTP Post
9
+ # binding specification.
10
+ # https://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf
6
11
  # {include:file:spec/saml/kit/bindings/http_post_spec.rb}
7
12
  class HttpPost < Binding
8
13
  include Serializable
@@ -3,6 +3,11 @@
3
3
  module Saml
4
4
  module Kit
5
5
  module Bindings
6
+ # This class is responsible for
7
+ # serializing/deserializing SAML
8
+ # documents using the HTTP Redirect
9
+ # binding specification.
10
+ # https://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf
6
11
  # {include:file:spec/saml/kit/bindings/http_redirect_spec.rb}
7
12
  class HttpRedirect < Binding
8
13
  include Serializable
@@ -20,31 +25,31 @@ module Saml
20
25
 
21
26
  def deserialize(params, configuration: Saml::Kit.configuration)
22
27
  parameters = normalize(params_to_hash(params))
23
- document = deserialize_document_from!(parameters, configuration)
24
- ensure_valid_signature!(parameters, document)
28
+ document = deserialize_document_from(parameters, configuration)
29
+ ensure_valid_signature(parameters, document)
25
30
  document
26
31
  end
27
32
 
28
33
  private
29
34
 
30
- def deserialize_document_from!(params, configuration)
35
+ def deserialize_document_from(params, configuration)
31
36
  xml = inflate(decode(unescape(saml_param_from(params))))
32
37
  Saml::Kit::Document.to_saml_document(xml, configuration: configuration)
33
38
  end
34
39
 
35
- def ensure_valid_signature!(params, document)
36
- return if params[:Signature].blank? || params[:SigAlg].blank?
37
- return if document.provider.nil?
40
+ def ensure_valid_signature(params, document)
41
+ signature = params[:Signature]
42
+ algorithm = params[:SigAlg]
43
+ provider = document.provider
44
+ return if signature.blank? || algorithm.blank?
45
+ return if provider.nil?
38
46
 
39
- if document.provider.verify(
40
- algorithm_for(params[:SigAlg]),
41
- decode(params[:Signature]),
47
+ return document.signature_verified! if provider.verify(
48
+ algorithm_for(algorithm),
49
+ decode(signature),
42
50
  canonicalize(params)
43
51
  )
44
- document.signature_verified!
45
- else
46
- raise ArgumentError, 'Invalid Signature'
47
- end
52
+ raise ArgumentError, 'Invalid Signature'
48
53
  end
49
54
 
50
55
  def canonicalize(params)
@@ -79,7 +84,7 @@ module Saml
79
84
 
80
85
  def params_to_hash(value)
81
86
  return value unless value.is_a?(String)
82
- Hash[URI.parse(value).query.split('&').map { |x| x.split('=', 2) }]
87
+ Hash[URI.parse(value).query.split('&').map { |xx| xx.split('=', 2) }]
83
88
  end
84
89
  end
85
90
  end
@@ -3,6 +3,11 @@
3
3
  module Saml
4
4
  module Kit
5
5
  module Bindings
6
+ # This class is responsible for
7
+ # generating a url as per the
8
+ # rules for the HTTP redirect binding
9
+ # specification.
10
+ # https://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf
6
11
  # {include:file:spec/saml/kit/bindings/url_builder_spec.rb}
7
12
  class UrlBuilder
8
13
  include Serializable
@@ -13,15 +18,16 @@ module Saml
13
18
  end
14
19
 
15
20
  def build(saml_document, relay_state: nil)
21
+ destination = saml_document.destination
16
22
  if configuration.sign?
17
23
  payload = canonicalize(saml_document, relay_state)
18
- "#{saml_document.destination}?#{payload}&Signature=#{signature_for(payload)}"
24
+ "#{destination}?#{payload}&Signature=#{signature_for(payload)}"
19
25
  else
20
26
  payload = to_query_string(
21
27
  saml_document.query_string_parameter => serialize(saml_document.to_xml),
22
28
  'RelayState' => relay_state
23
29
  )
24
- "#{saml_document.destination}?#{payload}"
30
+ "#{destination}?#{payload}"
25
31
  end
26
32
  end
27
33
 
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Saml
4
4
  module Kit
5
+ # This module is responsible for
6
+ # providing an API to build a
7
+ # document object, xml, or builder class.
5
8
  module Buildable
6
9
  extend ActiveSupport::Concern
7
10
 
@@ -8,11 +8,14 @@ require 'saml/kit/builders/identity_provider_metadata'
8
8
  require 'saml/kit/builders/logout_request'
9
9
  require 'saml/kit/builders/logout_response'
10
10
  require 'saml/kit/builders/metadata'
11
+ require 'saml/kit/builders/null'
11
12
  require 'saml/kit/builders/response'
12
13
  require 'saml/kit/builders/service_provider_metadata'
13
14
 
14
15
  module Saml
15
16
  module Kit
17
+ # This module contains all the builders classes
18
+ # that are used to create SAML documents.
16
19
  module Builders
17
20
  end
18
21
  end
@@ -3,6 +3,7 @@
3
3
  module Saml
4
4
  module Kit
5
5
  module Builders
6
+ # This class is responsible for building a SAML Assertion
6
7
  # {include:file:lib/saml/kit/builders/templates/assertion.builder}
7
8
  class Assertion
8
9
  include XmlTemplatable
@@ -3,6 +3,7 @@
3
3
  module Saml
4
4
  module Kit
5
5
  module Builders
6
+ # This class is responsible for encrypting an Assertion.
6
7
  # {include:file:lib/saml/kit/builders/templates/encrypted_assertion.builder}
7
8
  class EncryptedAssertion
8
9
  include XmlTemplatable
@@ -22,14 +22,14 @@ module Saml
22
22
  end
23
23
 
24
24
  def build_service_provider
25
- @service_provider = Saml::Kit::ServiceProviderMetadata.builder(configuration: configuration) do |x|
26
- yield x if block_given?
25
+ @service_provider = Saml::Kit::ServiceProviderMetadata.builder(configuration: configuration) do |xx|
26
+ yield xx if block_given?
27
27
  end
28
28
  end
29
29
 
30
30
  def build_identity_provider
31
- @identity_provider = Saml::Kit::IdentityProviderMetadata.builder(configuration: configuration) do |x|
32
- yield x if block_given?
31
+ @identity_provider = Saml::Kit::IdentityProviderMetadata.builder(configuration: configuration) do |xx|
32
+ yield xx if block_given?
33
33
  end
34
34
  end
35
35
 
@@ -0,0 +1,13 @@
1
+
2
+ # frozen_string_literal: true
3
+
4
+ module Saml
5
+ module Kit
6
+ module Builders
7
+ # This class is responsible for rendering an empty xml element
8
+ class Null
9
+ include XmlTemplatable
10
+ end
11
+ end
12
+ end
13
+ end
@@ -9,7 +9,7 @@ module Saml
9
9
  include XmlTemplatable
10
10
  attr_reader :user, :request
11
11
  attr_accessor :id, :reference_id, :now
12
- attr_accessor :version, :status_code
12
+ attr_accessor :version, :status_code, :status_message
13
13
  attr_accessor :issuer, :destination
14
14
  attr_reader :configuration
15
15
 
@@ -21,6 +21,7 @@ module Saml
21
21
  @now = Time.now.utc
22
22
  @version = '2.0'
23
23
  @status_code = Namespaces::SUCCESS
24
+ @status_message = nil
24
25
  @issuer = configuration.entity_id
25
26
  @encryption_certificate = request.try(:provider).try(:encryption_certificates).try(:last)
26
27
  @encrypt = encryption_certificate.present?
@@ -31,6 +32,10 @@ module Saml
31
32
  Saml::Kit::Response.new(to_xml, request_id: request.try(:id), configuration: configuration)
32
33
  end
33
34
 
35
+ def assertion=(value)
36
+ @assertion = value ? value : Null.new
37
+ end
38
+
34
39
  def assertion
35
40
  @assertion ||=
36
41
  begin
@@ -54,7 +59,7 @@ module Saml
54
59
  xmlns: Namespaces::PROTOCOL,
55
60
  }
56
61
  options[:Destination] = destination if destination.present?
57
- options[:InResponseTo] = request.id if request.present?
62
+ options[:InResponseTo] = request.try(:id) if request.present?
58
63
  options
59
64
  end
60
65
  end
@@ -0,0 +1 @@
1
+ # frozen_string_literal: true
@@ -6,6 +6,7 @@ xml.Response response_options do
6
6
  signature_for(reference_id: id, xml: xml)
7
7
  xml.Status do
8
8
  xml.StatusCode Value: status_code
9
+ xml.StatusMessage(status_message) if status_message.present?
9
10
  end
10
11
  render assertion, xml: xml
11
12
  end
@@ -2,6 +2,11 @@
2
2
 
3
3
  module Saml
4
4
  module Kit
5
+ # This class implements the Composite
6
+ # design pattern to allow client
7
+ # component to work with a metadata
8
+ # that provides an IDPSSODescriptor
9
+ # and SPSSODescriptor element.
5
10
  class CompositeMetadata < Metadata # :nodoc:
6
11
  include Enumerable
7
12
  attr_reader :service_provider, :identity_provider
@@ -15,7 +20,7 @@ module Saml
15
20
  end
16
21
 
17
22
  def services(type)
18
- xpath = map { |x| "//md:EntityDescriptor/md:#{x.name}/md:#{type}" }.join('|')
23
+ xpath = map { |xxx| "//md:EntityDescriptor/md:#{xxx.name}/md:#{type}" }.join('|')
19
24
  search(xpath).map do |item|
20
25
  binding = item.attribute('Binding').value
21
26
  location = item.attribute('Location').value
@@ -32,7 +37,7 @@ module Saml
32
37
  end
33
38
 
34
39
  def method_missing(name, *args)
35
- if (target = find { |x| x.respond_to?(name) })
40
+ if (target = find { |xxx| xxx.respond_to?(name) })
36
41
  target.public_send(name, *args)
37
42
  else
38
43
  super
@@ -40,7 +45,7 @@ module Saml
40
45
  end
41
46
 
42
47
  def respond_to_missing?(method, *)
43
- find { |x| x.respond_to?(method) }
48
+ find { |xxx| xxx.respond_to?(method) }
44
49
  end
45
50
  end
46
51
  end
@@ -56,7 +56,7 @@ module Saml
56
56
  # @param passphrase [String] the password to decrypt the private key.
57
57
  # @param use [Symbol] the type of key pair, `:signing` or `:encryption`
58
58
  def add_key_pair(certificate, private_key, passphrase: nil, use: :signing)
59
- ensure_proper_use!(use)
59
+ ensure_proper_use(use)
60
60
  @key_pairs.push(::Xml::Kit::KeyPair.new(certificate, private_key, passphrase, use.to_sym))
61
61
  end
62
62
 
@@ -65,7 +65,7 @@ module Saml
65
65
  # @param use [Symbol] the type of key pair, `:signing` or `:encryption`
66
66
  # @param passphrase [String] the private key passphrase to use.
67
67
  def generate_key_pair_for(use:, passphrase: SecureRandom.uuid)
68
- ensure_proper_use!(use)
68
+ ensure_proper_use(use)
69
69
  certificate, private_key = ::Xml::Kit::SelfSignedCertificate.new.create(passphrase: passphrase)
70
70
  add_key_pair(certificate, private_key, passphrase: passphrase, use: use)
71
71
  end
@@ -74,7 +74,7 @@ module Saml
74
74
  #
75
75
  # @param use [Symbol] the type of key pair to return `nil`, `:signing` or `:encryption`
76
76
  def key_pairs(use: nil)
77
- use.present? ? @key_pairs.find_all { |x| x.for?(use) } : @key_pairs
77
+ use.present? ? @key_pairs.find_all { |xxx| xxx.for?(use) } : @key_pairs
78
78
  end
79
79
 
80
80
  # Return each certificate for a specific use.
@@ -93,12 +93,12 @@ module Saml
93
93
 
94
94
  # Returns true if there is at least one signing certificate registered.
95
95
  def sign?
96
- certificates(use: :signing).any?
96
+ @sign ||= certificates(use: :signing).any?
97
97
  end
98
98
 
99
99
  private
100
100
 
101
- def ensure_proper_use!(use)
101
+ def ensure_proper_use(use)
102
102
  return if USES.include?(use)
103
103
 
104
104
  error_message = 'Use must be either :signing or :encryption'
@@ -69,6 +69,9 @@ module Saml
69
69
  end
70
70
  end
71
71
 
72
+ # This class is responsible for
73
+ # making HTTP requests to fetch metadata
74
+ # from remote locations.
72
75
  class HttpApi # :nodoc:
73
76
  def initialize(url, verify_ssl: true)
74
77
  @uri = URI.parse(url)
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Saml
4
4
  module Kit
5
+ # This class is a base class for SAML documents.
5
6
  class Document
6
7
  include ActiveModel::Validations
7
8
  include XsdValidatable
@@ -65,8 +66,8 @@ module Saml
65
66
  # Returns the SAML document as an XML string.
66
67
  #
67
68
  # @param pretty [Boolean] formats the xml or returns the raw xml.
68
- def to_xml(pretty: false)
69
- pretty ? to_nokogiri.to_xml(indent: 2) : content
69
+ def to_xml(pretty: nil)
70
+ pretty ? to_nokogiri.to_xml(indent: 2) : to_s
70
71
  end
71
72
 
72
73
  # Returns the SAML document as an XHTML string.
@@ -77,7 +78,7 @@ module Saml
77
78
 
78
79
  # @!visibility private
79
80
  def to_nokogiri
80
- @to_nokogiri ||= Nokogiri::XML(content)
81
+ @to_nokogiri ||= Nokogiri::XML(to_s)
81
82
  end
82
83
 
83
84
  # @!visibility private
@@ -91,7 +92,7 @@ module Saml
91
92
  end
92
93
 
93
94
  def to_s
94
- to_xml
95
+ content
95
96
  end
96
97
 
97
98
  class << self
@@ -74,9 +74,9 @@ module Saml
74
74
  # @param configuration [Saml::Kit::Configuration] the configuration to use for generating the request.
75
75
  # @return [Array] The url and saml params encoded using the rules for the specified binding.
76
76
  def login_request_for(binding:, relay_state: nil, configuration: Saml::Kit.configuration)
77
- builder = Saml::Kit::AuthenticationRequest.builder(configuration: configuration) do |x|
78
- x.embed_signature = want_authn_requests_signed
79
- yield x if block_given?
77
+ builder = Saml::Kit::AuthenticationRequest.builder(configuration: configuration) do |xxx|
78
+ xxx.embed_signature = want_authn_requests_signed
79
+ yield xxx if block_given?
80
80
  end
81
81
  request_binding = single_sign_on_service_for(binding: binding)
82
82
  request_binding.serialize(builder, relay_state: relay_state)
@@ -2,6 +2,8 @@
2
2
 
3
3
  module Saml
4
4
  module Kit
5
+ # This class represents an invalid SAML
6
+ # document that could not be parsed.
5
7
  # {include:file:spec/saml/kit/invalid_document_spec.rb}
6
8
  class InvalidDocument < Document
7
9
  validate do |model|
@@ -51,8 +51,8 @@ module Saml
51
51
  # @param relay_state [Object] The RelayState to include in the RelayState param.
52
52
  # @return [Array] Returns an array with a url and Hash of parameters to return to the requestor.
53
53
  def response_for(binding:, relay_state: nil)
54
- builder = Saml::Kit::LogoutResponse.builder(self) do |x|
55
- yield x if block_given?
54
+ builder = Saml::Kit::LogoutResponse.builder(self) do |xxx|
55
+ yield xxx if block_given?
56
56
  end
57
57
  response_binding = provider.single_logout_service_for(binding: binding)
58
58
  response_binding.serialize(builder, relay_state: relay_state)
@@ -110,7 +110,7 @@ module Saml
110
110
  # @param type [Symbol] can be on the service element like `AssertionConsumerServiceURL`, `SingleSignOnService` or `SingleLogoutService`.
111
111
  def service_for(binding:, type:)
112
112
  binding = Saml::Kit::Bindings.binding_for(binding)
113
- services(type).find { |x| x.binding?(binding) }
113
+ services(type).find { |xxx| xxx.binding?(binding) }
114
114
  end
115
115
 
116
116
  # Returns each of the SingleLogoutService bindings
@@ -132,7 +132,7 @@ module Saml
132
132
  # @param relay_state [String] the relay state to have echo'd back.
133
133
  # @return [Array] Returns an array with a url and Hash of parameters to send to the other party.
134
134
  def logout_request_for(user, binding: :http_post, relay_state: nil)
135
- builder = Saml::Kit::LogoutRequest.builder(user) { |x| yield x if block_given? }
135
+ builder = Saml::Kit::LogoutRequest.builder(user) { |xxx| yield xxx if block_given? }
136
136
  request_binding = single_logout_service_for(binding: binding)
137
137
  request_binding.serialize(builder, relay_state: relay_state)
138
138
  end
@@ -143,7 +143,7 @@ module Saml
143
143
  # @param use [Symbol] the type of certificates to look at. Can be `:signing` or `:encryption`.
144
144
  # @return [Xml::Kit::Certificate] returns the matching `{Xml::Kit::Certificate}`
145
145
  def matches?(fingerprint, use: :signing)
146
- certificates.find { |x| x.for?(use) && x.fingerprint == fingerprint }
146
+ certificates.find { |xxx| xxx.for?(use) && xxx.fingerprint == fingerprint }
147
147
  end
148
148
 
149
149
  # Returns the XML document converted to a Hash.
@@ -153,14 +153,14 @@ module Saml
153
153
 
154
154
  # Returns the XML document as a String.
155
155
  #
156
- # @param pretty [Symbol] true to return a human friendly version of the XML.
157
- def to_xml(pretty: false)
158
- pretty ? to_nokogiri.to_xml(indent: 2) : @xml
156
+ # @param pretty [Boolean] true to return a human friendly version of the XML.
157
+ def to_xml(pretty: nil)
158
+ pretty ? to_nokogiri.to_xml(indent: 2) : to_s
159
159
  end
160
160
 
161
161
  # Returns the XML document as a [String].
162
162
  def to_s
163
- to_xml
163
+ @xml
164
164
  end
165
165
 
166
166
  # Verifies the signature and data using the signing certificates.
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Saml
4
4
  module Kit
5
+ # This class is an implementation of the
6
+ # Null Object pattern for when a Response
7
+ # is missing an Assertion.
5
8
  class NullAssertion
6
9
  include ActiveModel::Validations
7
10
  include Translatable
@@ -2,6 +2,10 @@
2
2
 
3
3
  module Saml
4
4
  module Kit
5
+ # This module is responsible for providing
6
+ # the functionality available to all
7
+ # SAML request documents.
8
+ # e.g. AuthnRequest, LogoutRequest.
5
9
  module Requestable
6
10
  extend ActiveSupport::Concern
7
11
 
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Saml
4
4
  module Kit
5
+ # This module provides the behaviours
6
+ # associated with SAML Response documents.
7
+ # .e.g. Response, LogoutResponse
5
8
  module Respondable
6
9
  extend ActiveSupport::Concern
7
10
  attr_reader :request_id
@@ -21,6 +24,11 @@ module Saml
21
24
  at_xpath('./*/samlp:Status/samlp:StatusCode/@Value').try(:value)
22
25
  end
23
26
 
27
+ # Returns the /Status/StatusMessage
28
+ def status_message
29
+ at_xpath('./*/samlp:Status/samlp:StatusMessage').try(:text)
30
+ end
31
+
24
32
  # Returns the /InResponseTo attribute.
25
33
  def in_response_to
26
34
  at_xpath('./*/@InResponseTo').try(:value)
@@ -2,6 +2,8 @@
2
2
 
3
3
  module Saml
4
4
  module Kit
5
+ # This class is responsible for validating and
6
+ # parsing a SAML Response document.
5
7
  # {include:file:spec/examples/response_spec.rb}
6
8
  class Response < Document
7
9
  include Respondable
@@ -8,7 +8,7 @@ RSpec::Matchers.define :have_query_param do |key|
8
8
  end
9
9
 
10
10
  def query_params_from(url)
11
- Hash[query_for(url).split('&').map { |x| x.split('=', 2) }]
11
+ Hash[query_for(url).split('&').map { |xxx| xxx.split('=', 2) }]
12
12
  end
13
13
 
14
14
  def uri_for(url)
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Saml
4
4
  module Kit
5
+ # This module is responsible for serializing/deserialing values.
5
6
  module Serializable
6
7
  # Base 64 decodes the value.
7
8
  #
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Saml
4
4
  module Kit
5
+ # This class represents a
6
+ # SPSSODescriptor element in a
7
+ # SAML metadata document.
5
8
  # {include:file:spec/examples/service_provider_metadata_spec.rb}
6
9
  class ServiceProviderMetadata < Metadata
7
10
  def initialize(xml)
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Saml
4
4
  module Kit
5
+ # This class is responsible for
6
+ # validating an xml digital signature
7
+ # in an xml document.
5
8
  class Signature
6
9
  include ActiveModel::Validations
7
10
  include Translatable
@@ -34,8 +37,8 @@ module Saml
34
37
  end
35
38
 
36
39
  def expected_digest_value
37
- digests = dsignature.references.map do |x|
38
- Base64.encode64(x.calculate_digest_value).chomp
40
+ digests = dsignature.references.map do |xxx|
41
+ Base64.encode64(xxx.calculate_digest_value).chomp
39
42
  end
40
43
  digests.count > 1 ? digests : digests[0]
41
44
  end
@@ -69,8 +72,12 @@ module Saml
69
72
  node.present?
70
73
  end
71
74
 
72
- def to_xml(pretty: false)
73
- pretty ? node.to_xml(indent: 2) : node.to_s
75
+ def to_xml(pretty: nil)
76
+ pretty ? node.to_xml(indent: 2) : to_s
77
+ end
78
+
79
+ def to_s
80
+ node.to_s
74
81
  end
75
82
 
76
83
  private
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Saml
4
4
  module Kit
5
+ # This module is responsible
6
+ # for translating error messages
7
+ # to the current locale.
5
8
  module Translatable
6
9
  # @!visibility private
7
10
  def error_message(attribute, options = {})
@@ -2,6 +2,9 @@
2
2
 
3
3
  module Saml
4
4
  module Kit
5
+ # This module is responsible for
6
+ # validating the trustworthiness
7
+ # of a saml document.
5
8
  module Trustable
6
9
  extend ActiveSupport::Concern
7
10
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Saml
4
4
  module Kit
5
- VERSION = '1.0.14'.freeze
5
+ VERSION = '1.0.15'.freeze
6
6
  end
7
7
  end
@@ -2,6 +2,8 @@
2
2
 
3
3
  module Saml
4
4
  module Kit
5
+ # This module is responsible for
6
+ # generating converting templates to xml.
5
7
  module XmlTemplatable
6
8
  TEMPLATES_DIR = Pathname.new(File.join(__dir__, 'builders/templates/'))
7
9
  include ::Xml::Kit::Templatable
@@ -2,6 +2,8 @@
2
2
 
3
3
  module Saml
4
4
  module Kit
5
+ # This module is responsible for validating
6
+ # xml documents against the SAML XSD's
5
7
  module XsdValidatable
6
8
  # @!visibility private
7
9
  def matches_xsd?(xsd)
@@ -34,6 +34,7 @@ Gem::Specification.new do |spec|
34
34
  spec.add_development_dependency 'bundler-audit', '~> 0.6'
35
35
  spec.add_development_dependency 'ffaker', '~> 2.7'
36
36
  spec.add_development_dependency 'rake', '~> 10.0'
37
+ spec.add_development_dependency 'reek', '~> 4.8'
37
38
  spec.add_development_dependency 'rspec', '~> 3.0'
38
39
  spec.add_development_dependency 'rspec-benchmark', '~> 0.3'
39
40
  spec.add_development_dependency 'rubocop', '~> 0.52'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: saml-kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.14
4
+ version: 1.0.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - mo khan
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-03-07 00:00:00.000000000 Z
11
+ date: 2018-03-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
@@ -100,6 +100,20 @@ dependencies:
100
100
  - - "~>"
101
101
  - !ruby/object:Gem::Version
102
102
  version: '10.0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: reek
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '4.8'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '4.8'
103
117
  - !ruby/object:Gem::Dependency
104
118
  name: rspec
105
119
  requirement: !ruby/object:Gem::Requirement
@@ -233,6 +247,7 @@ files:
233
247
  - lib/saml/kit/builders/logout_request.rb
234
248
  - lib/saml/kit/builders/logout_response.rb
235
249
  - lib/saml/kit/builders/metadata.rb
250
+ - lib/saml/kit/builders/null.rb
236
251
  - lib/saml/kit/builders/response.rb
237
252
  - lib/saml/kit/builders/service_provider_metadata.rb
238
253
  - lib/saml/kit/builders/templates/assertion.builder
@@ -242,6 +257,7 @@ files:
242
257
  - lib/saml/kit/builders/templates/logout_request.builder
243
258
  - lib/saml/kit/builders/templates/logout_response.builder
244
259
  - lib/saml/kit/builders/templates/metadata.builder
260
+ - lib/saml/kit/builders/templates/null.builder
245
261
  - lib/saml/kit/builders/templates/response.builder
246
262
  - lib/saml/kit/builders/templates/service_provider_metadata.builder
247
263
  - lib/saml/kit/composite_metadata.rb