Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
827 views
in Technique[技术] by (71.8m points)

json - I am trying to store the Authorization Token fetched from the Rest API and then use it in the headers of other API calls in Flutter

As the title of the problem explains most of it but will still elaborate more. So I am calling an API using the POST method and registering a user which gives me response data containing only the Authorization token which needs to be used while calling other APIs.

Now I want to store the token and use it in the headers while making other API calls. I am herewith attaching a few code snippets that might demonstrate what I have done actually and what needs to be done in order to get the particular outcome. I am getting the API response for fetching the key but I am unable to understand why it is not getting stored and why cannot I use it in the headers.

API call that returns just the token in the response

   final storage = SecureStorage();
Future<UserRegistration> registration(dynamic param) async {
    var client = http.Client();
    try {
      var response = await client
          .post(Uri.https("baseURL", "endpoint"),
              body: param)
          .timeout(Duration(seconds: TIME_CONST))
          .catchError(handleError);

      if (response.statusCode == 201) {
        print('Response Body: ${response.body}');
        final data = jsonDecode(response.body);

    ///////Using the flutter secure storage here to save the token

         var token = storage.writeSecureToken('key', data['key']);
          print("Token Here $token");
        return UserRegistration(
          key: data['key'],
          status: true,
        );
      } else {
        print("Something went wrong");
        return param;
      }
    } on SocketException {
      throw FetchDataException('message', 'url');
    } on TimeoutException {
      throw ApiNotRespondingException("message", "url");
    }
  }

API response that I am getting

Response Body: {"key":"8fb303212871a80899f0b883f3554b189fddf24b"}

API call that I am making which requires the Authorization Header as the key received in the previous response.

Future<PhoneOTPValidate> phoneOTPvalidate(dynamic param) async {
    var client = http.Client();
    var token = storage.readSecureToken('key');
    try {
      var response = await client
          .post(
              Uri.https("baseURL", "endpoint"),
              headers: <String, String>{
                'Authorization': 'Token $token',
              },
              body: param)
          .timeout(Duration(seconds: TIME_CONST))
          .catchError(handleError);

      if (response.statusCode == 200) {
        print('Response Body: ${response.body}');
        final data = jsonDecode(response.body);
        return PhoneOTPValidate(
          status: data['success'],
          validate: true,
        );
      } else {
        print("The OTP is not valid");
        return param;
      }
    } on SocketException {
      throw FetchDataException('message', 'url');
    } on TimeoutException {
      throw ApiNotRespondingException("message", "url");
    }
  }

My Classes for the above API calls are here:

class PhoneOTPValidate {
  PhoneOTPValidate({this.status, this.validate});
  final String? status;
  final bool? validate;
}

class UserRegistration {
  UserRegistration({this.key, this.status});
  final String? key;
  final bool? status;
}

Flutter Secure Storage Class

class SecureStorage {
  final storage = FlutterSecureStorage();
  Future writeSecureToken(String key, String value) async {
    var writeData = await storage.write(key: key, value: value);
    print('Token Here');
    return writeData;
  }

  Future readSecureToken(String key) async {
    var readData = await storage.read(key: key);
    return readData;
  }

  Future deleteSecureToken(String key) async {
    var deleteData = await storage.delete(key: key);
    return deleteData;
  }
}

Here's the output for what I have written:

Response Body: {"key":"de18d1239ed0b6be13f4c9a9d96eebeb1c401922"}
I/flutter (23010): Token Here Instance of 'Future<dynamic>'
I/flutter (23010): Token Here

How do I solve this problem of saving the key and using it in the headers of the other API calls? Have almost tried all the solutions from StackOverflow but nothing gave a solid answer to how it is being done. Am stuck at this problem for quite a few days Would appreciate it if anyone can solve my problem considering my code.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The problem is that you don't "await" for secure token to be read and written. This can easily be avoided by providing explicit types for you variables. Let's fix your code:

// I assume you are using null-safety

class SecureStorage {
  final FlutterSecureStorage storage = FlutterSecureStorage();
  Future<void> writeSecureToken(String key, String value) async {
    // I'm not exactly sure how you get the data from storage.write, because it has a type of Future<void>
    // So the whole function should be await storage.write(key: key, value: value);
    await storage.write(key: key, value: value);
  }

  Future<String?> readSecureToken(String key) async {
    return await storage.read(key: key);
  }

  Future<void> deleteSecureToken(String key) async {
    // Same here: delete is a type of void, so it shouldn't return anything
    await storage.delete(key: key);
  }
}

Then with updating secured storage finished we can move to getting the token

final storage = SecureStorage();
Future<UserRegistration> registration(dynamic param) async {
  var client = http.Client();
  try {
    var response = await client
        .post(Uri.https("baseURL", "endpoint"), body: param)
        .timeout(Duration(seconds: TIME_CONST))
        .catchError(handleError);

    if (response.statusCode == 201) {
      print('Response Body: ${response.body}');
      final data = jsonDecode(response.body);

      ///////Using the flutter secure storage here to save the token
      String? token = data['key'];
      if (token == null) {
        throw Exception("No token in response");
      }
      
      await storage.writeSecureToken('key', token);
      print("Token Here $token");
      return UserRegistration(
        key: token,
        status: true,
      );
    } else {
      print("Something went wrong");
      return param;
    }
  } on SocketException {
    throw FetchDataException('message', 'url');
  } on TimeoutException {
    throw ApiNotRespondingException("message", "url");
  }
}

and finally fix the read for the token when you make a call:

Future<PhoneOTPValidate> phoneOTPvalidate(dynamic param) async {
  var client = http.Client();
  // Added type String? on the left side and await keyword for the storage.read()
  String? token = await storage.readSecureToken('key');
  if (token == null) {
    throw Exception("No token stored in storage");
  }
  try {
    var response = await client
        .post(
          Uri.https("baseURL", "endpoint"),
          headers: <String, String>{
            'Authorization': 'Token $token',
          },
          body: param,
        )
        .timeout(Duration(seconds: TIME_CONST))
        .catchError(handleError);

    if (response.statusCode == 200) {
      print('Response Body: ${response.body}');
      final data = jsonDecode(response.body);
      return PhoneOTPValidate(
        status: data['success'],
        validate: true,
      );
    } else {
      print("The OTP is not valid");
      return param;
    }
  } on SocketException {
    throw FetchDataException('message', 'url');
  } on TimeoutException {
    throw ApiNotRespondingException("message", "url");
  }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...