Class: Supabase::Rails::SessionStore

Inherits:
Object
  • Object
show all
Defined in:
lib/supabase/rails/session_store.rb

Overview

Single source of truth for the encrypted session cookie used in ‘:web` mode. Wraps Rails’ ‘ActionDispatch::Cookies::EncryptedCookieJar` (keyed by the host app’s ‘secret_key_base`, so no new secret is introduced) so the middleware (read + refresh-rewrite) and the `Authentication` concern (`start_new_session_for` / `terminate_session`) read and write the same cookie consistently.

Decrypted payload contains only the credential fields needed to verify / refresh the session — access_token, refresh_token, expires_at, expires_in, token_type. The upstream ‘Supabase::Auth::Types::Session` struct also exposes a `user` field (and `provider_token` / `provider_refresh_token`), but those are intentionally NOT persisted: the user object is reconstructed from the access_token’s JWT claims at request time, and a full Session would overflow Rails’ 4 KB cookie limit on real Supabase responses (which embed identities, metadata, etc.).

Constant Summary collapse

"sb-session"
DEFAULT_SAME_SITE =
:lax
DEFAULT_PATH =
"/"
PERSISTED_KEYS =
%w[access_token refresh_token expires_at expires_in token_type].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config = nil) ⇒ SessionStore

Returns a new instance of SessionStore.



31
32
33
34
35
36
37
38
39
# File 'lib/supabase/rails/session_store.rb', line 31

def initialize(config = nil)
  cfg = normalize_config(config)

  @cookie_name = cfg[:cookie_name] || DEFAULT_COOKIE_NAME
  @same_site   = cfg[:same_site]   || DEFAULT_SAME_SITE
  @path        = cfg[:path]        || DEFAULT_PATH
  @domain      = cfg[:domain]
  @secure      = cfg.key?(:secure) && !cfg[:secure].nil? ? cfg[:secure] : default_secure
end

Instance Attribute Details

Returns the value of attribute cookie_name.



29
30
31
# File 'lib/supabase/rails/session_store.rb', line 29

def cookie_name
  @cookie_name
end

#domainObject (readonly)

Returns the value of attribute domain.



29
30
31
# File 'lib/supabase/rails/session_store.rb', line 29

def domain
  @domain
end

#pathObject (readonly)

Returns the value of attribute path.



29
30
31
# File 'lib/supabase/rails/session_store.rb', line 29

def path
  @path
end

#same_siteObject (readonly)

Returns the value of attribute same_site.



29
30
31
# File 'lib/supabase/rails/session_store.rb', line 29

def same_site
  @same_site
end

#secureObject (readonly)

Returns the value of attribute secure.



29
30
31
# File 'lib/supabase/rails/session_store.rb', line 29

def secure
  @secure
end

Instance Method Details

#clear(response) ⇒ Object

Past-dates the cookie so the browser drops it. Deletion happens on the base jar — the encrypted layer wraps read/write encoding only.



63
64
65
# File 'lib/supabase/rails/session_store.rb', line 63

def clear(response)
  base_jar(response).delete(cookie_name, delete_options)
end

#read(request) ⇒ Object

Decrypts the session cookie. Returns a Hash mirroring ‘Supabase::Auth::Types::Session`, or `nil` if the cookie is missing, tampered, or otherwise unreadable. A tampered ciphertext is treated as a missing cookie (no exception bubbles up).



45
46
47
48
49
50
51
52
53
# File 'lib/supabase/rails/session_store.rb', line 45

def read(request)
  raw = encrypted_jar(request)[cookie_name]
  return nil if raw.nil?
  return nil unless raw.is_a?(Hash)

  raw
rescue StandardError
  nil
end

#write(response, session) ⇒ Object

Encrypts and persists a Supabase session as a cookie. Accepts either a ‘Supabase::Auth::Types::Session` (or any struct with `#to_h`) or a Hash.



57
58
59
# File 'lib/supabase/rails/session_store.rb', line 57

def write(response, session)
  encrypted_jar(response)[cookie_name] = cookie_options.merge(value: serialize_session(session))
end