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 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'),
);
}
}
  • 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.

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'),
)

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(),
)

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
});
  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).