Class: SSO::Server::Passports::Activity

Inherits:
Object
  • Object
show all
Includes:
Logging
Defined in:
lib/sso/server/passports/activity.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Logging

#debug, #error, #fatal, #info, #logger, #progname, #warn

Constructor Details

#initialize(passport:, request:) ⇒ Activity

Returns a new instance of Activity.



9
10
11
12
# File 'lib/sso/server/passports/activity.rb', line 9

def initialize(passport:, request:)
  @passport = passport
  @request = request
end

Instance Attribute Details

#passportObject (readonly)

Returns the value of attribute passport.



7
8
9
# File 'lib/sso/server/passports/activity.rb', line 7

def passport
  @passport
end

#requestObject (readonly)

Returns the value of attribute request.



7
8
9
# File 'lib/sso/server/passports/activity.rb', line 7

def request
  @request
end

Instance Method Details

#callObject



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/sso/server/passports/activity.rb', line 14

def call
  if passport.insider? || trusted_proxy_app?
    proxied_ip = request['ip']
    unless proxied_ip
      warn { "There should have been a proxied IP param, but there was none. I will use the immediate IP #{immediate_ip} now." }
      proxied_ip = immediate_ip
    end
    attributes = { ip: proxied_ip, agent: request['agent'], device: request['device_id'] }
  else
    attributes = { ip: immediate_ip, agent: request.user_agent, device: request['device_id'] }
  end
  attributes.merge! activity_at: Time.now

  passport.stamps ||= {}  # <- Not thread-safe, this may potentially delete all existing stamps, I guess
  passport.stamps[attributes[:ip]] = Time.now.to_i

  debug { "Updating activity of #{passport.insider? ? :insider : :outsider} Passport #{passport.id.inspect} using IP #{attributes[:ip]} agent #{attributes[:agent]} and device #{attributes[:device]}" }
  if passport.update_attributes(attributes)
    Operations.success :passport_metadata_updated
  else
    Operations.failure :could_not_update_passport_activity, object: passport.errors.to_hash
  end
end

#immediate_ipObject



86
87
88
# File 'lib/sso/server/passports/activity.rb', line 86

def immediate_ip
  request.respond_to?(:remote_ip) ? request.remote_ip : request.ip
end

#insider_idObject



78
79
80
# File 'lib/sso/server/passports/activity.rb', line 78

def insider_id
  request['insider_id']
end

#insider_signatureObject



82
83
84
# File 'lib/sso/server/passports/activity.rb', line 82

def insider_signature
  request['insider_signature']
end

#proxied_ipObject



74
75
76
# File 'lib/sso/server/passports/activity.rb', line 74

def proxied_ip
  request['ip']
end

#signature_digestObject



70
71
72
# File 'lib/sso/server/passports/activity.rb', line 70

def signature_digest
  OpenSSL::Digest.new 'sha1'
end

#trusted_proxy_app?Boolean

Returns:

  • (Boolean)


38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/sso/server/passports/activity.rb', line 38

def trusted_proxy_app?
  unless insider_id
    debug { 'This is an immediate request because there is no insider_id param' }
    return
  end

  unless insider_signature
    debug { 'This is an immediate request because there is no insider_signature param' }
    return
  end

  application = ::Doorkeeper::Application.find_by_id(insider_id)
  unless application
    warn { 'The insider_id param does not correspond to an existing Doorkeeper Application' }
    return
  end

  unless application.scopes.include?('insider')
    warn { 'The Doorkeeper Application belonging to this insider_id param is considered an outsider' }
    return
  end

  expected_signature = ::OpenSSL::HMAC.hexdigest signature_digest, application.secret, proxied_ip
  unless insider_signature == expected_signature
    warn { "The insider signature #{insider_signature.inspect} does not match my expectation #{expected_signature.inspect}" }
    return
  end

  debug { 'This is a proxied request because insider_id and insider_signature are valid' }
  true
end