Class: WSDL::Response::SecurityContext

Inherits:
Object
  • Object
show all
Defined in:
lib/wsdl/response/security_context.rb

Overview

Encapsulates security verification for SOAP responses.

This class handles signature verification, certificate validation, and timestamp freshness checking as a unified security context. It provides a clean API for verifying that a SOAP response is authentic and fresh.

Examples:

Basic signature verification

response = operation.invoke
if response.security.signature_valid?
  puts "Response is signed and valid"
else
  puts "Errors: #{response.security.errors}"
end

Combined verification (signature + timestamp)

response = operation.invoke
if response.security.valid?
  puts "Response is secure"
end

Strict verification with exceptions

begin
  response.security.verify!
rescue WSDL::SecurityError => e
  puts "Security verification failed: #{e.message}"
end

See Also:

Instance Method Summary collapse

Constructor Details

#initialize(raw_xml, verification = Security::ResponseVerification::Options.default, certificate: nil) ⇒ SecurityContext

Creates a new SecurityContext instance.

Parameters:

  • raw_xml (String)

    the raw SOAP response XML

  • verification (Security::ResponseVerification) (defaults to: Security::ResponseVerification::Options.default)

    verification options for certificate and timestamp validation

  • certificate (OpenSSL::X509::Certificate, nil) (defaults to: nil)

    optional certificate to use for verification instead of extracting from message

Raises:

  • (ArgumentError)


43
44
45
46
47
48
49
# File 'lib/wsdl/response/security_context.rb', line 43

def initialize(raw_xml, verification = Security::ResponseVerification::Options.default, certificate: nil)
  raise ArgumentError, "Expected String, got #{raw_xml.class}" unless raw_xml.is_a?(String)

  @raw_xml = raw_xml
  @verification = verification
  @certificate = certificate
end

Instance Method Details

#digest_algorithmString?

Returns the digest algorithm used.

Returns:

  • (String, nil)

    the algorithm URI from the first reference



161
162
163
# File 'lib/wsdl/response/security_context.rb', line 161

def digest_algorithm
  verifier.digest_algorithm
end

#errorsArray<String>

Returns all errors from security verification.

Includes signature verification errors and, when timestamp validation is enabled, any timestamp errors.

Returns:

  • (Array<String>)

    error messages



239
240
241
242
243
244
245
# File 'lib/wsdl/response/security_context.rb', line 239

def errors
  all_errors = verifier.errors.dup

  all_errors.concat(verifier.timestamp_errors) if @verification.timestamp.validate && !verifier.timestamp_valid?

  all_errors.uniq
end

#signature_algorithmString?

Returns the signature algorithm used.

Returns:

  • (String, nil)

    the algorithm URI



153
154
155
# File 'lib/wsdl/response/security_context.rb', line 153

def signature_algorithm
  verifier.signature_algorithm
end

#signature_present?Boolean

Returns whether the response contains a signature.

Returns:

  • (Boolean)

    true if a ds:Signature element is present



92
93
94
# File 'lib/wsdl/response/security_context.rb', line 92

def signature_present?
  verifier.signature_present?
end

#signature_valid?Boolean

Returns whether the response signature is valid.

This performs full signature verification including:

  • Locating the signing certificate (from BinarySecurityToken or provided)
  • Verifying all Reference digests match the signed elements
  • Enforcing that SignedInfo references the SOAP Body
  • Verifying the SignatureValue over the canonicalized SignedInfo

Returns false if no signature is present. Use #signature_present? to distinguish between "no signature" and "invalid signature".

Returns:

  • (Boolean)

    true if signature is present and valid



109
110
111
112
113
# File 'lib/wsdl/response/security_context.rb', line 109

def signature_valid?
  return false unless signature_present?

  verifier.valid?
end

#signed_element_idsArray<String>

Returns the IDs of all signed elements.

Returns:

  • (Array<String>)

    element IDs (e.g., ['Body-abc123', 'Timestamp-xyz789'])



