Courses

[NEW] Flutter 3 Mobile App with Laravel 12 API

Storing Authentication Tokens on Device

Now that we have our Navigation bar, we should consider our user experience. Currently, each time users launch the app, they have to log in. This is not a good user experience. We should store the token on the device so that users don't have to log in each time they launch the app.


Installing Package

First, we need a secure way to store the information. While we could use a simple filesystem, there is a package that makes it easier for us. We'll use the flutter_secure_storage package.

flutter pub add flutter_secure_storage

Once the package is installed, we can store the token on the device.


Changing Token to be Nullable

Currently, the token is required. This can cause exceptions when we try to store a null value after hibernation (minimizing the app and waking it up). So let's solve that:

lib/services/api.dart

// ...
class ApiService {
late String token;
late String? token;
// ...

Storing Token on Device

And finally, we can work on setting/getting the token from the device. For this, we'll need two functions:

lib/providers/auth_provider.dart

// ...
 
Future<String?> getToken() {
Future<String?> token = storage.read(key: 'token');
if(token != null) {
return Future.value(token);
}
 
return Future.value('');
}
 
Future<String?> setToken(String token) async {
await storage.write(key: 'token', value: token);
 
return token;
}
 
// ...

Of course, we can't forget to import the package and initialize our storage in the AuthProvider:

lib/providers/auth_provider.dart

import 'package:flutter_secure_storage/flutter_secure_storage.dart';
 
// ...
 
class AuthProvider extends ChangeNotifier {
bool isAuthenticated = false;
late String token;
ApiService apiService = ApiService('');
final storage = new FlutterSecureStorage();
// ...

Then, we can use these functions in our functions:

lib/providers/auth_provider.dart

// ...
 
Future<void> register(String name, String email, String password,
String password_confirmation, String device_name) async {
token = await apiService.register(
name, email, password, password_confirmation, device_name);
setToken(token);
isAuthenticated = true;
notifyListeners();
}
 
Future<void> login(String email, String password, String device_name) async {
token = await apiService.login(email, password, device_name);
setToken(token);
isAuthenticated = true;
notifyListeners();
}
 
Future<void> logout() async {
token = '';
isAuthenticated = false;
await storage.delete(key: 'token');
notifyListeners();
}

If we try to load the application, our token will be stored on the device. But if we reload it - we'll still have to log in. This is because we're not checking if the token is stored on the device. So let's do that:

lib/providers/auth_provider.dart

// ...
 
class AuthProvider extends ChangeNotifier {
bool isAuthenticated = false;
late String token;
ApiService apiService = ApiService('');
final storage = new FlutterSecureStorage();
 
AuthProvider();
AuthProvider() {
getToken().then((value) {
if (value != null) {
token = value;
isAuthenticated = true;
notifyListeners();
}
});
}
// ...

Now, completely restart your application emulator and log in. If you do a hot reload in VSCode, you should still be logged in after it reloads.


In the next lesson, we'll take what we learned and create a Transactions CRUD.


Check out the GitHub Commit for this lesson.

Previous: Adding Bottom Navigation Bar

No comments yet…

avatar
You can use Markdown