voo_authstack_client 0.1.2
voo_authstack_client: ^0.1.2 copied to clipboard
Flutter SDK for Voo AuthStack - a centralized authentication platform. Supports email/password, OAuth providers (Google, GitHub, Microsoft, Apple, Discord), automatic token refresh, and provider linking.
Vee AuthStack Client #
A comprehensive Flutter SDK for Vee AuthStack - a centralized authentication platform. Supports email/password authentication, OAuth providers, automatic token refresh, and provider linking.
Features #
- Email/Password Authentication - Register and login with email and password
- OAuth Providers - Login with Google, GitHub, Microsoft, Apple, Discord
- Token Management - Automatic token storage and refresh
- Provider Linking - Link/unlink multiple OAuth providers to a single account
- Dio Interceptor - Automatic token refresh with request queuing
- Type Safe - Fully typed with strong type constraints
- Clean Architecture - Following best practices with VooCore integration
Installation #
Add to your pubspec.yaml:
dependencies:
vee_authstack_client: ^0.1.0
Or for local development in the VooFlutter monorepo:
dependencies:
vee_authstack_client:
path: packages/dev/vee_authstack_client
Quick Start #
1. Initialize the Service #
import 'package:vee_authstack_client/vee_authstack_client.dart';
final authService = VeeAuthstackService(
config: VeeAuthstackConfig(
baseUrl: 'https://auth.voostack.com/api',
),
);
// Initialize (checks for stored tokens)
await authService.initialize();
2. Register a New User #
try {
final result = await authService.register(
email: 'user@example.com',
password: 'securePassword123',
firstName: 'John',
lastName: 'Doe',
);
print('Welcome, ${result.user.fullName}!');
} on VeeAuthstackException catch (e) {
print('Registration failed: ${e.message}');
}
3. Login with Email/Password #
try {
final result = await authService.loginWithEmail(
email: 'user@example.com',
password: 'securePassword123',
);
print('Logged in as ${result.user.email}');
} on VeeAuthstackException catch (e) {
if (e.code == 'invalid-credentials') {
print('Invalid email or password');
}
}
4. Login with OAuth Provider #
// With access token from OAuth provider
final result = await authService.loginWithOAuthToken(
provider: OAuthProvider.google,
token: googleAccessToken,
);
// With authorization code
final result = await authService.loginWithOAuthCode(
provider: OAuthProvider.github,
code: authorizationCode,
redirectUri: 'https://yourapp.com/callback',
);
5. Listen to Auth State Changes #
authService.statusStream.listen((status) {
switch (status) {
case AuthStatus.authenticated:
print('User is logged in');
break;
case AuthStatus.unauthenticated:
print('User is logged out');
break;
case AuthStatus.authenticating:
print('Login in progress...');
break;
case AuthStatus.refreshing:
print('Refreshing token...');
break;
case AuthStatus.error:
print('Authentication error');
break;
}
});
authService.userStream.listen((user) {
if (user != null) {
print('Current user: ${user.fullName}');
}
});
OAuth Providers #
Supported OAuth providers:
| Provider | Enum Value |
|---|---|
OAuthProvider.google |
|
| GitHub | OAuthProvider.github |
| Microsoft | OAuthProvider.microsoft |
| Apple | OAuthProvider.apple |
| Discord | OAuthProvider.discord |
Provider Linking #
Link multiple OAuth providers to a single account:
// Get linked providers
final providers = await authService.getLinkedProviders();
for (final provider in providers) {
print('${provider.providerType}: ${provider.email}');
}
// Link a new provider
final linked = await authService.linkProviderWithToken(
provider: OAuthProvider.github,
token: githubAccessToken,
);
print('Linked ${linked.providerType}');
// Unlink a provider
await authService.unlinkProvider(OAuthProvider.github);
Token Management #
Custom Token Storage #
Implement TokenStorage for persistent storage:
class SecureTokenStorage implements TokenStorage {
final FlutterSecureStorage _storage = FlutterSecureStorage();
@override
Future<void> saveTokens(AuthTokens tokens) async {
await _storage.write(key: 'auth_tokens', value: jsonEncode(tokens.toJson()));
}
@override
Future<AuthTokens?> getTokens() async {
final data = await _storage.read(key: 'auth_tokens');
if (data == null) return null;
return AuthTokens.fromJson(jsonDecode(data));
}
@override
Future<void> deleteTokens() async {
await _storage.delete(key: 'auth_tokens');
}
@override
Future<bool> hasTokens() async {
return await _storage.containsKey(key: 'auth_tokens');
}
}
// Use custom storage
final authService = VeeAuthstackService(
config: VeeAuthstackConfig(baseUrl: 'https://auth.voostack.com/api'),
tokenStorage: SecureTokenStorage(),
);
Auto-Refresh Interceptor #
Add the interceptor to your Dio instance for automatic token refresh:
final dio = Dio();
dio.interceptors.add(AuthInterceptor(
authService: authService,
refreshBuffer: Duration(minutes: 5), // Refresh 5 min before expiry
));
// All requests will now automatically include auth headers
// and refresh tokens when needed
final response = await dio.get('/api/protected-resource');
Configuration #
VeeAuthstackConfig(
// Required
baseUrl: 'https://auth.voostack.com/api',
// Optional
connectTimeout: Duration(seconds: 30),
receiveTimeout: Duration(seconds: 30),
autoRefreshBuffer: Duration(minutes: 5),
)
Error Handling #
All auth errors throw VeeAuthstackException:
try {
await authService.loginWithEmail(email: email, password: password);
} on VeeAuthstackException catch (e) {
switch (e.code) {
case 'invalid-credentials':
// Wrong email or password
break;
case 'unauthenticated':
// User not logged in
break;
case 'token-expired':
// Token has expired
break;
case 'refresh-failed':
// Failed to refresh token
break;
case 'network-error':
// Network connectivity issue
break;
case 'email-in-use':
// Email already registered
break;
case 'provider-already-linked':
// OAuth provider already linked
break;
case 'provider-not-linked':
// OAuth provider not linked
break;
default:
print('Error: ${e.message}');
}
}
API Reference #
VeeAuthstackService #
| Method | Description |
|---|---|
initialize() |
Check for stored tokens and restore session |
register() |
Register new user with email/password |
loginWithEmail() |
Login with email and password |
loginWithOAuthToken() |
Login with OAuth provider token |
loginWithOAuthCode() |
Login with OAuth authorization code |
refreshToken() |
Manually refresh the access token |
logout() |
Logout and clear tokens |
getCurrentUser() |
Fetch current user info |
getLinkedProviders() |
Get all linked OAuth providers |
linkProviderWithToken() |
Link OAuth provider with token |
linkProviderWithCode() |
Link OAuth provider with code |
unlinkProvider() |
Unlink an OAuth provider |
dispose() |
Clean up resources |
Properties #
| Property | Type | Description |
|---|---|---|
status |
AuthStatus |
Current auth status |
currentUser |
UserInfo? |
Current user info |
currentTokens |
AuthTokens? |
Current tokens |
isAuthenticated |
bool |
Whether user is authenticated |
statusStream |
Stream<AuthStatus> |
Auth status changes |
userStream |
Stream<UserInfo?> |
User changes |
authenticatedDio |
Dio |
Dio instance with auth headers |
Example #
See the example folder for a complete sample application demonstrating:
- Email/password registration and login
- OAuth provider authentication
- Auth state management
- Provider linking/unlinking
- Token refresh
Run the example:
cd example
flutter run -d chrome
Architecture #
lib/
├── vee_authstack_client.dart # Main export
└── src/
├── enums/
│ ├── auth_status.dart # Authentication states
│ └── oauth_provider.dart # OAuth provider enum
├── exceptions/
│ └── vee_authstack_exception.dart
├── interceptors/
│ └── auth_interceptor.dart # Auto-refresh interceptor
├── models/
│ ├── auth_result.dart # Login/register result
│ ├── auth_tokens.dart # JWT tokens
│ ├── linked_provider.dart # Linked OAuth provider
│ └── user_info.dart # User information
└── services/
├── auth_service.dart # Main auth service
└── token_storage.dart # Token storage interface
Learn More #
License #
MIT License - see LICENSE for details.
Built by VooStack #
Need help with Flutter development or authentication solutions?
VooStack builds enterprise Flutter applications and developer tools. We're here to help with your next project.