Class: WashOut::Wsse

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

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(token) ⇒ Wsse

Returns a new instance of Wsse.



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

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

Class Method Details

.authenticate(token) ⇒ Object



4
5
6
7
8
9
10
# File 'lib/wash_out/wsse.rb', line 4

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

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

Instance Method Details

#eligible?Boolean

Returns:

  • (Boolean)


61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/wash_out/wsse.rb', line 61

def eligible?
  return true unless required?

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

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

  if (expected_user == user && matches_expected_digest?(password))
    return true
  end

  return false
end

#expected_passwordObject



27
28
29
# File 'lib/wash_out/wsse.rb', line 27

def expected_password
  WashOut::Engine.wsse_password
end

#expected_userObject



23
24
25
# File 'lib/wash_out/wsse.rb', line 23

def expected_user
  WashOut::Engine.wsse_username
end

#matches_expected_digest?(password) ⇒ Boolean

Returns:

  • (Boolean)


31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/wash_out/wsse.rb', line 31

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

  return false if nonce.nil? || timestamp.nil?

  # 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 - DateTime.parse(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 + expected_password
  flavors << Base64.encode64(Digest::SHA1.hexdigest(token)).chomp!

  # Java
  token = Base64.decode64(nonce) + timestamp + expected_password
  flavors << Base64.encode64(Digest::SHA1.digest(token)).chomp!

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

  return false
end

#required?Boolean

Returns:

  • (Boolean)


19
20
21
# File 'lib/wash_out/wsse.rb', line 19

def required?
  !WashOut::Engine.wsse_username.blank?
end