Class: WashOut::Wsse

Inherits:
Object
  • Object
show all
Defined in:
lib/wash_out/wsse.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(soap_config, token) ⇒ Wsse

Returns a new instance of Wsse.



21
22
23
24
25
26
27
# File 'lib/wash_out/wsse.rb', line 21

def initialize(soap_config, token)
  @soap_config = soap_config
  if token.blank? && required?
    raise WashOut::Dispatcher::SOAPError, "Missing required UsernameToken"
  end
  @username_token = token
end

Instance Attribute Details

#soap_configObject (readonly)

Returns the value of attribute soap_config.



12
13
14
# File 'lib/wash_out/wsse.rb', line 12

def soap_config
  @soap_config
end

Class Method Details

.authenticate(soap_config, token) ⇒ Object



13
14
15
16
17
18
19
# File 'lib/wash_out/wsse.rb', line 13

def self.authenticate(soap_config, token)
  wsse = self.new(soap_config, token)

  unless wsse.eligible?
    raise WashOut::Dispatcher::SOAPError, "Unauthorized"
  end
end

.matches_expected_digest?(expected_password, password, nonce, timestamp) ⇒ Boolean

Returns:

  • (Boolean)


73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/wash_out/wsse.rb', line 73

def self.matches_expected_digest?(expected_password, password, nonce, timestamp)
  return false if nonce.nil? || timestamp.nil?

  timestamp = timestamp.to_datetime

  # Token should not be accepted if timestamp is older than 5 minutes ago
  # http://www.oasis-open.org/committees/download.php/16782/wss-v1.1-spec-os-UsernameTokenProfile.pdf
  offset_in_minutes = ((DateTime.now - timestamp)* 24 * 60).to_i
  return false if offset_in_minutes >= 5

  # There are a few different implementations of the digest calculation

  flavors = Array.new

  # Ruby / Savon
  token = nonce + timestamp.strftime("%Y-%m-%dT%H:%M:%SZ") + expected_password
  flavors << Base64.encode64(Digest::SHA1.hexdigest(token)).chomp!

  # Java
  token = Base64.decode64(nonce) + timestamp.strftime("%Y-%m-%dT%H:%M:%SZ") + expected_password
  flavors << Base64.encode64(Digest::SHA1.digest(token)).chomp!

  # SoapUI
  token = Base64.decode64(nonce) + timestamp.strftime("%Y-%m-%dT%H:%M:%S.%3NZ") + expected_password
  flavors << Base64.encode64(Digest::SHA1.digest(token)).chomp!

  flavors.each do |f|
    return true if f == password
  end

  return false
end

Instance Method Details

#auth_callback?Boolean

Returns:

  • (Boolean)


33
34
35
# File 'lib/wash_out/wsse.rb', line 33

def auth_callback?
  return !!soap_config.wsse_auth_callback && soap_config.wsse_auth_callback.respond_to?(:call) && soap_config.wsse_auth_callback.arity == 4
end

#eligible?Boolean

Returns:

  • (Boolean)


49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/wash_out/wsse.rb', line 49

def eligible?
  return true unless required?

  user     = @username_token.values_at(:username, :Username).compact.first
  password = @username_token.values_at(:password, :Password).compact.first

  nonce = @username_token.values_at(:nonce, :Nonce).compact.first
  timestamp = @username_token.values_at(:created, :Created).compact.first

  if (expected_user == user && self.class.matches_expected_digest?(expected_password, password, nonce, timestamp))
    return true
  end

  if auth_callback?
    return perform_auth_callback(user, password, nonce, timestamp)
  end

  if (expected_user == user && expected_password == password)
    return true
  end

  return false
end

#expected_passwordObject



45
46
47
# File 'lib/wash_out/wsse.rb', line 45

def expected_password
  soap_config.wsse_password
end

#expected_userObject



41
42
43
# File 'lib/wash_out/wsse.rb', line 41

def expected_user
  soap_config.wsse_username
end

#perform_auth_callback(user, password, nonce, timestamp) ⇒ Object



37
38
39
# File 'lib/wash_out/wsse.rb', line 37

def perform_auth_callback(user, password, nonce, timestamp)
  soap_config.wsse_auth_callback.call(user, password, nonce, timestamp)
end

#required?Boolean

Returns:

  • (Boolean)


29
30
31
# File 'lib/wash_out/wsse.rb', line 29

def required?
  !soap_config.wsse_username.blank? || auth_callback?
end