Class: SignIn::SessionRefresher

Inherits:
Object
  • Object
show all
Defined in:
app/services/sign_in/session_refresher.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(refresh_token:, anti_csrf_token:) ⇒ SessionRefresher

Returns a new instance of SessionRefresher.



7
8
9
10
# File 'app/services/sign_in/session_refresher.rb', line 7

def initialize(refresh_token:, anti_csrf_token:)
  @refresh_token = refresh_token
  @anti_csrf_token = anti_csrf_token
end

Instance Attribute Details

#anti_csrf_tokenObject (readonly)

Returns the value of attribute anti_csrf_token.



5
6
7
# File 'app/services/sign_in/session_refresher.rb', line 5

def anti_csrf_token
  @anti_csrf_token
end

#refresh_tokenObject (readonly)

Returns the value of attribute refresh_token.



5
6
7
# File 'app/services/sign_in/session_refresher.rb', line 5

def refresh_token
  @refresh_token
end

#sessionObject (readonly)

Returns the value of attribute session.



5
6
7
# File 'app/services/sign_in/session_refresher.rb', line 5

def session
  @session
end

Instance Method Details

#access_tokenObject (private)



152
153
154
# File 'app/services/sign_in/session_refresher.rb', line 152

def access_token
  @access_token ||= create_access_token
end

#anti_csrf_checkObject (private)



36
37
38
39
40
# File 'app/services/sign_in/session_refresher.rb', line 36

def anti_csrf_check
  if anti_csrf_token != refresh_token.anti_csrf_token
    raise Errors::AntiCSRFMismatchError.new message: 'Anti CSRF token is not valid'
  end
end

#anti_csrf_enabled_client?Boolean (private)

Returns:

  • (Boolean)


116
117
118
# File 'app/services/sign_in/session_refresher.rb', line 116

def anti_csrf_enabled_client?
  client_config.anti_csrf
end

#audienceObject (private)



120
121
122
# File 'app/services/sign_in/session_refresher.rb', line 120

def audience
  @audience ||= AccessTokenAudienceGenerator.new(client_config:).perform
end

#child_refresh_tokenObject (private)



148
149
150
# File 'app/services/sign_in/session_refresher.rb', line 148

def child_refresh_token
  @child_refresh_token ||= create_child_refresh_token
end

#client_configObject (private)



124
125
126
# File 'app/services/sign_in/session_refresher.rb', line 124

def client_config
  @client_config ||= SignIn::ClientConfig.find_by!(client_id:)
end

#client_idObject (private)



128
129
130
# File 'app/services/sign_in/session_refresher.rb', line 128

def client_id
  @client_id ||= session.client_id
end

#create_access_tokenObject (private)



85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'app/services/sign_in/session_refresher.rb', line 85

def create_access_token
  AccessToken.new(
    session_handle: session.handle,
    client_id:,
    user_uuid: refresh_token.user_uuid,
    audience:,
    refresh_token_hash: get_hash(child_refresh_token.to_json),
    parent_refresh_token_hash: refresh_token_hash,
    anti_csrf_token: updated_anti_csrf_token,
    last_regeneration_time:,
    user_attributes: session.user_attributes_hash,
    device_secret_hash: session.hashed_device_secret
  )
end

#create_child_refresh_tokenObject (private)



76
77
78
79
80
81
82
83
# File 'app/services/sign_in/session_refresher.rb', line 76

def create_child_refresh_token
  RefreshToken.new(
    session_handle: session.handle,
    user_uuid: refresh_token.user_uuid,
    anti_csrf_token: updated_anti_csrf_token,
    parent_refresh_token_hash: refresh_token_hash
  )
end

#create_new_tokensObject (private)



62
63
64
65
66
67
68
# File 'app/services/sign_in/session_refresher.rb', line 62

def create_new_tokens
  SessionContainer.new(session:,
                       refresh_token: child_refresh_token,
                       access_token:,
                       client_config:,
                       anti_csrf_token: updated_anti_csrf_token)
end

#detect_token_theftObject (private)



47
48
49
50
51
52
# File 'app/services/sign_in/session_refresher.rb', line 47

def detect_token_theft
  unless refresh_token_in_session? || parent_refresh_token_in_session?
    session.destroy!
    raise Errors::TokenTheftDetectedError.new message: 'Token theft detected'
  end
