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
Section titled “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
Section titled “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
maxAgeto ensure sensitive data doesn’t linger.
Secure Mutations
Section titled “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
Section titled “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 ProviderScopefinal 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
Section titled “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
Section titled “Security Best Practices”- Short TTL for Sensitive Data: Always use low
staleTimeandmaxAgefor providers handling tokens or PII (Personally Identifiable Information). - Auto-Dispose: Leverage
AutoDispose(default inqueryProvider) to ensure data is wiped from memory as soon as it’s no longer being used by any widget. - Encrypted Persistence: If you must persist sensitive non-secure data, ensure your
persistenceOptionsuse an encrypted storage backend (likeflutter_secure_storage).
Next Steps
Section titled “Next Steps”fasqClientProvider- How the client is shared- Persistence - Secure storage options