ruby-saml 0.8.16 → 0.9

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 (90) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.travis.yml +1 -6
  4. data/Gemfile +2 -12
  5. data/README.md +363 -35
  6. data/Rakefile +14 -0
  7. data/changelog.md +22 -9
  8. data/lib/onelogin/ruby-saml/attribute_service.rb +34 -0
  9. data/lib/onelogin/ruby-saml/attributes.rb +26 -64
  10. data/lib/onelogin/ruby-saml/authrequest.rb +47 -89
  11. data/lib/onelogin/ruby-saml/idp_metadata_parser.rb +87 -0
  12. data/lib/onelogin/ruby-saml/logoutrequest.rb +34 -93
  13. data/lib/onelogin/ruby-saml/logoutresponse.rb +25 -24
  14. data/lib/onelogin/ruby-saml/metadata.rb +46 -16
  15. data/lib/onelogin/ruby-saml/response.rb +62 -322
  16. data/lib/onelogin/ruby-saml/saml_message.rb +78 -0
  17. data/lib/onelogin/ruby-saml/settings.rb +54 -121
  18. data/lib/onelogin/ruby-saml/slo_logoutrequest.rb +26 -61
  19. data/lib/onelogin/ruby-saml/slo_logoutresponse.rb +27 -84
  20. data/lib/onelogin/ruby-saml/utils.rb +32 -199
  21. data/lib/onelogin/ruby-saml/version.rb +1 -1
  22. data/lib/ruby-saml.rb +5 -2
  23. data/lib/schemas/{saml20assertion_schema.xsd → saml-schema-assertion-2.0.xsd} +283 -283
  24. data/lib/schemas/saml-schema-authn-context-2.0.xsd +23 -0
  25. data/lib/schemas/saml-schema-authn-context-types-2.0.xsd +821 -0
  26. data/lib/schemas/saml-schema-metadata-2.0.xsd +339 -0
  27. data/lib/schemas/{saml20protocol_schema.xsd → saml-schema-protocol-2.0.xsd} +302 -302
  28. data/lib/schemas/sstc-metadata-attr.xsd +35 -0
  29. data/lib/schemas/sstc-saml-attribute-ext.xsd +25 -0
  30. data/lib/schemas/sstc-saml-metadata-algsupport-v1.0.xsd +41 -0
  31. data/lib/schemas/sstc-saml-metadata-ui-v1.0.xsd +89 -0
  32. data/lib/schemas/{xenc_schema.xsd → xenc-schema.xsd} +1 -11
  33. data/lib/schemas/xml.xsd +287 -0
  34. data/lib/schemas/{xmldsig_schema.xsd → xmldsig-core-schema.xsd} +0 -9
  35. data/lib/xml_security.rb +83 -235
  36. data/ruby-saml.gemspec +1 -0
  37. data/test/idp_metadata_parser_test.rb +54 -0
  38. data/test/logoutrequest_test.rb +68 -144
  39. data/test/logoutresponse_test.rb +43 -25
  40. data/test/metadata_test.rb +87 -0
  41. data/test/request_test.rb +103 -90
  42. data/test/response_test.rb +181 -471
  43. data/test/responses/idp_descriptor.xml +3 -0
  44. data/test/responses/logoutresponse_fixtures.rb +5 -5
  45. data/test/responses/response_no_cert_and_encrypted_attrs.xml +29 -0
  46. data/test/responses/response_with_multiple_attribute_values.xml +1 -1
  47. data/test/responses/slo_request.xml +4 -0
  48. data/test/settings_test.rb +25 -112
  49. data/test/slo_logoutrequest_test.rb +41 -44
  50. data/test/slo_logoutresponse_test.rb +87 -167
  51. data/test/test_helper.rb +27 -102
  52. data/test/xml_security_test.rb +114 -337
  53. metadata +34 -84
  54. data/lib/onelogin/ruby-saml/setting_error.rb +0 -6
  55. data/test/certificates/certificate.der +0 -0
  56. data/test/certificates/formatted_certificate +0 -14
  57. data/test/certificates/formatted_chained_certificate +0 -42
  58. data/test/certificates/formatted_private_key +0 -12
  59. data/test/certificates/formatted_rsa_private_key +0 -12
  60. data/test/certificates/invalid_certificate1 +0 -1
  61. data/test/certificates/invalid_certificate2 +0 -1
  62. data/test/certificates/invalid_certificate3 +0 -12
  63. data/test/certificates/invalid_chained_certificate1 +0 -1
  64. data/test/certificates/invalid_private_key1 +0 -1
  65. data/test/certificates/invalid_private_key2 +0 -1
  66. data/test/certificates/invalid_private_key3 +0 -10
  67. data/test/certificates/invalid_rsa_private_key1 +0 -1
  68. data/test/certificates/invalid_rsa_private_key2 +0 -1
  69. data/test/certificates/invalid_rsa_private_key3 +0 -10
  70. data/test/certificates/ruby-saml-2.crt +0 -15
  71. data/test/requests/logoutrequest_fixtures.rb +0 -47
  72. data/test/responses/encrypted_new_attack.xml.base64 +0 -1
  73. data/test/responses/invalids/invalid_issuer_assertion.xml.base64 +0 -1
  74. data/test/responses/invalids/invalid_issuer_message.xml.base64 +0 -1
  75. data/test/responses/invalids/multiple_signed.xml.base64 +0 -1
  76. data/test/responses/invalids/no_signature.xml.base64 +0 -1
  77. data/test/responses/invalids/response_with_concealed_signed_assertion.xml +0 -51
  78. data/test/responses/invalids/response_with_doubled_signed_assertion.xml +0 -49
  79. data/test/responses/invalids/signature_wrapping_attack.xml.base64 +0 -1
  80. data/test/responses/response_node_text_attack.xml.base64 +0 -1
  81. data/test/responses/response_with_concealed_signed_assertion.xml +0 -51
  82. data/test/responses/response_with_doubled_signed_assertion.xml +0 -49
  83. data/test/responses/response_with_multiple_attribute_statements.xml +0 -72
  84. data/test/responses/response_with_signed_assertion_3.xml +0 -30
  85. data/test/responses/response_with_signed_message_and_assertion.xml +0 -34
  86. data/test/responses/response_with_undefined_recipient.xml.base64 +0 -1
  87. data/test/responses/response_wrapped.xml.base64 +0 -150
  88. data/test/responses/valid_response.xml.base64 +0 -1
  89. data/test/responses/valid_response_without_x509certificate.xml.base64 +0 -1
  90. data/test/utils_test.rb +0 -231
