In today’s digital world, implementing robust authentication and seamless navigation are crucial aspects of any web application.
When it comes to Flutter Web, developers face unique challenges in setting up authentication and navigation due to the nature of web-based interactions.
Fortunately, there is a powerful package called go_router that simplifies the process and enhances the user experience.
In this article, we will delve into the importance of authentication and navigation in Flutter Web and explore how go_router can be utilized to overcome these challenges effectively.
Authentication forms the backbone of secure web applications, ensuring that only authorized users can access sensitive information or perform specific actions. Implementing authentication in Flutter Web is of utmost importance as it provides several benefits and plays a crucial role in the overall security and integrity of your application.
By recognizing the benefits and understanding the importance of implementing authentication in Flutter Web, you can ensure the security, privacy, and integrity of your application.
It enables you to provide a seamless and trusted user experience while protecting sensitive data from unauthorized access.
Invest the necessary time and effort into implementing robust authentication mechanisms to establish a strong foundation for your Flutter Web application’s security and success.
Seamless navigation is vital for creating intuitive and user-friendly web applications. In Flutter Web, navigation plays a crucial role in providing a smooth user experience and ensuring users can effortlessly move between different sections of your application. Let’s explore the benefits and importance of implementing effective navigation in your Flutter Web projects.
Incorporating effective navigation in your Flutter Web application not only enhances the user experience but also helps achieve business goals, improve conversion rates, and increase user retention. By adopting a user-centric approach and designing a clear and intuitive navigation system, you can provide a seamless browsing experience that keeps users engaged, satisfied, and coming back for more.
Investing time and effort in understanding your users’ needs, organizing your content, and implementing well-designed navigation elements will undoubtedly contribute to the success and usability of your Flutter Web application.
Learn How to Build Complex Navigation Stack with Flutter
Go Router is a powerful Flutter package specifically designed for managing navigation in Flutter Web applications.
It offers several benefits over the standard Flutter navigation system, making it an excellent choice for implementing navigation in Flutter Web projects.
While Flutter Navigation 2.0 provides a solid foundation for navigation, go_router offers additional features and flexibility specifically tailored for Flutter Web. It simplifies the navigation process and improves overall performance, resulting in a smoother user experience. Go Router leverages the browser history API to manage the page stack and back navigation, allowing users to navigate backwards through the application history using the browser’s back button or other navigation gestures. This feature ensures consistent behaviour and enhances user convenience.
Easy setup: Go Router provides a straightforward and intuitive API, making it simple to integrate with your Flutter Web project.
Deep linking: Go Router enables deep linking by updating the URL dynamically, allowing users to share specific screens or states of your application.
Nested routing: With Go Router, you can easily implement nested routing, allowing for complex and hierarchical navigation structures.
Error handling: Go Router offers built-in error handling mechanisms, making it easier to handle exceptions and provide meaningful error messages to users.
flutter create my_app
dependencies:
go_router: ^7.0.1
hive: ^2.2.3
hive_flutter: ^1.1.0
dev_dependencies:
build_runner: ^2.4.2
hive_generator: ^2.0.0
Here, the hive is used to store local data. You can use shared_preferences or any other local data storage package instead of the hive.
Create a common service to handle authentication-related logic, such as user authentication, session management, and secure storage.
This service will serve as the foundation for implementing authentication in your Flutter Web application.
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:hive/hive.dart';
import '../../models/user_data.dart';
import '../pages/login_page.dart';
class AppService extends ChangeNotifier {
/// Ensure to make this as a singleton class.
AppService._();
factory AppService() => _instance;
static AppService get instance => _instance;
static final AppService _instance = AppService._();
final Box storageBox = Hive.box('App Service Box');
final navigatorKey = GlobalKey<NavigatorState>();
BuildContext get context => navigatorKey.currentContext!;
final _kCurrentUserKey = 'current_user';
UserData? currentUser;
bool get isLoggedIn => currentUser != null;
void initialize() {
final user = storageBox.get(_kCurrentUserKey);
if (user != null) currentUser = user;
}
void setUserData(UserData userData) {
storageBox.put(_kCurrentUserKey, userData);
currentUser = userData;
notifyListeners();
}
void manageAutoLogout() {
terminate();
context.go(LoginPage.route);
}
Future<void> terminate() async {
currentUser = null;
storageBox.clear();
}
}
import 'package:hive/hive.dart';
part 'user_data.g.dart';
@HiveType(typeId: 0)
class UserData {
@HiveField(0)
final String? id;
@HiveField(1)
final String? email;
const UserData({
this.id,
this.email,
});
}
flutter pub run build_runner build --delete-conflicting-outputs
This command will generate user_data.g.dart at the same location as user_data.dart
Initialize go_router in your application and define the initial route.
You can set up a default route and handle the navigation based on the user’s authentication status.
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import '../pages/home_page.dart';
import '../pages/login_page.dart';
import '../services/app_service.dart';
part 'redirection.dart';
final router = GoRouter(
redirect: _redirect,
debugLogDiagnostics: true,
refreshListenable: AppService.instance,
navigatorKey: AppService.instance.navigatorKey,
routes: <GoRoute>[
GoRoute(
path: '/',
redirect: (_, __) => HomePage.route,
),
GoRoute(
path: LoginPage.route,
pageBuilder: (context, state) => const MaterialPage(child: LoginPage()),
),
GoRoute(
path: HomePage.route,
pageBuilder: (context, state) => const MaterialPage(child: HomePage()),
),
],
);
Redirect users based on their authentication status. If a user is not authenticated, redirect them to the login page. Otherwise, navigate them to the home page or any other authorized sections.
part of 'router.dart';
String? _redirect(BuildContext context, GoRouterState state) {
final isLoggedIn = AppService.instance.isLoggedIn;
final isLoginRoute = state.matchedLocation == LoginPage.route;
if (!isLoggedIn && !isLoginRoute) {
return LoginPage.route;
} else if (isLoggedIn && isLoginRoute) {
return HomePage.route;
}
return null;
}
Define routes for different screens and components of your application.
With go_router, you can easily map routes to specific pages or widgets.
import 'package:flutter/material.dart';
import 'package:flutter_web_plugins/url_strategy.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'models/user_data.dart';
import 'routing/router.dart';
import 'services/app_service.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Hive.initFlutter();
Hive.registerAdapter(UserDataAdapter());
await Hive.openBox('App Service Box');
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
usePathUrlStrategy();
AppService.instance.initialize();
}
@override
Widget build(BuildContext context) {
return MaterialApp.router(
title: 'Web Authentication',
debugShowCheckedModeBanner: false,
routerDelegate: router.routerDelegate,
routeInformationParser: router.routeInformationParser,
routeInformationProvider: router.routeInformationProvider,
);
}
}
Create the necessary pages and widgets for your application.
Each page should correspond to a specific route defined in the go_router configuration and provide the desired functionality.
Design your pages with user-friendly interfaces, intuitive navigation elements, and responsive layouts to ensure a pleasant user experience across various devices.
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:web_auth_demo/models/user_data.dart';
import 'package:web_auth_demo/services/app_service.dart';
import 'home_page.dart';
class LoginPage extends StatefulWidget {
static const route = '/login';
const LoginPage({Key? key}) : super(key: key);
@override
State<LoginPage> createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final _emailCtrl = TextEditingController();
final _passwordCtrl = TextEditingController();
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView(
padding: const EdgeInsets.all(16),
children: [
const Text(
'Login to your account',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 32),
TextFormField(
controller: _emailCtrl,
),
const SizedBox(height: 16),
TextFormField(
controller: _passwordCtrl,
obscureText: true,
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
AppService.instance.setUserData(UserData(
id: DateTime.now().millisecondsSinceEpoch.toString(),
email: _emailCtrl.text,
));
context.go(HomePage.route);
},
child: const Text('Login'),
)
],
),
);
}
}
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import '../pages/login_page.dart';
import '../services/app_service.dart';
class HomePage extends StatefulWidget {
static const route = '/home';
const HomePage({Key? key}) : super(key: key);
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Home page'),
actions: [
IconButton(
onPressed: () async {
await AppService.instance.terminate();
if (mounted) context.go(LoginPage.route);
},
icon: const Icon(Icons.logout),
)
],
),
body: Center(
child: Text('Login to ${AppService.instance.currentUser!.email}'),
),
);
}
}
Explore a comparison between the performance of an app built with Native Android and Flutter.
Implementing authentication and navigation in Flutter Web is vital for creating secure and user-friendly web applications.
The go_router package offers a powerful solution for managing navigation, providing a seamless browsing experience for users. By leveraging go_router, developers can simplify the navigation setup process, handle authentication efficiently, and enhance the overall user experience.
By following the steps outlined in this article, you can easily set up go_router in your Flutter Web project, add necessary dependencies, create a common service for authentication logic, define routes, and design pages that provide a cohesive and intuitive user experience. For any assistance with Flutter app development, connect with our team of skilled Flutter developers today. They will provide expert guidance and deliver top-notch solutions tailored to your needs.