Flutter
One package for Android, iOS, web, macOS, Windows and Linux. Sessions are kept in secure storage (Keychain / Keystore) and survive restarts; the app still opens signed in when offline.
Install
tausi_flutter on pub.devRequires Flutter 3.19+, Dart 3.3+flutter pub add tausi_flutterpk_… here; keep sk_… on your server.Set up
import 'package:tausi_flutter/tausi_flutter.dart';
final tausi = TausiClient(
baseUrl: const String.fromEnvironment('TAUSI_URL', defaultValue: 'https://tausi-auth.onrender.com'),
publishableKey: const String.fromEnvironment('TAUSI_KEY'),
);flutter run --dart-define=TAUSI_URL=https://tausi-auth.onrender.com --dart-define=TAUSI_KEY=pk_…| Option | Default | What it does |
|---|---|---|
tokenStore | SecureTokenStore | Where the session token is kept. Implement TokenStore to use your own. |
sendDeviceId | true | Sends a random per-install ID so projects can limit accounts per device. Not a fingerprint. |
timeout | 15 s | Per-request timeout. |
oauthLauncher | flutter_web_auth_2 | How the social sign-in browser is opened. |
Running on an Android emulator against a local Tausi? localhost there is the emulator itself; use http://10.0.2.2:3000.
Switch screens
void main() => runApp(MaterialApp(
home: TausiAuthGate(
client: tausi,
loading: (_) => const SplashScreen(),
signedIn: (_, user) => HomePage(user: user),
signedOut: (_) => const SignInPage(),
),
));TausiAuthGate restores the saved session, checks it with Tausi, and rebuilds whenever the user signs in or out (including when Tausi revokes the session or bans the user).
Email and password
// Sign up (optional attributes are saved with the account)
final verificationRequired = await tausi.signUp(
email: email,
password: password,
name: name,
username: username, // optional
phoneNumber: '+255712345678', // optional
);
// Sign in
await tausi.signIn(email: email, password: password);
await tausi.sendVerificationEmail(email);
await tausi.forgotPassword(email);
await tausi.changePassword(currentPassword: current, newPassword: next); // signs out other devices
await tausi.signOut();Errors
try {
await tausi.signIn(email: email, password: password);
} on TausiException catch (e) {
final message = switch (e.code) {
'INVALID_CREDENTIALS' => 'Wrong email or password.',
'EMAIL_NOT_VERIFIED' => 'Check your inbox to verify your email.',
'ACCOUNT_BANNED' || 'ACCOUNT_SUSPENDED' => e.message,
'RATE_LIMITED' => 'Too many attempts. Try again in ${e.retryAfter?.inSeconds ?? 60}s.',
'NETWORK_ERROR' || 'TIMEOUT' => 'You seem to be offline.',
_ => e.message,
};
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(message)));
}TausiException has status, code, message, details and retryAfter. Sign-up adds EMAIL_ALREADY_REGISTERED and USERNAME_TAKEN.
Call your backend
final token = await tausi.getToken();
final res = await http.get(
Uri.parse('https://api.example.com/orders'),
headers: {'authorization': 'Bearer $token'},
);Verify it on the server with the Node, PHP or Python SDK. Renewed tokens are stored automatically.
Profile and devices
final user = tausi.currentUser; // cached, available offline
final fresh = await tausi.getUser();
await tausi.updateUser(firstName: 'Asha', timezone: 'Africa/Dar_es_Salaam');
await tausi.updateUser(clear: {'phoneNumber'}); // remove an attribute
final sessions = await tausi.listSessions(); // OwnSession.current marks this device
await tausi.revokeSession(sessions.first.id);
await tausi.revokeOtherSessions();
await tausi.deleteAccount(password);Email links
Send verification and reset emails straight into your app with redirectTo. Use an https App Link / Universal Link on an allowed origin, or a custom scheme listed in the project's Redirect URLs:
await tausi.signUp(email: email, password: pw, name: name, redirectTo: Uri.parse('https://app.example.com/verify'));
await tausi.forgotPassword(email, redirectTo: Uri.parse('myapp://auth/reset'));
// When the link opens the app (app_links, go_router, uni_links, ...):
void onLink(Uri uri) async {
final token = uri.queryParameters['token'];
if (token == null) return;
switch (uri.queryParameters['type']) {
case 'email_verification':
await tausi.verifyEmail(token);
case 'password_reset':
// show a "new password" screen, then:
await tausi.resetPassword(token: token, newPassword: newPassword);
}
}Some email apps won't open custom schemes; https App Links / Universal Links are the most reliable. Without redirectTo, links go to your App URL's /verify-email and /reset-password pages.
State management
The client is a ChangeNotifier, so it plugs into anything:
// Plain Flutter
ListenableBuilder(listenable: tausi, builder: (_, __) => tausi.isSignedIn ? const Home() : const SignIn());
// Provider
ChangeNotifierProvider.value(value: tausi, child: const App());
// Riverpod
final tausiProvider = ChangeNotifierProvider((_) => tausi);
Social sign-in
The provider opens in a secure browser session and the one-time code is exchanged with PKCE.
redirectTomust be an https URL on an allowed origin that opens your app:CallbackActivityintent filter fromflutter_web_auth_2.Cancelling throws
TausiExceptionwith codeaccess_denied; a banned user getsaccount_banned. For other setups, calloauthUrl()andhandleOAuthRedirect()yourself.