137
138
139
# File 'lib/wsdl/response/security_context.rb', line 137

def signed_element_ids
  verifier.signed_element_ids
end

#signed_elementsArray<String>

Returns the names of all signed elements.

Returns:

  • (Array<String>)

    element names (e.g., ['Body', 'Timestamp'])



145
146
147
# File 'lib/wsdl/response/security_context.rb', line 145

def signed_elements
  verifier.signed_elements
end

#signing_certificateOpenSSL::X509::Certificate?

Returns the certificate used to sign the response.

Returns:

  • (OpenSSL::X509::Certificate, nil)

    the signing certificate



169
170
171
172
173
# File 'lib/wsdl/response/security_context.rb', line 169

def signing_certificate
  # Trigger verification to extract certificate
  verifier.valid? unless verifier.certificate
  verifier.certificate
end

#timestampHash?

Returns the parsed timestamp information.

Returns:

  • (Hash, nil)

    hash with :created_at and :expires_at keys, or nil if no timestamp present



224
225
226
# File 'lib/wsdl/response/security_context.rb', line 224

def timestamp
  verifier.timestamp
end

#timestamp_present?Boolean

Returns whether the response contains a timestamp.

Returns:

  • (Boolean)

    true if wsu:Timestamp exists in the Security header



183
184
185
# File 'lib/wsdl/response/security_context.rb', line 183

def timestamp_present?
  verifier.timestamp_present?
end

#timestamp_valid?Boolean

Returns whether the response timestamp is valid (fresh).

Returns true if:

  • Timestamp validation is disabled
  • No timestamp is present (timestamps are optional per spec)
  • Timestamp is present and within acceptable time bounds

Returns:

  • (Boolean)

    true if timestamp is valid or not present



196
197
198
199
200
# File 'lib/wsdl/response/security_context.rb', line 196

def timestamp_valid?
  return true unless @verification.timestamp.validate

  verifier.timestamp_valid?
end

#valid?Boolean

Returns whether the response passes all security checks.

This performs combined verification of:

  • Signature (if present)
  • Timestamp freshness (if enabled and present)

Returns:

  • (Boolean)

    true if all security checks pass



63
64
65
66
67
# File 'lib/wsdl/response/security_context.rb', line 63

def valid?
  return false unless signature_present?

  verifier.valid? && timestamp_valid?
end

#verify!true

Verifies the response and raises an error if any check fails.

This performs combined verification of signature and timestamp, raising the appropriate error type for the first failure encountered.

Returns:

  • (true)

    if all checks pass

Raises:



78
79
80
81
82
# File 'lib/wsdl/response/security_context.rb', line 78

def verify! # rubocop:disable Naming/PredicateMethod
  verify_signature!
  verify_timestamp!
  true
end

#verify_signature!true

Verifies the signature and raises an error if invalid.

A valid signature must include a SignedInfo reference to SOAP Body.

Returns:

  • (true)

    if signature is valid

Raises:



122
123
124
125
126
127
128
129
130
131
# File 'lib/wsdl/response/security_context.rb', line 122

def verify_signature!
  raise SignatureVerificationError, 'Response does not contain a signature' unless signature_present?

  unless signature_valid?
    sig_errors = verifier.errors.join('; ')
    raise SignatureVerificationError, "Signature verification failed: #{sig_errors}"
  end

  true
end

#verify_timestamp!true

Verifies the timestamp and raises an error if invalid.

Returns:

  • (true)

    if timestamp is valid

Raises:



207
208
209
210
211
212
213
214
215
216
217
# File 'lib/wsdl/response/security_context.rb', line 207

def verify_timestamp! # rubocop:disable Naming/PredicateMethod
  return true unless @verification.timestamp.validate
  return true unless timestamp_present?

  unless verifier.timestamp_valid?
    ts_errors = verifier.timestamp_errors.join('; ')
    raise TimestampValidationError, "Timestamp validation failed: #{ts_errors}"
  end

  true
end