Class: WSDL::Security::UsernameToken
- Inherits:
-
Object
- Object
- WSDL::Security::UsernameToken
- Defined in:
- lib/wsdl/security/username_token.rb
Overview
The digest algorithm (SHA-1) is mandated by the WS-Security UsernameToken Profile 1.1 specification and cannot be changed without breaking interoperability with compliant servers.
Represents a WS-Security UsernameToken element.
The UsernameToken provides username/password authentication for SOAP messages. It supports both plain text and digest password modes.
== Security Comparison
Choose the appropriate mode based on your security requirements:
- Password is sent as-is in the SOAP message
- Must only be used over HTTPS to protect the password in transit
- Simpler but provides no replay protection
- Suitable for: Development, trusted networks with HTTPS
- Password is never transmitted
- Computed as: +Base64(SHA-1(nonce + created + password))+
- Provides replay attack protection via nonce and timestamp
- Even if intercepted, attacker cannot recover the original password
- Suitable for: Production environments, sensitive operations
- For high-security requirements, consider using Signature instead
- Supports SHA-256/SHA-512 (configurable)
- Provides non-repudiation and stronger cryptographic guarantees
- Suitable for: Compliance requirements, financial transactions
== SHA-1 Protocol Limitation
The WS-Security UsernameToken Profile 1.1 specification mandates SHA-1 for password digests. This is a protocol constraint, not a design choice. Servers expecting WS-Security compliance will reject non-SHA-1 digests.
While SHA-1 has known weaknesses (collision attacks), these do not directly impact password digest security:
- Collision attacks find two inputs with the same hash — not useful for password cracking
- Preimage resistance (recovering input from hash) remains computationally infeasible
- The nonce changes every request, preventing precomputation attacks
- The real risk is weak passwords, not SHA-1 itself
For scenarios requiring stronger cryptographic algorithms, use X.509 certificate signatures which support SHA-256/SHA-512.
== Recommendations
- Always use HTTPS — regardless of password mode
- Prefer digest mode over plain text for production
- Use strong passwords — this is the primary security factor
- Consider X.509 signatures for high-security requirements
Constant Summary collapse
- PasswordType =
Local aliases for token profile constants
Constants::TokenProfiles::UsernameToken
- Encoding =
Alias for encoding URI constants used in UsernameToken XML.
Constants::Encoding
Instance Attribute Summary collapse
-
#created_at ⇒ Time
readonly
Returns the creation timestamp.
-
#id ⇒ String
readonly
Returns the unique ID for this token element.
-
#nonce ⇒ String?
readonly
Returns the nonce value (only present in digest mode).
-
#password ⇒ String
readonly
Returns the password (plain text, before digest if applicable).
-
#username ⇒ String
readonly
Returns the username.
Instance Method Summary collapse
-
#created_at_xml ⇒ String
Returns the created timestamp as an XML Schema dateTime string.
-
#digest? ⇒ Boolean
Returns whether digest authentication is enabled.
-
#encoded_nonce ⇒ String?
Returns the nonce encoded as Base64 (for XML output).
-
#initialize(username, password, digest: false, created_at: nil, id: nil) ⇒ UsernameToken
constructor
Creates a new UsernameToken instance.
-
#inspect ⇒ String
Returns a safe string representation that hides sensitive values.
-
#password_type ⇒ String
Returns the password type URI for the XML Type attribute.
-
#password_value ⇒ String
Returns the password value to include in the XML.
-
#to_hash ⇒ Hash
Returns a Hash representation suitable for Gyoku XML generation.
-
#to_xml(xml) ⇒ void
Builds the XML representation of the UsernameToken element.
Constructor Details
#initialize(username, password, digest: false, created_at: nil, id: nil) ⇒ UsernameToken
Creates a new UsernameToken instance.
110 111 112 113 114 115 116 117 |
# File 'lib/wsdl/security/username_token.rb', line 110 def initialize(username, password, digest: false, created_at: nil, id: nil) @username = username @password = password @digest = digest @created_at = (created_at || Time.now).utc @id = id || IdGenerator.for('UsernameToken') @nonce = generate_nonce if digest? end |
Instance Attribute Details
#created_at ⇒ Time (readonly)
Returns the creation timestamp.
96 97 98 |
# File 'lib/wsdl/security/username_token.rb', line 96 def created_at @created_at end |
#id ⇒ String (readonly)
Returns the unique ID for this token element.
100 101 102 |
# File 'lib/wsdl/security/username_token.rb', line 100 def id @id end |
#nonce ⇒ String? (readonly)
Returns the nonce value (only present in digest mode).
131 132 133 |
# File 'lib/wsdl/security/username_token.rb', line 131 def nonce @nonce end |
#password ⇒ String (readonly)
Returns the password (plain text, before digest if applicable).
92 93 94 |
# File 'lib/wsdl/security/username_token.rb', line 92 def password @password end |
#username ⇒ String (readonly)
Returns the username.
88 89 90 |
# File 'lib/wsdl/security/username_token.rb', line 88 def username @username end |
Instance Method Details
#created_at_xml ⇒ String
Returns the created timestamp as an XML Schema dateTime string.
147 148 149 |
# File 'lib/wsdl/security/username_token.rb', line 147 def created_at_xml @created_at.xmlschema end |
#digest? ⇒ Boolean
Returns whether digest authentication is enabled.
123 124 125 |
# File 'lib/wsdl/security/username_token.rb', line 123 def digest? @digest end |
#encoded_nonce ⇒ String?
Returns the nonce encoded as Base64 (for XML output).
137 138 139 140 141 |
# File 'lib/wsdl/security/username_token.rb', line 137 def encoded_nonce return nil unless @nonce Base64.strict_encode64(@nonce) end |
#inspect ⇒ String
Returns a safe string representation that hides sensitive values.
This method ensures that passwords and nonces are never accidentally exposed in logs, error messages, debugger output, or stack traces.
251 252 253 254 255 256 257 258 259 260 |
# File 'lib/wsdl/security/username_token.rb', line 251 def inspect parts = [ "username=#{@username.inspect}", 'password=[REDACTED]', "digest=#{@digest}" ] parts << 'nonce=[REDACTED]' if @nonce "#<#{self.class.name} #{parts.join(' ')}>" end |
#password_type ⇒ String
Returns the password type URI for the XML Type attribute.
170 171 172 173 174 175 176 |
# File 'lib/wsdl/security/username_token.rb', line 170 def password_type if digest? PasswordType::PASSWORD_DIGEST else PasswordType::PASSWORD_TEXT end end |
#password_value ⇒ String
Returns the password value to include in the XML.
For plain text mode, this is the original password. For digest mode, this is Base64(SHA-1(nonce + created + password)).
158 159 160 161 162 163 164 |
# File 'lib/wsdl/security/username_token.rb', line 158 def password_value if digest? compute_digest else @password end end |
#to_hash ⇒ Hash
Returns a Hash representation suitable for Gyoku XML generation.
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 |
# File 'lib/wsdl/security/username_token.rb', line 213 def to_hash token = { 'wsse:Username' => @username, 'wsse:Password' => password_value, :attributes! => { 'wsse:Password' => { 'Type' => password_type } } } if digest? token['wsse:Nonce'] = encoded_nonce token['wsu:Created'] = created_at_xml token[:attributes!]['wsse:Nonce'] = { 'EncodingType' => Encoding::BASE64 } token[:order!] = ['wsse:Username', 'wsse:Password', 'wsse:Nonce', 'wsu:Created'] else token[:order!] = ['wsse:Username', 'wsse:Password'] end { 'wsse:UsernameToken' => token, :attributes! => { 'wsse:UsernameToken' => { 'wsu:Id' => @id } } } end |
#to_xml(xml) ⇒ void
This method returns an undefined value.
Builds the XML representation of the UsernameToken element.
197 198 199 200 201 202 203 204 205 206 207 |
# File 'lib/wsdl/security/username_token.rb', line 197 def to_xml(xml) xml['wsse'].UsernameToken('wsu:Id' => @id) do xml['wsse'].Username(@username) xml['wsse'].Password(password_value, 'Type' => password_type) if digest? xml['wsse'].Nonce(encoded_nonce, 'EncodingType' => Encoding::BASE64) xml['wsu'].Created(created_at_xml) end end end |