Class: Supabase::Rails::Web::RequestScopedStorage

Inherits:
Auth::SupportedStorage
  • Object
show all
Defined in:
lib/supabase/rails/web/request_scoped_storage.rb

Overview

Per-request Supabase Auth storage.

Implements the ‘Supabase::Auth::SupportedStorage` duck type (`get_item` / `set_item` / `remove_item`). The backing Hash lives in `request.env` and is allocated lazily on first access — concurrent requests in the same worker each get their own slot, so PKCE verifiers and session state never leak across threads or users.

PKCE verifiers must survive the OAuth round-trip (the verifier is written during ‘sign_in_with_oauth` on one request and consumed at `/callback` on another). When `#oauth_state` is set, writes to any key whose name ends with `code-verifier` are mirrored into a signed cookie `sb-oauth-state-<state>` with a 10-minute expiry; reads fall back to that cookie when the per-request hash misses. Keying the cookie by the OAuth `state` param binds the verifier to the specific round-trip and prevents mix-ups across concurrent OAuth attempts.

Constant Summary collapse

ENV_KEY =
"supabase.rails.auth_storage"
"sb-oauth-state-"
600
PKCE_KEY_SUFFIX =
"code-verifier"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(request, oauth_state: nil) ⇒ RequestScopedStorage

Returns a new instance of RequestScopedStorage.



34
35
36
37
38
# File 'lib/supabase/rails/web/request_scoped_storage.rb', line 34

def initialize(request, oauth_state: nil)
  super()
  @request = request
  @oauth_state = oauth_state
end

Instance Attribute Details

#oauth_stateObject

Returns the value of attribute oauth_state.



31
32
33
# File 'lib/supabase/rails/web/request_scoped_storage.rb', line 31

def oauth_state
  @oauth_state
end

#requestObject (readonly)

Returns the value of attribute request.



32
33
34
# File 'lib/supabase/rails/web/request_scoped_storage.rb', line 32

def request
  @request
end

Instance Method Details

#backing_hashObject

The backing per-request hash, lazily allocated in ‘request.env`. Subsequent `RequestScopedStorage.new(request)` calls for the same request observe the same hash (memoized by env key).



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

def backing_hash
  env[ENV_KEY] ||= {}
end

#get_item(key) ⇒ Object



40
41
42
43
44
45
# File 'lib/supabase/rails/web/request_scoped_storage.rb', line 40

def get_item(key)
  value = backing_hash[key]
  return value unless value.nil?

  read_pkce_cookie(key)
end

#remove_item(key) ⇒ Object



53
54
55
56
57
58
# File 'lib/supabase/rails/web/request_scoped_storage.rb', line 53

def remove_item(key)
  existed = backing_hash.key?(key)
  value = backing_hash.delete(key)
  clear_pkce_cookie if pkce_key?(key) && oauth_state_present?
  existed ? value : nil
end

#set_item(key, value) ⇒ Object



47
48
49
50
51
# File 'lib/supabase/rails/web/request_scoped_storage.rb', line 47

def set_item(key, value)
  backing_hash[key] = value
  write_pkce_cookie(value) if pkce_key?(key) && oauth_state_present?
  value
end