#[non_exhaustive]pub enum PkceStateStore {
InMemory(InMemoryPkceStateStore),
}Expand description
PKCE state store that dispatches to an in-memory or Redis backend.
§Backends
-
InMemory (default): per-process DashMap. Safe for single-replica deployments. State is lost on restart.
-
Redis (requires
redis-pkceCargo feature): distributed, shared across all replicas. Required for multi-instance Kubernetes / ECS / fly.io deployments where/auth/startand/auth/callbackmay hit different nodes.
§Multi-replica requirement
Set FRAISEQL_REQUIRE_REDIS=1 in your deployment environment to make
FraiseQL refuse to start without a Redis-backed PKCE store. This is the
recommended pattern for production Kubernetes deployments.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
InMemory(InMemoryPkceStateStore)
Single-node DashMap-backed store.
Implementations§
Source§impl PkceStateStore
impl PkceStateStore
Sourcepub fn new(
state_ttl_secs: u64,
encryptor: Option<Arc<StateEncryptionService>>,
) -> Self
pub fn new( state_ttl_secs: u64, encryptor: Option<Arc<StateEncryptionService>>, ) -> Self
Create an in-memory PKCE state store (single-replica deployments).
Sourcepub const fn is_in_memory(&self) -> bool
pub const fn is_in_memory(&self) -> bool
Returns true when backed by the in-memory DashMap store.
Used by the FRAISEQL_REQUIRE_REDIS startup check.
Sourcepub async fn create_state(
&self,
redirect_uri: &str,
) -> Result<(String, String), Error>
pub async fn create_state( &self, redirect_uri: &str, ) -> Result<(String, String), Error>
Generate an authorization-code verifier and reserve a state slot.
Returns (outbound_token, code_verifier):
outbound_tokengoes in the OIDC?state=query parameter.code_verifieris passed toSelf::s256_challengeand stored until the callback arrives.
§Errors
Returns an error if encryption fails (effectively never with a valid key) or the Redis backend is unreachable.
Sourcepub async fn consume_state(
&self,
outbound_token: &str,
) -> Result<ConsumedPkceState, PkceError>
pub async fn consume_state( &self, outbound_token: &str, ) -> Result<ConsumedPkceState, PkceError>
Consume a state token, atomically removing it from the store.
Returns PkceError::StateNotFound for:
- tokens that were never issued,
- tokens that have already been consumed (one-time use), and
- tokens that fail decryption (tampered or from a different key).
Returns PkceError::StateExpired when the in-memory token is valid
but its TTL has elapsed. The Redis backend returns StateNotFound for
expired tokens (Redis TTL handles expiry).
§Errors
Returns PkceError::StateNotFound if the token is unknown, already consumed,
or fails decryption. Returns PkceError::StateExpired if the token’s TTL has elapsed.
Sourcepub fn s256_challenge(verifier: &str) -> String
pub fn s256_challenge(verifier: &str) -> String
Compute the S256 code challenge for a given verifier.
Per RFC 7636 §4.2:
code_challenge = BASE64URL(SHA256(ASCII(code_verifier)))
(no padding).
Sourcepub async fn cleanup_expired(&self)
pub async fn cleanup_expired(&self)
Remove expired entries.
No-op for the Redis backend — Redis TTL handles expiry automatically. Call from a background task on a fixed interval for the in-memory backend.
Auto Trait Implementations§
impl Freeze for PkceStateStore
impl !RefUnwindSafe for PkceStateStore
impl Send for PkceStateStore
impl Sync for PkceStateStore
impl Unpin for PkceStateStore
impl UnsafeUnpin for PkceStateStore
impl UnwindSafe for PkceStateStore
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more