Auth

Auth

The Auth components are designed to simplify the integration of authentication services from popular cloud providers like Firebase and Appwrite. By leveraging Auth, you can avoid the need to memorize specific implementations for each provider, making your code more concise and maintainable.

// Example: Signup, logout, and login.
final authService = AuthService.static.cloud();
 
var account = await authService.signup(AuthCredentials.email(email: email, password: password));
await authService.logout();
account = await authService.login(AuthCredentials.email(email: email, password: password));

In addition to cloud services, Auth also enables you to emulate authentication when you're in the testing or device environment. This feature allows you to test your application's authentication flow without relying on live services.

AuthService

The AuthService class is the core of the Auth components. It provides methods for login, signup, logout, and delete, allowing you to handle user authentication seamlessly.

Additionally, Auth introduces the loginWithOtp method, which enables login with a one-time password (OTP). Currently, only SMS OTP is supported, but more options will be added in the future.

// Example: Login with OTP
final account = await AuthService.static.cloud().loginWithOtp(OtpProvider.phone(
  phoneNumber: '18001234567',
  smsCodeGetter: () => getUserInputForSmsCode(), // Getter for the user submitting the SMS code they received. Once validated, an `Account` will be returned.
));

Auth provides several AuthService implementations to cater to different scenarios:

  • memory(): An in-memory implementation suitable for testing and development.
  • file(): A file-based implementation that stores authentication data locally.
  • cloud(): An implementation that integrates with cloud providers like Firebase and Appwrite.
  • adapting(): An implementation that adapts to the current environment.

Account

The Account class represents a user's account in your application. It contains an accountId and an isAdmin property, indicating whether the user is an admin or not.

// Example: Check if user is an admin
final account = authService.loggedInAccount;
 
account.accountId; // A unique ID for this account.
 
if (account.isAdmin) {
  // Perform admin-specific actions
} else {
  // Perform regular user actions
}

In the memory() and adapting() implementations, you can set whether logged-in users in the testing environment are admins by passing the memoryIsAdmin: true parameter. This helps you test the functionality of your app based on the user's admin status.

final authService = AuthService.static.memory(isAdmin: true); // Accounts created with this AuthService are admins.
 
final account = await authService.signup(AuthCredentials.email(email: email, password: password));
account.isAdmin; // true

To understand how the different auth services generate account IDs and determine whether an account is an admin or not, check out the integration page for Firebase or Appwrite

AuthService Implementations

Auth supports various authentication service implementations, including file-based storage, cloud-based storage, and environment-specific storage. However, the .cloud modifier on its own do not provide any implementation details. It requires authServiceImplementations to be passed into FloodCoreComponent to specify the exact implementation of the authentication services to use in those environments.

For example, if you pass in FirebaseCloudRepositoryImplementation as one of the repositoryImplementations, it will make any .cloud repositories (or any .adapting repositories in a cloud environment) use the Firebase implementation. Similarly, you can provide implementations for other environments or storage mechanisms.

Here's an example of passing repository implementations to FloodCoreComponent:

await corePondContext.register(FloodCoreComponent(
    authServiceImplementations: (corePondContext) => [FirebaseAuthServiceImplementation()],
));

Hooks

Auth provides the useLoggedInAccountOrNull() hook (opens in a new tab), which returns the currently logged-in account or null if the user is not logged in. This hook makes it easy to access the account information in your Flutter widgets.

// Example: Display user's email in a widget
final account = useLoggedInAccountOrNull();
 
if (account != null) {
  return Text('Logged in as: ${account.email}');
} else {
  return Text('Not logged in');
}

Usage

To use Auth in your application, pass an AuthService instance to FloodCoreComponent. After the CorePondContext has been loaded, you can determine the current authentication status of the user.

example_core/lib/pond.dart
await corePondContext.register(FloodCoreComponent(
    authService: (context) => AuthService.static.adapting(memoryIsAdmin: true),
);
final account = corePondContext.locate<AuthCoreComponent>().loggedInAccount;

Debugging

Use the Debug Module to view debug information about the currently logged-in user.