How to solve error 401 is not authorized in a Flutter app - flutter

This is the state when logging in to the homepage:
Future<User?> login(String nim, String password) async {
String token = await UtilSharedPreferences.getToken();
SharedPreferences pref = await SharedPreferences.getInstance();
try {
var body = {
'username': nim,
'password': password,
};
var response = await http.post(
Uri.parse('http://dev.api.app.masoemuniversity.ac.id/v1/login_mhs'),
headers: {
'Authorization': 'Bearer $token',
},
body: body,
);
print(response.statusCode);
print(response.body);
if (response.statusCode == 200) {
return User.fromJson(jsonDecode(response.body));
} else {
return null;
}
} catch (e) {
print(e);
return null;
}
}
And this is when I call user data after login
Future<User> getDataMahasiswa() async {
String _token = await UtilSharedPreferences.getToken();
SharedPreferences _pref = await SharedPreferences.getInstance();
final response = await http.get(
Uri.parse(
'http://dev.api.app.masoemuniversity.ac.id/v1/auth/mhs_siakad/biodata'),
headers: {
'Authorization': 'Bearer $_token',
"Content-Type": 'application/json'
},
);
print(response.statusCode);
print(response.body);
if (response.statusCode == 200) {
return User.fromJson(jsonDecode(response.body)['data']);
} else {
throw Exception();
}
}
And this is the response when logging in with code 200 is successful, but when getting user data the response is code 401
I/flutter (15446): 200
I/flutter (15446): {"status":"success","data":{"nim":"20265028","name":"Sukandar","id_role":"f4d4d365-dc99-4fe7-b2b7-5daddf77e127","role":"Mahasiswa","level":7,"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiIxIiwianRpIjoiYzZlNGE3ZmFmZTAzZDYyODdhMDM2NTg4MjNiZmE0MDZjOGI4YWQ1OGQ5MTRjZDkzMzRkYjhmZDQzYjc3MjRmYWFiZDgwY2FiNzYzZjI0YTEiLCJpYXQiOjE2NjU2NDY5MzkuNzc4NTUsIm5iZiI6MTY2NTY0NjkzOS43Nzg1NTQsImV4cCI6MTY5NzE4MjkzOS43Njg5MzQsInN1YiI6ImM4MzljNmNlLTUxZDEtNGZmYS05MmIxLWQwM2FlZTQ5MWNmMSIsInNjb3BlcyI6W119.mfag9cVCgIyojIkPuXXi7-xfnAsbWds5DYRLgSovE6u6NtAI8s3ZMYVQ0X7Bgu6IE_DfNDNSB2lap6_fvv_lx41NCSvegPLcOa57XBy9dIcQOeg-rWo8B0kYnvsG2q_g4UFCx2FEnhVeWKuhyqDfM3kkG2IB3c1rGNkx50A9_uGeofqrTkxlnuTnkRnYjcTuGOEj6laRnkWsE9_HTfu2Q7-Te66ZYqIllc4CH4OaxBwSKgd3qMPrvy8sFenah6mx7RgZ2h9cpiFmTM-bj8WP6lc-DiqSJyvde14vebBNylg6NJKX7dpV7oeRJGlVDuMK4Dqihy4wDNAx4q_vCYQticiRrUwvhuXY9AZnD6IhXbqrwb0bYZE3f6eg1voKltpBiVxx0YSQkIGze_w9ceEDpZsFHWszJ0U7O99mL763kEjnZ4MM60Xyn9YZ5iRCT2uswWtljI0rUrGBgR1QPWJ5oMEOXR4CWfSZ8m7LrPwBGB_JCo8Y9Dyn6fDM-A6YSfrbXW1BlEd7eW6I
I/flutter (15446): 401
I/flutter (15446): Unauthorized.

idk the mechanism auth in your app. may be you can try this.
after success login you got this:
I/flutter (15446): 200
I/flutter (15446): {"status":"success","data":
{"nim":"20265028","name":"Sukandar","id_role":"f4d4d365-dc99-4fe7-b2b7-
5daddf77e127","role":"Mahasiswa","level":7,"access_token":"eyJ0eXAiO.....
see, now you have an access_token. use it for get the data from server
...
final response = await http.get(
// do not use UtilSharedPreferences.getToken();
// because this token use for login, its require username and password in body
Uri.parse(
'http://dev.api.app.masoemuniversity.ac.id/v1/auth/mhs_siakad/biodata'),
headers: {
'Authorization': 'Bearer $access_token',
"Content-Type": 'application/json'
},
);
....

Related

Retrieving data from http web call in flutter into a list object always empty

List is always empty even though body has contents. I am new to flutter so bare with me if this is basic. I am wanting to get back a list of station data I am coming from a c# background so forgive me if am missing something simple the test string body has the items and can see the items when i debug
class HttpService {
final String url = "url hidden";
final String host = 'url hidden';
final String apiSegment = "api/";
// ignore: non_constant_identifier_names
void login(email, password) async {
try {
Map<String, String> body = {
'username': email,
'password': password,
};
Map<String, String> headers = {'Content-Type': 'application/json'};
final msg = jsonEncode(body);
Response response =
await post(Uri.parse("$url/Login"), headers: headers, body: msg);
if (response.statusCode == 200) {
var data = jsonDecode(response.body.toString());
print(data['jwtToken']);
print('Login successfully');
final prefs = await SharedPreferences.getInstance();
await prefs.setString('jwtToken', data['jwtToken']);
List<Stations> stationData = await getStationData('11');
var test = stationData;
} else {
print('failed');
}
} catch (e) {
print(e.toString());
}
}
Future<List<Stations>> getStationData(String stationId) async {
final prefs = await SharedPreferences.getInstance();
final String? token = prefs.getString('jwtToken');
const String path = 'Station/GetAllStationData';
final uri = Uri.parse('$url/api/$path')
.replace(queryParameters: {'stationId': stationId});
List<Stations> stationData = <Stations>[];
try {
Response res = await get(uri, headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
// 'Authorization': 'Bearer $token',
});
if (res.statusCode == 200) {
var body = jsonDecode(res.body);
var body2 = body.toString();
stationData = body
.map(
(dynamic item) => Stations.fromJson(item),
)
.toList();
} else {
throw "Unable to retrieve posts.";
}
} catch (e) {
print(e.toString());
}
return stationData;
}
}
I am calling my function from the same class
List<Stations> stationData = await getStationData('11');
Data from body
Actually the problem is you are returning the data after the end of try catch.
Try this
Future<List<Stations>> getStationData(String stationId) async {
final prefs = await SharedPreferences.getInstance();
final String? token = prefs.getString('jwtToken');
const String path = 'Station/GetAllStationData';
final uri = Uri.parse('$url/api/$path')
.replace(queryParameters: {'stationId': stationId});
try {
Response res = await get(uri, headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
// 'Authorization': 'Bearer $token',
});
if (res.statusCode == 200) {
var body = jsonDecode(res.body);
final stationData = List<Stations>.from(body.map((item) => Stations.fromJson(item))); // made some changes
return stationData;
} else {
throw "Unable to retrieve posts.";
}
} catch (e) {
rethrow;
}
}
I hope this will help you

Can't get auth token stored in flutter secure storage to headers

I am making flutter app using API and I have a problem. When I want to get auth token to make request, flutter says that "Expected a value of type 'String', but got one of type '_Future'". How can I make a request with auth token without that error?
My login function, where I write the token:
loginUser() async {
final storage = new FlutterSecureStorage();
Uri uri = Uri.parse("http://127.0.0.1:8000/api/account/login");
await http
.post(uri,
headers: {"Content-Type": "application/json"},
body: jsonEncode({
"username": emailController.text,
"password": passwordController.text
}))
.then((response) async {
if (response.statusCode == 200) {
var data = json.decode(response.body);
await storage.write(key: "token", value: data["token"]);
print(data["token"]);
} else {
print(json.decode(response.body));
}
});
}
My getdata function, where i use the token:
getdata() async {
final storage = FlutterSecureStorage();
Uri uri = Uri.parse("http://127.0.0.1:8000/api/account/countries");
await http.get(uri, headers: {
"Content-Type": "application/json",
"Authorization": await storage.read(key: "token")
});
}
try this code
String token = await storage.read(key: 'token');
//make sure if there is no Bearer just token in that case just pass the token
var headers = {
'accept': 'application/json',
'Authorization': 'Bearer ${token}',
};
Uri uri = Uri.parse("http://127.0.0.1:8000/api/account/countries");
Response response = await http.get(
uri,
headers: headers
);
print (response);

flutter Unhandled Exception: DioError [DioErrorType.response]: Http status error [422]

I have an API which sends status 201 in case of a success and if there's any error with the submitted data it sends status 422 (Unprocessable Entity) with a JSON response.
{
"message": "The given data was invalid.",
"errors": {
"mobile": [
"The selected mobile is invalid."
]
}}
I am using Dio to post user credentials (mobile, password) if I enter the correct user credential I can fetch data from it but when I enter the wrong credential gives me this error:
Unhandled Exception: DioError [DioErrorType.response]: Http status error [422]
Dio code
userLogin(
String password,
String mobile,
) async {
try {
String url = "url";
Dio dio = Dio();
dio.options.headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
};
var response = await dio.post(url, queryParameters: {
"password": password,
"mobile": mobile,
});
if (response.statusCode == 200) {
return response.data;
} catch (e) {
return e.toString();
}}
How I cloud handle error response and success?
If some of Http status codes in responses are approved then you could use validateStatus function in BaseOptions to make them valid for all dio requests.
Dio dio = Dio(
BaseOptions(
headers: {...},
validateStatus: (statusCode){
if(statusCode == null){
return false;
}
if(statusCode == 422){ // your http status code
return true;
}else{
return statusCode >= 200 && statusCode < 300;
}
},
)
);
or validateStatus function in Options of concrete request
var response = await dio.post(url,
queryParameters: {
"password": password,
"mobile": mobile,
},
options: Options(
responseType: ResponseType.json,
validateStatus: (statusCode){
if(statusCode == null){
return false;
}
if(statusCode == 422){ // your http status code
return true;
}else{
return statusCode >= 200 && statusCode < 300;
}
},
),
);
The catch method has to be added to the try. In your case it was added to if(response.statuscode ==200)
userLogin(
String password,
String mobile,
) async {
try {
String url = "url";
Dio dio = Dio();
dio.options.headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
};
var response = await dio.post(url, queryParameters: json.encode({
"password": password??"",
"mobile": mobile??"",
}));
if (response.statusCode == 200) {
return response.data;
}
else{
print(response.data);
return "request failed";
}
}catch (e) {
return e.toString();
}
My Api response was this enter image description here
I have dealt with this method by allowing it BaseOptions
here is my post API code and bingo got the solution to problem
Future postApiResponse(
String url, dynamic data, bool tokentrue, String? token) async {
dynamic responceJson;
try {
// print('here 222');
if (kDebugMode) {
print('In Dio in try');
print(url);
print(data.toString());
print(tokentrue.toString());
print(token.toString());
print('In Dio in try');
}
Dio dio = Dio(BaseOptions(validateStatus: (statusCode) {
if (statusCode == 422) {
return true;
}
if (statusCode == 200) {
return true;
}
return false;
}));
if (tokentrue == true) {
// dio.options.headers['content-Type'] = 'application/json';
dio.options.headers['Accept'] = 'application/json';
dio.options.headers["authorization"] = "Bearer $token";
} else {
dio.options.headers['Accept'] = 'application/json';
}
// print('responceJson.toString()');
Response responce = await dio
.post(
url,
data: data,
)
.timeout(const Duration(seconds: 20));
debugPrint('.toString()');
responceJson = returnResponce(responce);
debugPrint(responce.toString());
} on DioError catch (e) {
returnExceptionError(e);
}
return responceJson;
}
DioError [DioErrorType.response]: Http status error [422]
The Solution :)
Dio dio = Dio(
BaseOptions(
headers: {...},
validateStatus: (statusCode){
if(statusCode == null){
return false;
}
if(statusCode == 422){ // your http status code
return true;
}else{
return statusCode >= 200 && statusCode < 300;
}
},
)
);

Flutter Laravel Api returns no response

i have a getx controller where i created a register user function, but when i call it from the register ui nothing seems to happen
RxBool isLoading = false.obs;
final Uri uri = Uri.parse(url + 'register');
Future registerUser(name, email, password) async {
try {
// Register user
isLoading.value = true;
final http.Response response = await http.post(
uri,
headers: {
'Content-type': 'application/json',
'Accept': 'application/json',
},
body: jsonEncode({
'name': name,
'email': email,
'password': password,
}),
);
isLoading.value = false;
final res = json.decode(response.body);
if (res['success'] == true) {
print(res);
} else {
print(res);
}
} catch (e) {
print(e);
}
}

I would like to upload a image and profile data in Multipart/Formdata format in flutter when hit a api i got response failed

Here is my post api code i try to upload file (image from image picker)and profilePojo(data like username ,fname, lastname etc.) when i run code i got result failed .
'''
void addData(final profilePojo) async {
SharedPreferences preferences = await SharedPreferences.getInstance();
String token = preferences.getString('token');
FormData formData = FormData.fromMap({
"file": await MultipartFile.fromFile("./text.txt",filename: "upload.txt"),
"profilePojo":profilePojo,//profilePojo means i pass heaar string of data on button click
});
String url =pass here url
http
.post(
url,
headers: {
HttpHeaders.authorizationHeader: 'Bearer $token',
// "Content-Type":"multipart/form-data",
"accept": "application/json",
},
body: formData.toString()
)
.then((response) {
if (response.statusCode == 200) {
var myData = json.decode(response.body);
if(myData['result']=="success"){
setState(() {
print(myData);//print response success
_showDialog();
getData();
});}
else{
print(response.statusCode);
print(myData);
}
} else {
print(response.statusCode);
print("object");
}
});
}
'''
I'm currently using dio for this kind of requests, here is my example:
final futureUploadList = imageList.map((img) async {
print(img.path);
return MultipartFile.fromFile(img.path);
});
final uploadList = await Future.wait(futureUploadList);
FormData data = FormData.fromMap({
"images": uploadList
});
dio.post('/images',
data: data, options: Options(headers: {'Authorization': 'Bearer abcd'}));