easy_auth 0.2.1 copy "easy_auth: ^0.2.1" to clipboard
easy_auth: ^0.2.1 copied to clipboard

Widgets and classes that make it easy to add authentication to any Flutter app

EasyAuth

very good analysis very good analysis License: MIT


Widgets and classes that make it easy to add authentication to any Flutter app. Built on top of the package:bloc architecture, it is fully authentication framework agnostic but provides some plug-and-play mechanisms for commonly used frameworks like package:firebase_auth.

⚠️ If you like this repository, I would really appreciate some help in maintaining/improving/promoting it!


Usage #

Lets take a look at how to integrate a basic Firebase Auth state to your app. For other examples, check the examples folder.

First, we create a basic MaterialApp (or any other app you might use) and initialize the default Firebase App:

// -> main.dart
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  GestureBinding.instance!.resamplingEnabled = true;
  await Firebase.initializeApp();
  runApp(
    MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const MyApp(),
    ),
  );
}
copied to clipboard

We then create our MyApp widget that extends AuthenticationBasedApp:

// -> main.dart
class MyApp extends AuthenticationBasedApp<EquatableUser> {
  const MyApp({Key? key}) : super(key: key);

  @override
  BasicFirebaseAuth get repository => BasicFirebaseAuth();

  @override
  Widget buildState(BuildContext context, AuthStatus status, EquatableUser user) {
    switch (status) {
      case AuthStatus.uninitialized:
        return const SplashScreenView();
      case AuthStatus.authenticated:
        return const HomeView();
      case AuthStatus.newAccount:
        return const HomeView.newAccount();
      case AuthStatus.authenticating:
      case AuthStatus.unauthenticated:
        return const LoginView();
    }
  }
}
copied to clipboard

That's it, you're done! Now you can use EasyAuth as you would use FirebaseAuth and login, signout, create accounts, etc.

Notice that we passed the EquatableUser class as a generic to AuthenticationBasedApp, let's talk about why.

EquatableUser #

This class is used as a default representation of what a user would be. It can easily be extended to add your own parameters.

As it extends Equatable, if you want to include property as part of the == operation, you'll have to add it to the props array.

// -> custom_user.dart
class CustomUser extends EquatableUser {
 const CustomUser({required this.birthday}) : super(id: '1', email: 'first@user.com');

 final String birthday;

 @override
 List<Object?> get props => [...super.props, birthday];
}
copied to clipboard

EasyAuth methods #

EasyAuth is a utility class that lets you statically access the methods on your AuthenticationRepository.

ElevatedButton(
  child: const Text('Log in'),
  onPressed: () {
    final provider = EmailPasswordAuth('test@easyauth.com', 'some-password');
    EasyAuth.login(context, provider: provider);
  },
)
copied to clipboard

AuthenticationRepository #

AuthenticationRepository is an abstract class that defines all the methods necessary to add a custom authentication provider.

Note that you do not need to handle errors when overriding any methods in this class!

abstract class AuthenticationRepository<T extends EquatableUser> {
  Future<void> login({required EasyAuthProvider provider});
  Future<void> register({required T user, required String password});
  Future<void> signOut();
  Future<void> deleteAccount();
  bool isUserNew(T user);

  T get currentUser;
  Stream<T> get user;

  Future<AuthException?> performSafeAuth(Future<void> future, AuthAction action) async {...}
}
copied to clipboard

The only method that does not need to be re-implemented is performSafeAuth(...). It is used to handle any errors that might be thrown by performing an authentication action.

Here's an example of a BasicFirebaseAuth:

class BasicFirebaseAuth extends AuthenticationRepository<EquatableUser> {
  final _firebaseAuth = FirebaseAuth.instance;

  @override
  Stream<EquatableUser> get user => _firebaseAuth.authStateChanges().map<EquatableUser>((user) {
        if (user == null) {
          return EquatableUser.empty;
        } else {
          return EquatableUser(
            id: user.uid,
            name: user.displayName,
            email: user.email,
            createdAt: user.metadata.creationTime,
          );
        }
      });

  @override
  bool isUserNew(EquatableUser user) =>
      user.createdAt?.isAfter(DateTime.now().subtract(const Duration(seconds: 5))) ?? false;

  @override
  EquatableUser get currentUser {
    final _user = _firebaseAuth.currentUser!;
    return EquatableUser(id: _user.uid, name: _user.displayName, email: _user.email);
  }

  @override
  Future<void> login({required EasyAuthProvider provider}) async {
    if (provider is EmailPasswordAuth) {
      await _firebaseAuth.signInWithEmailAndPassword(email: provider.email, password: provider.password);
    } else if (provider is GoogleAuth) {
      //sign in with google
    }
  }

  @override
  Future<void> register({required EquatableUser user, required String password}) async {
    if (user.email == null) throw FirebaseAuthException(code: 'no-email-registration');
    await _firebaseAuth.createUserWithEmailAndPassword(email: user.email!, password: password);
  }

  @override
  Future<void> signOut() => _firebaseAuth.signOut();

  @override
  Future<void> deleteAccount() => _firebaseAuth.currentUser!.delete();
}
copied to clipboard

EasyAuthProvider #

If you need to add more authentication providers than the pre-packaged ones, simply override the EasyAuthProvider class.

EasyAuth Widgets #

AuthenticationBasedApp

AuthenticationBasedApp is an abstract class that you need to extend to add authentication responsiveness to your app.

There are a couple of methods you need to know about:

  /// Rebuilds the state of the app every time the authentication status changes.
  /// This is an efficient method due to `T` extending `Equatable` and
  /// therefore only rebuilding when necessary
  Widget buildState(BuildContext context, AuthStatus status, T user);
copied to clipboard

Note: this method needs to be overriden.

  /// Called when an exception relating to authentication gets thrown.
  /// Can be overriden to provide your own custom error-handling logic (e.g. logging, custome snackbar, etc.)
  void handleError(BuildContext context, AuthException exception) {...}
copied to clipboard

Note: this method has a default implementation that prints the action that was performed when the exception was thrown and displays the following Flushbar from package:another_flushbar.

Flushbar(
  icon: const Padding(padding: EdgeInsets.only(left: 14.0), child: Text('😱')),
  message: exception.message,
  backgroundColor: Theme.of(context).errorColor,
  margin: const EdgeInsets.all(8),
  borderRadius: BorderRadius.circular(8.0),
  flushbarPosition: FlushbarPosition.TOP,
  flushbarStyle: FlushbarStyle.FLOATING,
);
copied to clipboard

EasyAuthBuilder

EasyAuthBuilder is a Flutter widget which requires a builder function. EasyAuthBuilder handles building the widget in response to new authentication states. EasyAuthBuilder is a simple wrapper around BlocBuilder from package:bloc. The builder function will potentially be called many times and should be a pure function that returns a widget in response to the state.

EasyAuthBuilder(
  builder: (context, status, user) {
    // return widget here based on the current AuthSatus and User
  }
)
copied to clipboard

Examples #

Dart Versions #

  • Dart 2: >= 2.12
  • Flutter: >=1.17.0

Maintainers #

12
likes
130
points
60
downloads

Publisher

unverified uploader

Weekly Downloads

2024.08.09 - 2025.02.21

Widgets and classes that make it easy to add authentication to any Flutter app

Repository (GitHub)
View/report issues

Documentation

Documentation
API reference

License

MIT (license)

Dependencies

bloc, equatable, flutter, flutter_bloc, rxdart

More

Packages that depend on easy_auth