Networking In Flutter: 🔥Interceptors🔥
What is Auth and How Does It Work? What is Interceptor? How to add Interceptors to Network Requests and Response? How to store Auth Token?

Search for a command to run...
What is Auth and How Does It Work? What is Interceptor? How to add Interceptors to Network Requests and Response? How to store Auth Token?

Awesome article... I love this, simple, concise, and straightforward.
However, how can the app check for user inactivity for a short period and logs the user out using dio interceptor, especially on network calls for security reasons on the app, Can you please explain how?
Thank you so much
How do you handle wrong email or password case?, I can't make BLoC to emitt to LogInFailed
hello, excellent article... I have a question... how would it be when an api comes with a request to refresh the token every so often? I know Dio does that but how would it be? Thank you
Check this out.
Lessons from Code, Content, and Consistency

Reliability basics: Outbox pattern + why it matters

Introducing Kafka/Redpanda + move to event-driven workflow

Connect Orders ↔ Inventory (first working service-to-service flow)

Inventory service + gRPC + proto contracts











User.dart which is nothing but a data class. We will convert the user data received from the server into a dart understandable data class.
class EndPoints {
static const String baseUrl = 'http://localhost:3000';
static const String allUsers = '/users/all';
static const String userEmail = '/users/email';
static const String login = '/users/login';
static const String register = '/users/register';
static const String profile = '/users/profile';
}
class DioClient {
final _dio = Dio();
Dio get dio => _dio;
}

In the SharedPreferenceHelper class, there are two main methods to store and get the token from the local DB.
class SharedPreferenceHelper {
static const String token = "TOKEN";
final SharedPreferences prefs;
SharedPreferenceHelper({required this.prefs});
Future<void> setUserToken({required String userToken}) async {
await prefs.setString(token, userToken);
}
String? getUserToken() {
final userToken = prefs.getString(token);
return userToken;
}
}

locator.dartfile we are going to register both the classes.final getIt = GetIt.instance;
//
Future<void> setup() async {
final _prefs = await SharedPreferences.getInstance();
getIt.registerSingleton<SharedPreferenceHelper>(
SharedPreferenceHelper(prefs: _prefs),
);
getIt.registerSingleton<DioClient>(DioClient());
}
setup() method defined in this class in the main() method. Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await setup();
runApp(const MyApp());
}

auth bloc.dart file, you'll notice that we're storing the Token that we get from the auth repository's login() method. Keep in mind that this token will be used in later requests.
register() and login(). Which will be called when the user presses the respective buttons from the UI.getAllUser() and as the name suggests, it is used to fetch all the users from the server.getUserProfileDetails() method, which is used to get the currently logged in user data from the server.getEmail(), which is used to get the tapped user email from the server.
home_repository.dart, email_repository.dart and profile_repository.dart I've attached the Token with the request that we are making to the server in order to get the data.//home_repository.dart
Future<List<User>> getAllUsers() async {
final response = await netWorkLocator.dio.get(
'${EndPoints.baseUrl}${EndPoints.allUsers}',
options: Options(
headers: {
'Authorization': '${sharedPrefLocator.getUserToken()}', <---Here
},
),
);
final data = (response.data as List).map((e) => User.fromJson(e)).toList();
return data;
}
class DioClient {
final _dio = Dio();
Dio get dio => _dio;
}
dio_interceptor.dart file inside the network folder.class DioInterceptor extends Interceptor {}
Here we need to override three methods :
onRequest(): This method is used to perform operations in the request before sending it to the server. For example: Setting the Header, Adding Token, etc
You can utilize this method as per your own requirements. In our case, we need to implement the onRequest() method in order to add the Token when requesting to the server. Let's implement it
class DioInterceptor extends Interceptor {
final _prefsLocator = getIt.get<SharedPreferenceHelper>();
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
options.headers['Authorization'] = _prefsLocator.getUserToken();
super.onRequest(options, handler);
}
@override
void onResponse(Response response, ResponseInterceptorHandler handler) {
// TODO: implement onResponse
super.onResponse(response, handler);
}
@override
void onError(DioError err, ErrorInterceptorHandler handler) {
// TODO: implement onError
super.onError(err, handler);
}
}
As you can see we are setting the Authorization key in the header when requesting to the server. That's it. Now head over to the dio_client.dart file and add this custom interceptor to our dio instance in the constructor.
class DioClient {
final Dio _dio = Dio();
DioClient() {
_dio.interceptors.add(DioInterceptor());
}
Dio get dio => _dio;
}
DioClient() {
_dio.interceptors.add(
InterceptorsWrapper(
onRequest: (options, handler) {},
onResponse: (response, handler) {},
onError: (error, handler) {}),
);
}
home_repository.dartFuture<List<User>> getAllUsers() async {
final response = await netWorkLocator.dio.get(
'${EndPoints.baseUrl}${EndPoints.allUsers}',
// options: Options(
// headers: {
// 'Authorization': '${sharedPrefLocator.getUserToken()}',
// },
// ),
);
final data = (response.data as List).map((e) => User.fromJson(e)).toList();
return data;
}
email_repositoryFuture<String> getEmail({required String id}) async {
final response = await netWorkLocator.dio.get(
"${EndPoints.baseUrl}${EndPoints.userEmail}",
// options: Options(
// headers: {
// "Authorization": "${sharedPrefLocator.getUserToken()}",
// },
// ),
queryParameters: {
"_id": id,
},
);
return response.data["email"];
}
profile_repository.dartFuture<User> getUserProfileDetails() async {
final response = await netWorkLocator.dio.get(
'${EndPoints.baseUrl}${EndPoints.profile}',
// options: Options(
// headers: {
// 'Authorization': '${sharedPrefLocator.getUserToken()}',
// },
// ),
);
return User.fromJson(response.data['user']);
}

