Module: CoalescingPanda::SessionReplacement

Extended by:
ActiveSupport::Concern
Included in:
ControllerHelpers
Defined in:
lib/coalescing_panda/session_replacement.rb

Instance Method Summary collapse

Instance Method Details

#current_session(create_missing: true) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/coalescing_panda/session_replacement.rb', line 29

def current_session(create_missing: true)
  return @current_session if @current_session.present?

  if params[:session_token]
    payload = JSON.parse(session_cryptor.decrypt_and_verify(params[:session_token])).with_indifferent_access
    matched_session = find_or_create_session(key: payload[:session_key])
    if matched_session.present?
      if payload[:token_type] == 'nonce' && matched_session.data[:link_nonce] == payload[:nonce]
        @current_session = matched_session
        @current_session.data[:link_nonce] = nil
      elsif payload[:token_type] == 'fixed_ip' && matched_session.data[:remote_ip] == request.remote_ip &&
        DateTime.parse(matched_session.data[:last_ip_token_requested]) > session_expiration_period_minutes.minutes.ago
        @current_session = matched_session
      elsif payload[:token_type] == 'expiring' && DateTime.parse(matched_session.data[:last_token_requested]) > session_expiration_period_minutes.minutes.ago
        @current_session = matched_session
      end
    end
    raise SessionNonceMismatch, "Session Not Found" unless @current_session.present?
  elsif (session_key = params[:session_key] || session_key_header || flash[:session_key] || session[:session_key]).present?
    @current_session = find_or_create_session(key: session_key)
  end

  @current_session ||= find_or_create_session(key: :create) if create_missing

  @current_session
end

#current_session_dataObject



56
57
58
# File 'lib/coalescing_panda/session_replacement.rb', line 56

def current_session_data
  current_session.data
end

#forbid_access_if_lacking_sessionObject



64
65
66
# File 'lib/coalescing_panda/session_replacement.rb', line 64

def forbid_access_if_lacking_session
  render plain: 'You should do an LTI Tool Launch.', status: :unauthorized unless valid_session?
end


97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/coalescing_panda/session_replacement.rb', line 97

def link_nonce(type: link_nonce_type)
  type = instance_exec(&type) if type.is_a?(Proc)
  type = type.to_s

  @cached_link_nonces ||= {}
  @cached_link_nonces[type] ||= begin
    payload = {
      token_type: type,
      session_key: current_session.session_key,
      organization_id: current_organization.id,
    }

    if type == 'nonce'
      current_session_data[:link_nonce] = SecureRandom.hex
      payload.merge!(nonce: current_session_data[:link_nonce])
    elsif type == 'fixed_ip'
      current_session_data[:remote_ip] ||= request.remote_ip
      current_session_data[:last_ip_token_requested] = DateTime.now.iso8601
    elsif type == 'expiring'
      current_session_data[:last_token_requested] = DateTime.now.iso8601
    else
      raise StandardError, "Unsupported link_nonce_type: '#{type}'"
    end

    session_cryptor.encrypt_and_sign(payload.to_json)
  end
end


125
126
127
# File 'lib/coalescing_panda/session_replacement.rb', line 125

def link_nonce_type
  self.class.link_nonce_type
end


85
86
87
# File 'lib/coalescing_panda/session_replacement.rb', line 85

def link_with_session_to(*args)
  helpers.link_to url_with_session(*args)
end

#redirect_with_session_to(*args) ⇒ Object

Redirect with the session key intact. In production, handle this by adding a one-time use encrypted token to the URL. Keeping it in the URL in development means that it plays nicely with webpack-dev-server live reloading (otherwise you get an access error everytime it tries to live reload).



81
82
83
# File 'lib/coalescing_panda/session_replacement.rb', line 81

def redirect_with_session_to(*args)
  redirect_to url_with_session(*args)
end

#save_sessionObject



25
26
27
# File 'lib/coalescing_panda/session_replacement.rb', line 25

def save_session
  current_session.try(:save)
end

#session_changed?Boolean

Returns:

  • (Boolean)


60
61
62
# File 'lib/coalescing_panda/session_replacement.rb', line 60

def session_changed?
  current_session.changed? && current_session.changes[:data].present?
end

#session_expiration_period_minutesObject



129
130
131
# File 'lib/coalescing_panda/session_replacement.rb', line 129

def session_expiration_period_minutes
  15
end

#session_url_for(*args) ⇒ Object



89
90
91
# File 'lib/coalescing_panda/session_replacement.rb', line 89

def session_url_for(*args)
  url_for(build_session_url_params(*args))
end

#url_with_session(location, *args, route_context: self, **kwargs) ⇒ Object



93
94
95
# File 'lib/coalescing_panda/session_replacement.rb', line 93

def url_with_session(location, *args, route_context: self, **kwargs)
  route_context.send(location, *build_session_url_params(*args, **kwargs))
end

#verify_authenticity_tokenObject



68
69
70
71
72
73
# File 'lib/coalescing_panda/session_replacement.rb', line 68

def verify_authenticity_token
  # No need to check CSRF when no cookies were sent. This fixes CSRF failures in Browsers
  # that restrict Cookie setting within an IFrame.
  return unless request.cookies.keys.length > 0
  super
end