Module: SSO::Server::Passports

Extended by:
Logging
Defined in:
lib/sso/server/passports.rb

Overview

This is the one interaction point with persisting and querying Passports.

Class Method Summary collapse

Methods included from Logging

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

Class Method Details

.find(id) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
# File 'lib/sso/server/passports.rb', line 7

def self.find(id)
  record = backend.find_by_id(id)

  if record
    Operations.success(:record_found, object: record)
  else
    Operations.failure :record_not_found
  end

rescue => exception
  Operations.failure :backend_error, object: exception
end

.find_by_access_token_id(id) ⇒ Object



20
21
22
23
24
25
26
27
28
# File 'lib/sso/server/passports.rb', line 20

def self.find_by_access_token_id(id)
  record = backend.where(revoked_at: nil).find_by_oauth_access_token_id(id)

  if record
    Operations.success(:record_found, object: record)
  else
    Operations.failure :record_not_found
  end
end

.generate(owner_id:, ip:, agent:, device: nil) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/sso/server/passports.rb', line 30

def self.generate(owner_id:, ip:, agent:, device: nil)
  debug { "Generating Passport for user ID #{owner_id.inspect} and IP #{ip.inspect} and Agent #{agent.inspect} and Device #{device.inspect}" }

  record = backend.create owner_id: owner_id, ip: ip, agent: agent, device: device

  if record.persisted?
    debug { "Successfully generated passport with ID #{record.id}" }
    Operations.success :generation_successful, object: record.id
  else
    Operations.failure :persistence_failed, object: record.errors.to_hash
  end
end

.logout(passport_id:) ⇒ Object



111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/sso/server/passports.rb', line 111

def self.logout(passport_id:)
  return Operations.failure(:missing_passport_id) if passport_id.blank?

  debug { "Logging out Passport with ID #{passport_id.inspect}" }
  record = backend.find_by_id passport_id
  return Operations.success(:passport_does_not_exist) unless record
  return Operations.success(:passport_already_revoked) if record.revoked_at

  if record.update_attributes revoked_at: Time.now, revoke_reason: :logout
    Operations.success :passport_revoked
  else
    Operations.failure :backend_could_not_revoke_passport
  end
end

.register_access_token_from_grant(grant_token:, access_token:) ⇒ Object



82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/sso/server/passports.rb', line 82

def self.register_access_token_from_grant(grant_token:, access_token:)
  access_grant = find_valid_access_grant(grant_token)             { |failure| return failure }
  access_token = find_valid_access_token(access_token)            { |failure| return failure }
  record       = find_valid_passport_by_grant_id(access_grant.id) { |failure| return failure }

  is_insider = access_token.scopes.include? 'insider'

  if record.update_attributes oauth_access_token_id: access_token.id, insider: is_insider
    debug { "Successfully augmented Passport #{record.id} with Access Token ID #{access_token.id} which is #{access_token.token}" }
    Operations.success :passport_known_by_grant_augmented_with_access_token
  else
    Operations.failure :could_not_augment_passport_known_by_grant_with_access_token
  end
end

.register_access_token_from_id(passport_id:, access_token:) ⇒ Object



97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/sso/server/passports.rb', line 97

def self.register_access_token_from_id(passport_id:, access_token:)
  access_token = find_valid_access_token(access_token) { |failure| return failure }
  record       = find_valid_passport(passport_id)      { |failure| return failure }

  is_insider = access_token.scopes.include? 'insider'

  if record.update_attributes oauth_access_token_id: access_token.id, insider: is_insider
    debug { "Successfully augmented #{is_insider ? :insider : :outsider} Passport #{record.id} with Access Token ID #{access_token.id} which is #{access_token.token}" }
    Operations.success :passport_augmented_with_access_token
  else
    Operations.failure :could_not_augment_passport_with_access_token
  end
end

.register_authorization_grant(passport_id:, token:) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
# File 'lib/sso/server/passports.rb', line 70

def self.register_authorization_grant(passport_id:, token:)
  record       = find_valid_passport(passport_id) { |failure| return failure }
  access_grant = find_valid_access_grant(token)   { |failure| return failure }

  if record.update_attribute :oauth_access_grant_id, access_grant.id
    debug { "Successfully augmented Passport #{record.id} with Authorization Grant ID #{access_grant.id} which is #{access_grant.token}" }
    Operations.success :passport_augmented_with_access_token
  else
    Operations.failure :could_not_augment_passport_with_access_token
  end
end

.update_activity(passport_id:, request:) ⇒ Object



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.rb', line 43

def self.update_activity(passport_id:, request:)
  record = find_valid_passport(passport_id) { |failure| return failure }

  immediate_ip = request.respond_to?(:remote_ip) ? request.remote_ip : request.ip
  if record.insider?
    proxied_ip = request['ip']
    unless proxied_ip
      warn { "There should have been a proxied IP param, but there was none. I will use the immediare 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.params['device_id'] }
  end
  attributes.merge! activity_at: Time.now

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

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