Super Better Auth ๐Ÿš€

A comprehensive Dart/Flutter client for Better Auth that provides seamless authentication, organization management, and advanced session handling features for your Flutter applications.

๐ŸŒŸ Why Super Better Auth?

  • Complete Better Auth Integration - Full support for all Better Auth features
  • Organization Management - Built-in team and organization handling
  • Advanced Cookie Management - Direct access to authentication cookies
  • Type-Safe API - Generated models with JSON serialization
  • Flutter-First - Designed specifically for Flutter applications
  • Production Ready - Comprehensive error handling and validation

Getting Started

Add super_better_auth to your project dependencies:

flutter pub add super_better_auth

Or manually add it to your pubspec.yaml:

dependencies:
   super_better_auth: <latest_version>

โœจ Features

๐Ÿ” Authentication

  • โœ… Email Authentication - Sign in/up with email and password
  • โœ… Social Authentication - GitHub, Google, Discord, and more
  • โœ… Phone Authentication - SMS-based authentication
  • โœ… Username Authentication - Traditional username/password
  • โœ… Anonymous Authentication - Guest user support
  • โœ… Email OTP - One-time password via email
  • ๐ŸŸ  Two-Factor Authentication - Enhanced security (coming soon)

๐Ÿข Organization Management

  • โœ… Organization CRUD - Create, read, update, delete organizations
  • โœ… Member Management - Add, remove, and manage organization members
  • โœ… Team Management - Create and manage teams within organizations
  • โœ… Invitation System - Invite users to join organizations
  • โœ… Role-Based Access - Flexible permission system
  • โœ… Membership Queries - List and filter organization memberships

๐Ÿช Advanced Session Management

  • โœ… Session Management - Get, validate, and refresh user sessions
  • โœ… Cookie Access - Direct access to authentication cookies
  • โœ… Token Management - JWT token handling and validation
  • โœ… Admin Operations - Administrative user management

๐Ÿ”ง Developer Experience

  • โœ… Type-Safe API - Generated models with JSON serialization
  • โœ… Error Handling - Comprehensive error types and messages
  • โœ… Flutter Integration - Provider pattern with BetterAuthConsumer
  • โœ… Hot Reload Support - Development-friendly architecture

Usage

Import the package in your main.dart:

import 'package:flutter/material.dart';
import 'package:super_better_auth/super_better_auth.dart';

void main() async {
   WidgetsFlutterBinding.ensureInitialized();
   await SuperBetterAuth.initialize(url: 'api_url');
   runApp(const MyApp());
}

Wrap your MaterialApp with BetterAuthProvider:

class MyApp extends StatelessWidget {
   const MyApp({super.key});

   @override
   Widget build(BuildContext context) {
      return BetterAuthProvider(
         child: MaterialApp(
            title: 'BetterAuth',
            theme: ThemeData(
               colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
            ),
            home: const MyHomePage(title: 'Better Auth'),
         ),
      );
   }
}

Access BetterAuth client using BetterAuthConsumer:

BetterAuthConsumer(
  builder: (context, client) {
    return Widget();
  }
)

Or directly via:

final client = SuperBetterAuth.client;

๐Ÿ”Œ Plugin System

Super Better Auth supports all Better Auth plugins through a modular architecture:

Available Plugins

import 'package:super_better_auth/plugins/admin/admin_plugin.dart';
import 'package:super_better_auth/plugins/phone/phone_plugin.dart';
import 'package:super_better_auth/plugins/email_otp/email_otp_plugin.dart';
import 'package:super_better_auth/plugins/jwt/jwt_plugin.dart';
import 'package:super_better_auth/plugins/organization/organization_plugin.dart';

Plugin Usage

final client = SuperBetterAuth.client;

// Core authentication
await client.signIn.email(email: "user@example.com", password: "password");
await client.signUp.social(provider: "github");

// Plugin-specific features
await client.phone.sendOtp(phoneNumber: "+1234567890");
await client.admin.createUser(email: "admin@example.com");
await client.emailOtp.sendOtp(email: "user@example.com");
await client.jwt.getTokens();

// Organization management
await client.organization.createOrganization(name: "My Company");
await client.organization.inviteMember(
  organizationId: "org_123",
  email: "member@example.com",
  role: "member"
);

