authflow 1.0.2
authflow: ^1.0.2 copied to clipboard
A flexible, provider-based authentication toolkit for Flutter with stream-based auth state, customizable storage, and composable UI widgets.
Authflow #
Authflow is a modular authentication orchestration package for Flutter. It helps you manage authentication flows, state, and persistence, while letting you plug in your own authentication logic, user model, and storage. Authflow is not a plug-and-play backend solution: you bring your own AuthProvider for your backend, and Authflow manages the rest.
What Does Authflow Do? #
| Authflow Manages | You Must Implement |
|---|---|
| Provider orchestration | Your own AuthProvider |
| Session state & persistence | (Optionally) your own AuthUser |
| Reactive streams for status | (Optionally) your own AuthStorage |
| Global login/logout events | UI and error handling |
UI helpers (e.g. AuthBuilder) |
Note: Authflow does not provide production-ready providers for every backend. You are expected to implement your own provider(s) for your authentication system.
How provider selection works: When you call
AuthManager().login(), Authflow uses the provider with thedefaultProviderIdyou configured. If you did not set adefaultProviderId, it will use the first provider in your list. Make sure to set this explicitly if you have multiple providers.
π Quickstart #
- Implement your own
AuthProvider(see below for details) - (Optionally) Customize your user model by extending
AuthUser - (Optionally) Customize storage by implementing
AuthStorage - Configure
AuthManagerwith your providers and storage - Use
AuthBuilderor streams to react to auth state in your UI
π Built-in AuthProviders #
AnonymousAuthProviderβ for anonymous login (production-ready)EmailPasswordAuthProviderβ for email/password login (demo/prototyping)
You are expected to implement your own
AuthProviderfor your backend, except for anonymous flows.
Example: Custom AuthProvider #
class MyProvider extends AuthProvider {
@override
String get providerId => 'my_provider';
@override
Future<AuthResult> login(Map<String, dynamic> credentials) async {
// Your authentication logic here
return AuthResult(user: customUser, token: customToken);
}
}
Register your provider:
await AuthManager().configure(AuthConfig(
providers: [MyProvider(), AnonymousAuthProvider()],
defaultProviderId: 'my_provider',
storage: SecureAuthStorage.withDefaultUser(),
));
π€ User Model Options #
- Default:
DefaultAuthUser(minimal, can be used as-is) - Custom: Extend
AuthUserto match your API
Important: If you use a custom user model, you must configure it in
SecureAuthStorageby passing a custom deserializer. By default,SecureAuthStorage.withDefaultUser()is used, which only supportsDefaultAuthUser.
final storage = SecureAuthStorage(
userDeserializer: (data) => MyUser.deserialize(data),
);
πΎ Storage Options #
- Default:
SecureAuthStorage(usesshared_preferences) - Custom: Implement
AuthStoragefor your own persistence
π οΈ Configuration Example #
final myProvider = MyProvider();
final anonProvider = AnonymousAuthProvider();
await AuthManager().configure(AuthConfig(
providers: [myProvider, anonProvider],
defaultProviderId: 'my_provider',
storage: SecureAuthStorage.withDefaultUser(),
));
π Usage #
Login #
final result = await AuthManager().loginWithProvider('my_provider', {
'email': 'user@example.com',
'password': 'secret',
});
final user = result.user;
final token = result.token;
Manual Session #
await AuthManager().setSession(user, token, providerId: 'my_provider');
Logout #
await AuthManager().logout();
Auth State & Streams #
final isLoggedIn = AuthManager().isAuthenticated;
final user = AuthManager().currentUser;
final token = AuthManager().currentToken;
AuthManager().statusStream.listen((status) { ... });
AuthManager().userStream.listen((user) { ... });
AuthManager().tokenStream.listen((token) { ... });
Global Events #
AuthEventBus().onLogin((event) { ... });
AuthEventBus().onLogout((event) { ... });
π§© Flutter UI Integration #
Use AuthBuilder to rebuild UI based on authentication state:
AuthBuilder(
authenticated: (context, user, token) => HomeScreen(user: user),
unauthenticated: (context) => LoginScreen(),
loading: (context) => LoadingScreen(),
// Optional: Control when rebuilds happen
buildWhen: (previous, current) {
// Don't rebuild during login attempts
if (current.status == AuthStatus.loading && previous.status != AuthStatus.loading) {
return false;
}
return true;
},
);
Tip: The
buildWhenparameter helps prevent UI flashing during authentication state changes.
π‘οΈ Error Handling #
Authflow provides a standardized exception system with AuthException:
try {
final result = await AuthManager().login({ ... });
} on AuthException catch (e) {
print('Error type: \\${e.type}');
print('Error message: \\${e.message}');
}
See the docs for available exception types and customization.
β FAQ #
Q: Is Authflow a plug-and-play backend auth solution?
A: No. You must implement your own AuthProvider for your backend.
Q: Can I use my own user model?
A: Yes! Just extend AuthUser.
Q: Can I use my own storage?
A: Yes! Just implement AuthStorage.
Q: What does Authflow actually do for me?
A: It manages the flow, state, and persistence of authentication, so you can focus on your business logic.
π License #
This project is licensed under the MIT License.
π€ Author #
Firuz Vorisov
github.com/vfiruz97
Feel free to open issues or contribute via PR!