end

#double_parent_refresh_token_hashObject (private)



144
145
146
# File 'app/services/sign_in/session_refresher.rb', line 144

def double_parent_refresh_token_hash
  @double_parent_refresh_token_hash ||= get_hash(refresh_token.parent_refresh_token_hash)
end

#double_refresh_token_hashObject (private)



140
141
142
# File 'app/services/sign_in/session_refresher.rb', line 140

def double_refresh_token_hash
  @double_refresh_token_hash ||= get_hash(refresh_token_hash)
end

#find_valid_oauth_sessionObject (private)



42
43
44
45
# File 'app/services/sign_in/session_refresher.rb', line 42

def find_valid_oauth_session
  @session ||= OAuthSession.find_by(handle: refresh_token.session_handle)
  raise Errors::SessionNotAuthorizedError.new message: 'No valid Session found' unless session&.active?
end

#get_hash(object) ⇒ Object (private)



132
133
134
# File 'app/services/sign_in/session_refresher.rb', line 132

def get_hash(object)
  Digest::SHA256.hexdigest(object)
end

#hashed_device_secretObject (private)



156
157
158
159
160
# File 'app/services/sign_in/session_refresher.rb', line 156

def hashed_device_secret
  return unless validated_credential.device_sso

  @hashed_device_secret ||= get_hash(device_secret)
end

#last_regeneration_timeObject (private)



100
101
102
# File 'app/services/sign_in/session_refresher.rb', line 100

def last_regeneration_time
  @last_regeneration_time ||= Time.zone.now
end

#parent_refresh_token_in_session?Boolean (private)

Returns:

  • (Boolean)


58
59
60
# File 'app/services/sign_in/session_refresher.rb', line 58

def parent_refresh_token_in_session?
  session.hashed_refresh_token == double_parent_refresh_token_hash
end

#performObject



12
13
14
15
16
17
18
19
20
# File 'app/services/sign_in/session_refresher.rb', line 12

def perform
  find_valid_oauth_session
  validate_credential_lock
  validate_terms_of_use if client_config.enforced_terms.present?
  anti_csrf_check if anti_csrf_enabled_client?
  detect_token_theft
  update_session! if parent_refresh_token_in_session?
  create_new_tokens
end

#refresh_expirationObject (private)



104
105
106
# File 'app/services/sign_in/session_refresher.rb', line 104

def refresh_expiration
  @refresh_expiration ||= Time.zone.now + validity_length
end

#refresh_token_hashObject (private)



136
137
138
# File 'app/services/sign_in/session_refresher.rb', line 136

def refresh_token_hash
  @refresh_token_hash ||= get_hash(refresh_token.to_json)
end

#refresh_token_in_session?Boolean (private)

Returns:

  • (Boolean)


54
55
56
# File 'app/services/sign_in/session_refresher.rb', line 54

def refresh_token_in_session?
  session.hashed_refresh_token == double_refresh_token_hash
end

#update_session!Object (private)



70
71
72
73
74
# File 'app/services/sign_in/session_refresher.rb', line 70

def update_session!
  session.hashed_refresh_token = double_refresh_token_hash
  session.refresh_expiration = refresh_expiration
  session.save!
end

#updated_anti_csrf_tokenObject (private)



112
113
114
# File 'app/services/sign_in/session_refresher.rb', line 112

def updated_anti_csrf_token
  @updated_anti_csrf_token ||= SecureRandom.hex
end

#validate_credential_lockObject (private)



24
25
26
27
28
# File 'app/services/sign_in/session_refresher.rb', line 24

def validate_credential_lock
  if session.user_verification.locked
    raise SignIn::Errors::CredentialLockedError.new(message: 'Credential is locked')
  end
end

#validate_terms_of_useObject (private)



30
31
32
33
34
# File 'app/services/sign_in/session_refresher.rb', line 30

def validate_terms_of_use
  if session..needs_accepted_terms_of_use?
    raise Errors::TermsOfUseNotAcceptedError.new message: 'Terms of Use has not been accepted'
  end
end

#validity_lengthObject (private)



108
109
110
# File 'app/services/sign_in/session_refresher.rb', line 108

def validity_length
  client_config.refresh_token_duration
end