// Cookie management
final sessionCookie = await client.getCookie('better-auth.session_token');
final allCookies = await client.getCookies();

๐Ÿ“– Advanced Usage Examples

Organization Management

final client = SuperBetterAuth.client;

// Create an organization
final createResult = await client.organization.createOrganization(
  name: "Acme Corp",
  slug: "acme-corp",
  logo: "https://example.com/logo.png"
);

if (createResult.isSuccess) {
  final organization = createResult.data!;
  print("Created organization: ${organization.name}");
  
  // Invite a member
  await client.organization.inviteMember(
    organizationId: organization.id,
    email: "john@example.com",
    role: "member"
  );
  
  // Create a team
  await client.organization.createTeam(
    organizationId: organization.id,
    name: "Development Team",
    description: "Core development team"
  );
  
  // List all members
  final membersResult = await client.organization.listMembers(organization.id);
  if (membersResult.isSuccess) {
    for (final member in membersResult.data!) {
      print("Member: ${member.user.name} (${member.role})");
    }
  }
}
// Get specific authentication cookies
final sessionToken = await client.getCookie('better-auth.session_token');
final csrfToken = await client.getCookie('better-auth.csrf_token');

// Get all Better Auth cookies
final authCookies = await client.getAuthCookies();
print("Found ${authCookies.length} auth cookies");

// Check if session exists
final hasSession = await client.hasCookie('better-auth.session_token');
if (hasSession) {
  print("User is authenticated");
}

// Clear all cookies (sign out completely)
await client.clearCookies();

Using Cookies for Authenticated API Calls

The SuperBetterAuth client automatically handles cookies for all API calls. However, you can also manually use the retrieved cookies for custom API requests:

import 'package:dio/dio.dart';

// Get the session token cookie
final sessionCookie = await client.getCookie('better-auth.session_token');

if (sessionCookie != null) {
  // Create a Dio instance for custom API calls
  final dio = Dio();
  
  // Add the session cookie to your custom requests
  dio.options.headers['Cookie'] = '${sessionCookie.name}=${sessionCookie.value}';
  
  // Make authenticated API calls to your backend
  final response = await dio.get('https://your-api.com/protected-endpoint');
  
  // Or use it with other HTTP clients
  final httpClient = HttpClient();
  final request = await httpClient.getUrl(Uri.parse('https://your-api.com/protected-endpoint'));
  request.headers.set('Cookie', '${sessionCookie.name}=${sessionCookie.value}');
  final response = await request.close();
}

// For CSRF protection, include both session and CSRF tokens
final sessionToken = await client.getCookie('better-auth.session_token');
final csrfToken = await client.getCookie('better-auth.csrf_token');

if (sessionToken != null && csrfToken != null) {
  final dio = Dio();
  dio.options.headers['Cookie'] = '${sessionToken.name}=${sessionToken.value}; ${csrfToken.name}=${csrfToken.value}';
  dio.options.headers['X-CSRF-Token'] = csrfToken.value;
  
  // Now your requests are properly authenticated and CSRF-protected
  final response = await dio.post('https://your-api.com/secure-action', data: {...});
}

Note: The SuperBetterAuth client automatically manages cookies for all built-in operations. Manual cookie handling is only needed when making custom API calls outside of the provided methods.

Error Handling

final result = await client.signIn.email(
  email: "user@example.com",
  password: "wrongpassword"
);

if (result.isSuccess) {
  print("Welcome ${result.data!.user.name}!");
} else {
  // Handle different error types
  switch (result.error?.code) {
    case 'INVALID_CREDENTIALS':
      showSnackBar("Invalid email or password");
      break;
    case 'USER_NOT_FOUND':
      showSnackBar("No account found with this email");
      break;
    default:
      showSnackBar("Login failed: ${result.error?.message}");
  }
}

๐ŸŽฏ Full Example

import 'package:flutter/material.dart';
import 'package:super_better_auth/super_better_auth.dart';

void main() async {
   WidgetsFlutterBinding.ensureInitialized();
   await SuperBetterAuth.initialize(
      url: 'your_base_url/api/auth',
   );
   runApp(const MyApp());
}

class MyApp extends StatelessWidget {
   const MyApp({super.key});

