How to handle 401(unauthorised) with Dio interceptor— Flutter

Krishan Madushanka
2 min readJul 8, 2021

In this article I am going to explain about how to make network calls with flutter dio(4.0.0) and handling 401 when you use refresh tokens and access tokens to handle authorization in your flutter application.

Before reading this, I expect you have a basic knowledge about flutter mobile app development.

Basic Authentication flow with refresh and access tokens

As you can see in the above diagram, it’s clear that what is the flow when you use refresh and access token in authentication flow. After logging in you will get two tokens called refresh and access. This access token is expiring quickly(refresh token also expiring but it will take more time than access token). When you make a request with expired access token you get status code 401(unauthorised) in the response.In that situation you have to ask for a new tokens from the server and make the previous request with valid access token again. If the refresh token also has expired you have to direct the user to login page and force to login again.

Dio class

Above is the full class and I am going to explain the most important parts there.

Mainly, as you can see inside the createDioInstance method you have to add an interceptor to catch the 401.when 401 occurred onError: (DioError e, handler) async{} is getting called. so inside that you

  1. Check the error code(401),
  2. Get new access token
await refreshToken();

above code will call the refreshToken method and store new refresh and access tokens in the repository.(for repository you can use flutter secure storage or shared preferences)

3. Make a clone of the previous request and set new access token

RequestOptions requestOptions = e.requestOptions;
Repository repository = Repository();
var accessToken = await repository.readData("accessToken");
final opts = new Options(method: requestOptions.method);
dio.options.headers["Authorization"] = "Bearer " + accessToken;
dio.options.headers["Accept"] = "*/*";

4. Make the previous call again

final response = await dio.request(requestOptions.path,
options: opts,
cancelToken: requestOptions.cancelToken,
onReceiveProgress: requestOptions.onReceiveProgress,
data: requestOptions.data,
queryParameters: requestOptions.queryParameters);

once the response is came, call

handler.resolve(response);

Then the response will be sent to the place where you called api as follows.

var dio = DioUtil().getInstance();
final String apiUrl = (BASE_PATH + "payments/addNewPayment/");
var accessToken = await repository.readData("accessToken");
dio.options.headers["Authorization"] = "Bearer " + accessToken;
dio.options.headers["Accept"] = "*/*";
//response will be assigned to response variable
response = await dio.post(apiUrl);

Thats all. happy coding :)
Hit on clap if this helped you and follow me for more articles.

--

--

Krishan Madushanka

Software Engineer | Android | iOS | Flutter | React Native | IoT | aws certified