data/Rakefile CHANGED
@@ -25,3 +25,17 @@ end
25
25
  task :test
26
26
 
27
27
  task :default => :test
28
+
29
+ # require 'rake/rdoctask'
30
+ # Rake::RDocTask.new do |rdoc|
31
+ # if File.exist?('VERSION')
32
+ # version = File.read('VERSION')
33
+ # else
34
+ # version = ""
35
+ # end
36
+
37
+ # rdoc.rdoc_dir = 'rdoc'
38
+ # rdoc.title = "ruby-saml #{version}"
39
+ # rdoc.rdoc_files.include('README*')
40
+ # rdoc.rdoc_files.include('lib/**/*.rb')
41
+ #end
@@ -1,13 +1,26 @@
1
1
  # RubySaml Changelog
2
-
3
- ### 0.8.4 (March 5, 2018)
4
- * Improve the fix for CVE-2017-11428 to parse CDATA properly
5
-
6
- ### 0.8.3 (Feb 27, 2018)
7
- * Fix vulnerability CVE-2017-11428. Process text of nodes properly, ignoring comments
8
- * Fix DigestMethod lookup bug #144
9
-
10
- ### 0.8.2 (Jan 26, 2014)
2
+ ### 0.9 (Jan 26, 2015)
3
+ * [#169](https://github.com/onelogin/ruby-saml/pull/169) WantAssertionSigned should be either true or false
4
+ * [#167](https://github.com/onelogin/ruby-saml/pull/167) (doc update) make unit of clock drift obvious
5
+ * [#160](https://github.com/onelogin/ruby-saml/pull/160) Extended solution for Attributes method [] can raise NoMethodError
6
+ * [#158](https://github.com/onelogin/ruby-saml/pull/1) Added ability to specify attribute services in metadata
7
+ * [#154](https://github.com/onelogin/ruby-saml/pull/154) Fix incorrect gem declaration statement
8
+ * [#152](https://github.com/onelogin/ruby-saml/pull/152) Fix the PR #99
9
+ * [#150](https://github.com/onelogin/ruby-saml/pull/150) Nokogiri already in gemspec
10
+ * [#147](https://github.com/onelogin/ruby-saml/pull/147) Fix LogoutResponse issuer validation and implement SAML Response issuer validation.
11
+ * [#144](https://github.com/onelogin/ruby-saml/pull/144) Fix DigestMethod lookup bug
12
+ * [#139](https://github.com/onelogin/ruby-saml/pull/139) Fixes handling of some soft and hard validation failures
13
+ * [#138](https://github.com/onelogin/ruby-saml/pull/138) Change logoutrequest.rb to UTC time
14
+ * [#136](https://github.com/onelogin/ruby-saml/pull/136) Remote idp metadata
15
+ * [#135](https://github.com/onelogin/ruby-saml/pull/135) Restored support for NIL as well as empty AttributeValues
16
+ * [#134](https://github.com/onelogin/ruby-saml/pull/134) explicitly require "onelogin/ruby-saml/logging"
17
+ * [#133](https://github.com/onelogin/ruby-saml/pull/133) Added license to gemspec
18
+ * [#132](https://github.com/onelogin/ruby-saml/pull/132) Support AttributeConsumingServiceIndex in AuthnRequest
19
+ * [#131](https://github.com/onelogin/ruby-saml/pull/131) Add ruby 2.1.1 to .travis.yml
20
+ * [#122](https://github.com/onelogin/ruby-saml/pull/122) Fixes #112 and #117 in a backwards compatible manner
21
+ * [#119](https://github.com/onelogin/ruby-saml/pull/119) Add support for extracting IdP details from metadata xml
22
+
23
+ ### 0.8.2 (Jan 26, 2015)
11
24
  * [#183](https://github.com/onelogin/ruby-saml/pull/183) Resolved a security vulnerability where string interpolation in a `REXML::XPath.first()` method call allowed for arbitrary code execution.
12
25
 
13
26
  ### 0.8.0 (Feb 21, 2014)
@@ -0,0 +1,34 @@
1
+ module OneLogin
2
+ module RubySaml
3
+ class AttributeService
4
+ attr_reader :attributes
5
+ attr_reader :name
6
+ attr_reader :index
7
+
8
+ def initialize
9
+ @index = "1"
10
+ @attributes = []
11
+ end
12
+
13
+ def configure(&block)
14
+ instance_eval &block
15
+ end
16
+
17
+ def configured?
18
+ @attributes.length > 0 && !@name.nil?
19
+ end
20
+
21
+ def service_name(name)
22
+ @name = name
23
+ end
24
+
25
+ def service_index(index)
26
+ @index = index
27
+ end
28
+
29
+ def add_attribute(options={})
30
+ attributes << options
31
+ end
32
+ end
33
+ end
34
+ end
@@ -1,118 +1,91 @@
1
1
  module OneLogin
2
2
  module RubySaml
3
-
4
- # SAML2 Attributes. Parse the Attributes from the AttributeStatement of the SAML Response.
5
- #
3
+ # Wraps all attributes and provides means to query them for single or multiple values.
4
+ #
5
+ # For backwards compatibility Attributes#[] returns *first* value for the attribute.
6
+ # Turn off compatibility to make it return all values as an array:
7
+ # Attributes.single_value_compatibility = false
6
8
  class Attributes
7
9
  include Enumerable
8
10
 
9
- attr_reader :attributes
10
-
11
11
  # By default Attributes#[] is backwards compatible and
12
12
  # returns only the first value for the attribute
13
13
  # Setting this to `false` returns all values for an attribute
14
14
  @@single_value_compatibility = true
15
15
 
16
- # @return [Boolean] Get current status of backwards compatibility mode.
17
- #
16
+ # Get current status of backwards compatibility mode.
18
17
  def self.single_value_compatibility
19
18
  @@single_value_compatibility
20
19
  end
21
20
 
22
21
  # Sets the backwards compatibility mode on/off.
23
- # @param value [Boolean]
24
- #
25
22
  def self.single_value_compatibility=(value)
26
23
  @@single_value_compatibility = value
27
24
  end
28
25
 
29
- # @param attrs [Hash] The +attrs+ must be a Hash with attribute names as keys and **arrays** as values:
26
+ # Initialize Attributes collection, optionally taking a Hash of attribute names and values.
27
+ #
28
+ # The +attrs+ must be a Hash with attribute names as keys and **arrays** as values:
30
29
  # Attributes.new({
31
30
  # 'name' => ['value1', 'value2'],
32
31
  # 'mail' => ['value1'],
33
32
  # })
34
- #
35
33
  def initialize(attrs = {})
36
34
  @attributes = attrs
37
35
  end
38
36
 
39
37
 
40
38
  # Iterate over all attributes
41
- #
42
39
  def each
43
40
  attributes.each{|name, values| yield name, values}
44
41
  end
45
42
 
46
-
47
43
  # Test attribute presence by name
48
- # @param name [String] The attribute name to be checked
49
- #
50
44
  def include?(name)
51
- attributes.has_key?(canonize_name(name)) || attributes.has_key?(name)
45
+ attributes.has_key?(canonize_name(name))
52
46
  end
53
47
 
54
48
  # Return first value for an attribute
55
- # @param name [String] The attribute name
56
- # @return [String] The value (First occurrence)
57
- #
58
49
  def single(name)
59
- multi(name).first if include?(name)
50
+ attributes[canonize_name(name)].first if include?(name)
60
51
  end
61
52
 
62
53
  # Return all values for an attribute
63
- # @param name [String] The attribute name
64
- # @return [Array] Values of the attribute
65
- #
66
54
  def multi(name)
67
- values = attributes[canonize_name(name)] || attributes[name]
68
-
69
- if values.is_a?(Array)
70
- values
71
- elsif !values.nil?
72
- Array(values)
73
- else
74
- nil
75
- end
55
+ attributes[canonize_name(name)]
76
56
  end
77
57
 
78
- # Retrieve attribute value(s)
79
- # @param name [String] The attribute name
80
- # @return [String|Array] Depending on the single value compatibility status this returns:
81
- # - First value if single_value_compatibility = true
82
- # response.attributes['mail'] # => 'user@example.com'
83
- # - All values if single_value_compatibility = false
84
- # response.attributes['mail'] # => ['user@example.com','user@example.net']
58
+ # By default returns first value for an attribute.
59
+ #
60
+ # Depending on the single value compatibility status this returns first value
61
+ # Attributes.single_value_compatibility = true # Default
62
+ # response.attributes['mail'] # => 'user@example.com'
85
63
  #
64
+ # Or all values:
65
+ # Attributes.single_value_compatibility = false
66
+ # response.attributes['mail'] # => ['user@example.com','user@example.net']
86
67
  def [](name)
87
- self.class.single_value_compatibility ? single(name) : multi(name)
68
+ self.class.single_value_compatibility ? single(canonize_name(name)) : multi(canonize_name(name))
88
69
  end
89
70
 
90
- # @return [Array] Return all attributes as an array
91
- #
71
+ # Return all attributes as an array
92
72
  def all
93
73
  attributes
94
74
  end
95
75
 
96
- # @param name [String] The attribute name
97
- # @param values [Array] The values
98
- #
76
+ # Set values for an attribute, overwriting all existing values
99
77
  def set(name, values)
100
78
  attributes[canonize_name(name)] = values
101
79
  end
102
80
  alias_method :[]=, :set
103
81
 
104
- # @param name [String] The attribute name
105
- # @param values [Array] The values
106
- #
82
+ # Add new attribute or new value(s) to an existing attribute
107
83
  def add(name, values = [])
108
84
  attributes[canonize_name(name)] ||= []
109
85
  attributes[canonize_name(name)] += Array(values)
110
86
  end
111
87
 
112
88
  # Make comparable to another Attributes collection based on attributes
113
- # @param other [Attributes] An Attributes object to compare with
114
- # @return [Boolean] True if are contains the same attributes and values
115
- #
116
89
  def ==(other)
117
90
  if other.is_a?(Attributes)
118
91
  all == other.all
@@ -121,26 +94,15 @@ module OneLogin
121
94
  end
122
95
  end
123
96
 
124
- def respond_to?(name)
125
- attributes.respond_to?(name) || super
126
- end
127
-
128
97
  protected
129
98
 
130
99
  # stringifies all names so both 'email' and :email return the same result
131
- # @param name [String] The attribute name
132
- # @return [String] stringified name
133
- #
134
100
  def canonize_name(name)
135
101
  name.to_s
136
102
  end
137
103
 
138
- def method_missing(name, *args, &block)
139
- if attributes.respond_to?(name)
140
- attributes.send(name, *args, &block)
141
- else
142
- super
143
- end
104
+ def attributes
105
+ @attributes
144
106
  end
145
107
  end
146
108
  end
@@ -1,21 +1,16 @@
1
- require "base64"
2
- require "zlib"
3
- require "cgi"
4
- require "onelogin/ruby-saml/utils"
5
- require "onelogin/ruby-saml/setting_error"
1
+ require "uuid"
2
+
3
+ require "onelogin/ruby-saml/logging"
6
4
 
7
5
  module OneLogin
8
6
  module RubySaml
7
+ include REXML
8
+ class Authrequest < SamlMessage
9
9
 
10
- class Authrequest
11
- # AuthNRequest ID
12
- attr_reader :uuid
10
+ attr_reader :uuid # Can be obtained if neccessary
13
11
 
14
- # Initializes the AuthNRequest. An Authrequest Object.
15
- # Asigns an ID, a random uuid.
16
- #
17
12
  def initialize
18
- @uuid = OneLogin::RubySaml::Utils.uuid
13
+ @uuid = "_" + UUID.new.generate
19
14
  end
20
15
 
21
16
  def create(settings, params = {})
@@ -26,25 +21,11 @@ module OneLogin
26
21
  params.each_pair do |key, value|
27
22
  request_params << "&#{key.to_s}=#{CGI.escape(value.to_s)}"
28
23
  end
29
- raise SettingError.new "Invalid settings, idp_sso_target_url is not set!" if settings.idp_sso_target_url.nil? or settings.idp_sso_target_url.empty?
30
24
  @login_url = settings.idp_sso_target_url + request_params
31
25
  end
32
26
 
33
- # Creates the Get parameters for the request.
34
- # @param settings [OneLogin::RubySaml::Settings|nil] Toolkit settings
35
- # @param params [Hash] Some extra parameters to be added in the GET for example the RelayState
36
- # @return [Hash] Parameters
37
- #
38
27
  def create_params(settings, params={})
39
- # The method expects :RelayState but sometimes we get 'RelayState' instead.
40
- # Based on the HashWithIndifferentAccess value in Rails we could experience
41
- # conflicts so this line will solve them.
42
- relay_state = params[:RelayState] || params['RelayState']
43
-
44
- if relay_state.nil?
45
- params.delete(:RelayState)
46
- params.delete('RelayState')
47
- end
28
+ params = {} if params.nil?
48
29
 
49
30
  request_doc = create_authentication_xml_doc(settings)
50
31
  request_doc.context[:attribute_quote] = :quote if settings.double_quote_xml_attribute_values
@@ -54,30 +35,18 @@ module OneLogin
54
35
 
55
36
  Logging.debug "Created AuthnRequest: #{request}"
56
37
 
57
- request = Zlib::Deflate.deflate(request, 9)[2..-5] if settings.compress_request
58
- if Base64.respond_to?('strict_encode64')
59
- base64_request = Base64.strict_encode64(request)
60
- else
61
- base64_request = Base64.encode64(request).gsub(/\n/, "")
62
- end
63
-
38
+ request = deflate(request) if settings.compress_request
39
+ base64_request = encode(request)
64
40
  request_params = {"SAMLRequest" => base64_request}
65
41
 
66
42
  if settings.security[:authn_requests_signed] && !settings.security[:embed_sign] && settings.private_key
67
- params['SigAlg'] = settings.security[:signature_method]
68
- url_string = OneLogin::RubySaml::Utils.build_query(
69
- :type => 'SAMLRequest',
70
- :data => base64_request,
71
- :relay_state => relay_state,
72
- :sig_alg => params['SigAlg']
73
- )
74
- sign_algorithm = XMLSecurity::BaseDocument.new.algorithm(settings.security[:signature_method])
75
- signature = settings.get_sp_key.sign(sign_algorithm.new, url_string)
76
- if Base64.respond_to?('strict_encode64')
77
- params['Signature'] = Base64.strict_encode64(signature)
78
- else
79
- params['Signature'] = Base64.encode64(signature).gsub(/\n/, "")
80
- end
43
+ params['SigAlg'] = XMLSecurity::Document::SHA1
44
+ url_string = "SAMLRequest=#{CGI.escape(base64_request)}"
45
+ url_string += "&RelayState=#{CGI.escape(params['RelayState'])}" if params['RelayState']
46
+ url_string += "&SigAlg=#{CGI.escape(params['SigAlg'])}"
47
+ private_key = settings.get_sp_key()
48
+ signature = private_key.sign(XMLSecurity::BaseDocument.new.algorithm(settings.security[:signature_method]).new, url_string)
49
+ params['Signature'] = encode(signature)
81
50
  end
82
51
 
83
52
  params.each_pair do |key, value|
@@ -88,12 +57,7 @@ module OneLogin
88
57
  end
89
58
 
90
59
  def create_authentication_xml_doc(settings)
91
- document = create_xml_document(settings)
92
- sign_document(document, settings)
93
- end
94
-
95
- def create_xml_document(settings)
96
- time = Time.now.utc.strftime('%Y-%m-%dT%H:%M:%SZ')
60
+ time = Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ")
97
61
 
98
62
  request_doc = XMLSecurity::Document.new
99
63
  request_doc.uuid = uuid
@@ -102,65 +66,59 @@ module OneLogin
102
66
  root.attributes['ID'] = uuid
103
67
  root.attributes['IssueInstant'] = time
104
68
  root.attributes['Version'] = "2.0"
105
- root.attributes['Destination'] = settings.idp_sso_target_url unless settings.idp_sso_target_url.nil? or settings.idp_sso_target_url.empty?
69
+ root.attributes['Destination'] = settings.idp_sso_target_url unless settings.idp_sso_target_url.nil?
106
70
  root.attributes['IsPassive'] = settings.passive unless settings.passive.nil?
107
71
  root.attributes['ProtocolBinding'] = settings.protocol_binding unless settings.protocol_binding.nil?
72
+ root.attributes["AttributeConsumingServiceIndex"] = settings.attributes_index unless settings.attributes_index.nil?
108
73
  root.attributes['ForceAuthn'] = settings.force_authn unless settings.force_authn.nil?
109
74
 
110
75
  # Conditionally defined elements based on settings
111
76
  if settings.assertion_consumer_service_url != nil
112
77
  root.attributes["AssertionConsumerServiceURL"] = settings.assertion_consumer_service_url
113
78
  end
114
- if settings.sp_entity_id != nil
79
+ if settings.issuer != nil
115
80
  issuer = root.add_element "saml:Issuer"
116
- issuer.text = settings.sp_entity_id
117
- end
118
-
119
- if settings.name_identifier_value_requested != nil
120
- subject = root.add_element "saml:Subject"
121
-
122
- nameid = subject.add_element "saml:NameID"
123
- nameid.attributes['Format'] = settings.name_identifier_format if settings.name_identifier_format
124
- nameid.text = settings.name_identifier_value_requested
125
-
126
- subject_confirmation = subject.add_element "saml:SubjectConfirmation"
127
- subject_confirmation.attributes['Method'] = "urn:oasis:names:tc:SAML:2.0:cm:bearer"
81
+ issuer.text = settings.issuer
128
82
  end
129
-
130
83
  if settings.name_identifier_format != nil
131
84
  root.add_element "samlp:NameIDPolicy", {
132
- "xmlns:samlp" => "urn:oasis:names:tc:SAML:2.0:protocol",
133
85
  # Might want to make AllowCreate a setting?
134
86
  "AllowCreate" => "true",
135
87
  "Format" => settings.name_identifier_format
136
88
  }
137
89
  end
138
90
 
139
- # BUG fix here -- if an authn_context is defined, add the tags with an "exact"
140
- # match required for authentication to succeed. If this is not defined,
141
- # the IdP will choose default rules for authentication. (Shibboleth IdP)
142
- if settings.authn_context != nil
91
+ if settings.authn_context || settings.authn_context_decl_ref
92
+
93
+ if settings.authn_context_comparison != nil
94
+ comparison = settings.authn_context_comparison
95
+ else
96
+ comparison = 'exact'
97
+ end
98
+
143
99
  requested_context = root.add_element "samlp:RequestedAuthnContext", {
144
- "xmlns:samlp" => "urn:oasis:names:tc:SAML:2.0:protocol",
145
- "Comparison" => "exact",
146
- }
147
- class_ref = requested_context.add_element "saml:AuthnContextClassRef", {
148
- "xmlns:saml" => "urn:oasis:names:tc:SAML:2.0:assertion",
100
+ "Comparison" => comparison,
149
101
  }
150
- class_ref.text = settings.authn_context
102
+
103
+ if settings.authn_context != nil
104
+ class_ref = requested_context.add_element "saml:AuthnContextClassRef"
105
+ class_ref.text = settings.authn_context
106
+ end
107
+ # add saml:AuthnContextDeclRef element
108
+ if settings.authn_context_decl_ref != nil
109
+ class_ref = requested_context.add_element "saml:AuthnContextDeclRef"
110
+ class_ref.text = settings.authn_context_decl_ref
111
+ end
151
112
  end
152
- request_doc
153
- end
154
113
 
155
- def sign_document(document, settings)
156
- # embed signature
157
- if settings.security[:authn_requests_signed] && settings.private_key && settings.certificate && settings.security[:embed_sign]
158
- private_key = settings.get_sp_key
159
- cert = settings.get_sp_cert
160
- document.sign_document(private_key, cert, settings.security[:signature_method], settings.security[:digest_method])
114
+ # embebed sign
115
+ if settings.security[:authn_requests_signed] && settings.private_key && settings.certificate && settings.security[:embed_sign]
116
+ private_key = settings.get_sp_key()
117
+ cert = settings.get_sp_cert()
118
+ request_doc.sign_document(private_key, cert, settings.security[:signature_method], settings.security[:digest_method])
161
119
  end
162
120
 
163
- document
121
+ request_doc
164
122
  end
165
123
 
166
124
  end