   @override
   Widget build(BuildContext context) {
      return BetterAuthProvider(
         child: MaterialApp(
            title: 'BetterAuth',
            theme: ThemeData(
               colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
            ),
            home: const MyHomePage(title: 'Better Auth'),
         ),
      );
   }
}

class MyHomePage extends StatefulWidget {
   const MyHomePage({super.key, required this.title});

   final String title;

   @override
   State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
   @override
   Widget build(BuildContext context) {
      return Scaffold(
         appBar: AppBar(
            backgroundColor: Theme.of(context).colorScheme.inversePrimary,
            title: Text(widget.title),
         ),
         body: BetterAuthConsumer(
            builder: (context, client) {
               return Center(
                  child: Column(
                     mainAxisAlignment: MainAxisAlignment.center,
                     spacing: 8,
                     children: <Widget>[
                        FilledButton(
                           onPressed: () async {
                              final result = await client.signIn.email(
                                 email: "test@mail.com",
                                 password: "123456788",
                              );
                              if (result.data != null) {
                                 debugPrint(result.data.toString());
                              } else {
                                 debugPrint(result.error?.message);
                              }
                           },
                           child: Text("Sign-in"),
                        ),

                        FilledButton(
                           onPressed: () async {
                              final result = await client.getSession();
                              if (result.data != null) {
                                 debugPrint(result.data.toString());
                              } else {
                                 debugPrint(result.error?.message);
                              }
                           },
                           child: Text("GetSession"),
                        ),
                        FilledButton(
                           onPressed: () {
                              client.signOut();
                           },
                           child: Text("SignOut"),
                        ),
                        FilledButton(
                           onPressed: () async {
                              await client.signIn.social(
                                 provider: 'github',
                                 disableRedirect: true,
                                 callbackURL: "/auth-callback",
                                 callbackUrlScheme: "myapp",
                              );
                           },
                           child: Text("Github"),
                        ),

                        FilledButton(
                           onPressed: () async {
                              final result = await client.signUp.email(
                                 name: "test",
                                 email: "test@mail.com",
                                 password: "123456788",
                              );
                              if (result.data != null) {
                                 debugPrint(result.data.toString());
                              } else {
                                 debugPrint(result.error?.message);
                              }
                           },
                           child: Text("SignUp"),
                        ),
                        
                        // Organization Management Button
                        FilledButton(
                           onPressed: () {
                              Navigator.push(context, MaterialPageRoute(
                                 builder: (_) => OrganizationExample()
                              ));
                           },
                           child: Text("Organizations"),
                        ),
                        
                        // Cookie Management Button
                        FilledButton(
                           onPressed: () {
                              Navigator.push(context, MaterialPageRoute(
                                 builder: (_) => CookieExample()
                              ));
                           },
                           child: Text("Cookie Management"),
                        ),
                     ],
                  ),
               );
            },
         ),
      );
   }
}

๐Ÿ“ฑ Example App

The package includes a comprehensive example app demonstrating all features:

Running the Example

  1. Clone the repository
  2. Navigate to the example directory: cd example
  3. Install dependencies: flutter pub get
  4. Configure your Better Auth server URL in lib/main.dart
  5. Run the app: flutter run

Example Features

The example app includes:

  • Authentication Demo - Sign in/up with email, social providers
  • Organization Management - Complete CRUD operations for organizations
  • Cookie Inspector - View and manage authentication cookies
  • Error Handling - Comprehensive error state management
  • Real-time Updates - Live session state monitoring

File Structure

example/
โ”œโ”€โ”€ lib/
โ”‚   โ”œโ”€โ”€ main.dart                 # Main app with authentication
โ”‚   โ”œโ”€โ”€ organization_example.dart # Organization management UI
โ”‚   โ”œโ”€โ”€ cookie_example.dart       # Cookie management UI
โ”‚   โ””โ”€โ”€ .env                      # Environment configuration

๐Ÿ” Social Authentication

For social authentication, it is currently recommended to use idToken.

If the social provider does not support idToken, follow these steps:

  1. Add the dependency:

    Add flutter_web_auth_2: ^5.0.0-alpha.3 (or newer) to your pubspec.yaml dependencies.

  2. Update your AndroidManifest.xml:

    Insert the following into your AndroidManifest.xml, replacing YOUR_CALLBACK_URL_SCHEME_HERE with your actual callback URL scheme:

