Skip to Content

Security Features

Fasq supports various security features through QueryClient configuration, enabling secure data handling in your Riverpod-based applications.

[!TIP] For enterprise-grade encryption and encrypted persistence, we recommend using the fasq_security package.

Secure Queries

Secure queries are specifically handled to prevent accidental data leakage, such as skipping persistence or ensuring rapid cleanup when the app goes into the background.

import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:fasq_riverpod/fasq_riverpod.dart'; final secureTokenProvider = queryProvider<String>( 'auth-token'.toQueryKey(), () => api.getAuthToken(), options: QueryOptions( isSecure: true, // Mark as secure maxAge: Duration(minutes: 15), // Required TTL staleTime: Duration(minutes: 5), ), ); class SecureWidget extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { // Standard AsyncValue usage final tokenAsync = ref.watch(secureTokenProvider); return tokenAsync.when( loading: () => CircularProgressIndicator(), error: (e, s) => Text('Error'), data: (token) => Text('Token: $token'), ); } }

Security Benefits

  • No Persistence: Secure entries are marked to never be saved by a persistence layer.
  • In-Memory Only: Data stays in memory and is wiped when the query is disposed or the app lifecycle necessitates it.
  • Strict TTL: Secure queries often enforce shorter maxAge to ensure sensitive data doesn’t linger.

Secure Mutations

Mutations involving sensitive data should be triggered through the notifier to maintain proper state tracking and security contexts.

final passwordChangeProvider = mutationProvider<void, String>( (newPassword) => api.changePassword(newPassword), ); // In your widget: ElevatedButton( onPressed: () => ref.read(passwordChangeProvider.notifier).mutate('new_pwd_123'), child: Text('Change Password'), )

Configuring the Secure Client

Fasq uses Riverpod’s dependency injection to share a single QueryClient instance across your app. You can customize this client with security-focused options.

// You can override the default fasqClientProvider in your ProviderScope final mySecureClient = QueryClient( config: const CacheConfig( defaultStaleTime: Duration(minutes: 5), ), // Configure encryption or other security plugins here if available ); // In your main.dart: ProviderScope( overrides: [ fasqClientProvider.overrideWithValue(mySecureClient), ], child: MyApp(), )

Accessing the Client in Providers

If you need to access the client instance within a provider (e.g., for manual cache manipulation), use ref.watch(fasqClientProvider).

final someProvider = Provider((ref) { final client = ref.watch(fasqClientProvider); // Perform secure operations on the client });

Security Best Practices

  1. Short TTL for Sensitive Data: Always use low staleTime and maxAge for providers handling tokens or PII (Personally Identifiable Information).
  2. Auto-Dispose: Leverage AutoDispose (default in queryProvider) to ensure data is wiped from memory as soon as it’s no longer being used by any widget.
  3. Encrypted Persistence: If you must persist sensitive non-secure data, ensure your persistenceOptions use an encrypted storage backend (like flutter_secure_storage).

Next Steps

Last updated on