<manifest>
   <application>
      ...
      <activity
              android:name="com.linusu.flutter_web_auth_2.CallbackActivity"
              android:exported="true"
              android:taskAffinity="">
         <intent-filter android:label="flutter_web_auth_2">
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="YOUR_CALLBACK_URL_SCHEME_HERE" />
         </intent-filter>
      </activity>
      ...
   </application>
</manifest>
  1. Configure your Better Auth server plugin:

    Add expo() from @better-auth/expo to your Better Auth server plugin.

  2. Add your callback scheme to trustedOrigins:

    In your Better Auth configuration, ensure that YOUR_CALLBACK_URL_SCHEME_HERE:// is included in the trustedOrigins list.

export const auth = betterAuth({
   trustedOrigins: ["YOUR_CALLBACK_URL_SCHEME_HERE://"]
})

๐Ÿ“š API Reference

Core Authentication Methods

Method Description Parameters
signIn.email() Email/password sign in email, password
signIn.social() Social provider sign in provider, callbackURL
signUp.email() Email registration name, email, password
getSession() Get current session None
signOut() Sign out user None

Organization Methods

Method Description Parameters
organization.createOrganization() Create new organization name, slug?, logo?
organization.getOrganization() Get organization by ID organizationId
organization.updateOrganization() Update organization organizationId, data
organization.deleteOrganization() Delete organization organizationId
organization.inviteMember() Invite user to org organizationId, email, role
organization.listMembers() List organization members organizationId
Method Description Returns
getCookie(name) Get specific cookie Cookie?
getCookies() Get all cookies List<Cookie>
getAuthCookies() Get auth-related cookies List<Cookie>
hasCookie(name) Check if cookie exists bool
clearCookies() Clear all cookies void

๐Ÿ›ก๏ธ Security Best Practices

  • Never log or expose sensitive cookies in production
  • Use getAuthCookies() to filter only authentication-related cookies
  • Clear cookies on sign out: await client.clearCookies()

Organization Access Control

  • Always verify user permissions before organization operations
  • Use role-based access control for sensitive operations
  • Validate organization membership before allowing access

Error Handling

  • Always check result.isSuccess before accessing result.data
  • Handle network errors gracefully with retry mechanisms
  • Log errors for debugging but avoid exposing sensitive information

๐Ÿ”ง Configuration

Initialize with Custom Options

await SuperBetterAuth.initialize(
  url: 'https://your-api.com/api/auth',
  options: BetterAuthOptions(
    timeout: Duration(seconds: 30),
    retryCount: 3,
    enableLogging: true, // Only in development
  ),
);

Environment Variables

Create a .env file in your project root:

BETTER_AUTH_URL=https://your-api.com/api/auth
BETTER_AUTH_TIMEOUT=30000
BETTER_AUTH_ENABLE_LOGGING=false

๐Ÿงช Testing

Unit Testing

// Test authentication flow
testWidgets('should sign in user with email', (tester) async {
  final client = SuperBetterAuth.client;
  
  final result = await client.signIn.email(
    email: 'test@example.com',
    password: 'password123'
  );
  
  expect(result.isSuccess, true);
  expect(result.data?.user.email, 'test@example.com');
});

Integration Testing

The package includes comprehensive integration tests. Run them with:

flutter test integration_test/

๐Ÿค Contributing

We welcome contributions! Please see our Contributing Guide for details.

Development Setup

  1. Fork the repository
  2. Clone your fork: git clone https://github.com/yourusername/super_better_auth.git
  3. Create a feature branch: git checkout -b feature/amazing-feature
  4. Install dependencies: flutter pub get
  5. Run tests: flutter test
  6. Make your changes and add tests
  7. Commit your changes: git commit -m 'Add amazing feature'
  8. Push to your branch: git push origin feature/amazing-feature
  9. Open a Pull Request

Code Generation

After modifying models, run code generation:

flutter packages pub run build_runner build --delete-conflicting-outputs

๐Ÿ“‹ Changelog

v1.2.0 - Latest

  • โœ… Organization Management - Complete organization, team, and member management
  • โœ… Cookie Management - Direct access to authentication cookies with getCookie() method
  • โœ… Enhanced Error Handling - Improved error types and messages
  • โœ… Type Safety - Generated models with JSON serialization
  • โœ… Example App - Comprehensive example with all features
  • ๐Ÿ› Bug Fixes - Resolved null safety issues and improved stability

v1.1.0

  • โœ… Plugin System - Modular architecture for Better Auth plugins
  • โœ… Social Authentication - GitHub, Google, Discord support
  • โœ… Admin Features - Administrative user management
  • โœ… JWT Support - Token-based authentication

v1.0.0

  • โœ… Core Authentication - Email, phone, username authentication
  • โœ… Session Management - User session handling
  • โœ… Flutter Integration - Provider pattern with BetterAuthConsumer

๐Ÿ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

๐Ÿ‘ฅ Authors

๐Ÿ™ Acknowledgments

  • Better Auth team for the excellent authentication framework
  • Flutter community for continuous inspiration and support
  • All contributors who help improve this package

๐Ÿ“ž Support


Made with โค๏ธ for the Flutter community

โญ Star this repo โ€ข ๐Ÿ› Report Bug โ€ข ๐Ÿ’ก Request Feature

Libraries

core/api/adapter
core/api/better_auth_client
core/api/default/sign_in/models/email/sign_in_email_response
core/api/default/sign_in/models/social/sign_in_social_response
core/api/default/sign_in/models/social/social_id_token_body
core/api/default/sign_in/sign_in_better_auth
core/api/default/sign_in/sign_in_extension
core/api/default/sign_up/models/sign_up_response/sign_up_response
core/api/default/sign_up/sign_up_better_auth
core/api/default/sign_up/sign_up_extension
core/api/default/social/models/list_account/social_account_response
core/api/default/social/models/token/token_response
core/api/default/social/social_better_auth
core/api/default/social/social_extension
core/api/interceptor
core/api/models/common/sign_out/sign_out_response
core/api/models/common/verify_email/verify_email_response
core/api/models/result/better_error
core/api/models/result/result
core/api/models/result/result_extension
core/api/models/result/status_response
core/api/models/result/success_response
core/api/models/session/session_response
core/models/account/account
core/models/session/session
core/models/user/user
core/models/verification/verification
core/storage/hive_storage
core/storage/memory_storage
core/storage/storage
core/super_better_auth
core/utils/logger
plugins/admin/admin_better_auth
plugins/admin/admin_extension
plugins/admin/admin_plugin
plugins/admin/models/create_user/user_response
plugins/admin/models/permission/check_permission_response
plugins/email_otp/email_otp_better_auth
plugins/email_otp/email_otp_extension
plugins/email_otp/email_otp_plugin
plugins/jwt/jwt_better_auth
plugins/jwt/jwt_extension
plugins/jwt/jwt_plugin
plugins/jwt/models/jwk_key/jwt_key
plugins/jwt/models/jwt_key_response/jwt_key_response
plugins/jwt/models/token_response/token_response
plugins/organization/api/models/models
plugins/organization/api/models/requests/create_organization_request
plugins/organization/api/models/requests/create_team_request
plugins/organization/api/models/requests/invite_member_request
plugins/organization/api/models/requests/update_member_role_request
plugins/organization/api/models/requests/update_organization_request
plugins/organization/api/models/requests/update_team_request
plugins/organization/api/models/responses/check_slug_response
plugins/organization/api/models/responses/full_organization_response
plugins/organization/api/models/responses/invitation_response
plugins/organization/api/models/responses/member_response
plugins/organization/api/models/responses/organization_response
plugins/organization/api/models/responses/team_response
plugins/organization/api/organization_client
plugins/organization/models/invitation
plugins/organization/models/member
plugins/organization/models/models
plugins/organization/models/organization
plugins/organization/models/team
plugins/organization/organization
plugins/organization/organization_extension
plugins/organization/organization_plugin
plugins/phone/models/phone_body
plugins/phone/models/reset/reset_phone_password_body
plugins/phone/models/send_otp/send_otp_response
plugins/phone/models/sign_in_phone_body
plugins/phone/models/verify/verify_phone_body
plugins/phone/phone_better_auth
plugins/phone/phone_extension
plugins/phone/phone_plugin
presentation/better_auth_consumer
presentation/better_auth_inherit
presentation/better_auth_provider
super_better_auth