I am starting flutter mobile development and have problem with http package http calls. I already have working API written in .NET with included Micorosft Identity. My goal is to create flutter mobile app that gets data from that API with authorizauion. I have problems implementing username-password authorization to get Token from API. Same API call works on Postman and in my existing Xamarin Forms App. Same problem with http call where in its header I use token which I get from Postman. Using VS Code, all packages installed, can retrive sample data from openweathermap.org in same flutter app. My code is:
Recive Bearer Token from API:
Future<String> authorization(String username, String password) async {
Uri uri = Uri.parse('https://myapi/token');
var request = http.MultipartRequest('POST', uri);
request.fields.addAll({
'grant_type': 'password',
'username': username,
'password': password,
});
http.StreamedResponse response = await request.send();
if (response.statusCode == 200) {
Map<String, dynamic> auth =
jsonDecode(await response.stream.bytesToString());
return auth['access_token'];
} else {
return "";
}
}
GET Cars Data from API:
Future<String> getCars() async {
Uri uri = Uri.parse('https://myapi/api/getcars');
var token =
'WorkingToken';
http.Response response = await http.get(uri, headers: {
"Content-Type": "application/json; charset=UTF-8",
"Authorization": "Bearer $token",
});
return response.body;
}
Microsoft Identity Authorization request expects application/x-www-form-urlencoded content.
Future<String> authorization(String username, String password) async {
final response = await http.post(
Uri.parse('https:/host/path/token'),
headers: <String, String>{
'Content-Type': 'application/x-www-form-urlencoded',
},
body: <String, String>{
'grant_type': 'password',
'username': username,
'password': password,
},
encoding: Encoding.getByName('utf-8')
);
if (response.statusCode == 200) {
return jsonDecode(response.body)['access_token'];
} else {
throw Exception(response.reasonPhrase);
}
}
Your question is very general and your problem depends on your response data. Of course, I did not realize that you have a problem receiving the token or using the token as a header for another api!
But since you are just starting to use Flutter, I suggest you to use the Chopper Library to work with HTTP services and api.
It's very simple and fase.
Related
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);
I'm facing some issues in Flutter REST API using with JWT token
Here the header authentication was not passing properly. But it working good in Postman
**Example Code:**
String url = "project URL";
String token = "generated jwt token";
var headers = {
'Authorization': token,
'Cookie': 'ci_session=u17u9effeqk5fdhl1eqdh4jsmu3o3v29'
};
var request = http.Request('GET', Uri.parse(url));
request.headers.addAll(headers);
http.StreamedResponse response = await request.send();
if (response.statusCode == 200) {
print(await response.stream.bytesToString());
}
else {
print(response.reasonPhrase);
}
If I try without the JWT token by removing it in the backend it's working properly. But I need to work with JWT.
Can anyone please help to fix this issue?
I use dio package to work with the same...
// Import dio package
Future<void> function() async {
Dio dio = new Dio();
String url = 'example.com';
try {
final response = await dio.post(
url,
options: Options(
headers: {'Authorization': 'Bearer $userToken'}, //This is where you define your header and provide jwt token
),
);
} on DioError catch (error) {
if (error.response!.statusCode == 401) {
print(error.response.toString());
throw Error();
}
print(error);
throw Error();
}
}
}
The package can be found here https://pub.dev/packages/dio
Feel free to clear up any confusions
The most likely issue here is the value that you give in your header.
For Bearer tokens, the value given in the Authorization header must be Bearer followed by the value of your token. If you did not implement some specific/homemade authorisation function in your backend, this must be what is expected to be received.
Try replacing 'Authorization': token, by
'Authorization': `Bearer $token`,
and it shouldd work as intended.
Future<String> loginUser(User user) async {
var body = jsonEncode({
'strlogin': user.email,
});
Response response = await post(SeguriSignAPIURL.loginUser,
headers: headers,
body: body);
if (response.statusCode == 200) {
var decode = jsonDecode(response.body);
return decode['token'];
} else {
print(response.reasonPhrase);
return '';
}
Hey! When I make this Post call on Postman I get a result, however when I run this code on flutter I get a 400 error. My headers:
final headers = {
'Content-Type': 'application/json; charset=UTF-8',
"Accept": "application/json",
};
Postman:
In Postman you do the request using form-data, but in your Flutter code, you pass json-encoded body.
You either need to use form-data in Flutter or update your server code to accept json content type.
I need to upload an image with caption and username to API that is built using Django. Create Post view in Django is marked with #permission_classes((IsAuthenticated,)). This is the code:
#permission_classes((IsAuthenticated,))
class PostCreateAPIView(CreateAPIView):
serializer_class = PostSerializer
def get_queryset(self):
return Post.objects.all()
Serializer:
class PostSerializer(ModelSerializer):
class Meta:
model = Post
fields = ('author', 'description', 'image', 'created_at')
I did some research and found that since only authenticated users can post image I need to somehow use the token which users receive on login.
I am getting the user token when I login and have been able to save it locally using hive. However I have no idea what to do next.
static Future<dynamic> loginUser(String username, String password) async {
final response = await http.post("$apiURL/en/api/users/login/", body: {
"username": username,
"password": password,
});
return response?.body;
}
This is my login code and it returns json format with username, user_id and token. Smth like this:
{
"token": "dc9e0de8fa2eaa917657e810db06aad2458e4f65",
"user_id": 4,
"username": "maria"
}
Merging my suggestion given in comments.
Write this to add headers with authentication token and files both at the same time :
upload(File imageFile, String token) async {
// open a bytestream
var stream = new http.ByteStream(DelegatingStream.typed(imageFile.openRead()));
// get file length
var length = await imageFile.length();
// string to uri
var uri = Uri.parse("http://ip:8082/composer/predict");
// create multipart request
var request = new http.MultipartRequest("POST", uri);
// add headers with Auth token
Map<String, String> headers = { "Authorization": "Token $token"};
request.headers.addAll(headers);
// multipart that takes file
var multipartFile = new http.MultipartFile('file', stream, length,
filename: basename(imageFile.path));
// add file to multipart
request.files.add(multipartFile);
// send
var response = await request.send();
print(response.statusCode);
// listen for response
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});
}
What you probably want to do is to pass the token inside the request header. Something like this should work:
static Future<dynamic> loginUser(String username, String password) async {
final response = await http.post(
"$apiURL/en/api/users/login/",
body: {
"username": username,
"password": password,
},
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Token $token',
},
);
return response?.body;
}
Note that the headers contains a field named Authorization, this is the place where you pass your the token. The keyword Token inside the string containing the token specifies the kind of authentication you are using. If it doesn't work, maybe you are using another kind of Authorization.
I recommend you take a look at https://www.django-rest-framework.org/api-guide/authentication/
I am in the learning proess for both flutter and requests so forgive me if it is a simple mistake. I am trying to make a client login to a mediaiwki instance using client login api. I can fetch the login token succesfully but when I try to login it says invalid csrf token it gives {"error":{"code":"badtoken","info":"Invalid CSRF token.","*":". The api I am using to login is as follows.
https://www.mediawiki.org/wiki/API:Login#Method_2._clientlogin
Thanks for your help.
To fetch login token succesfully I use
_fetch_login_token() async {
Map<String, String> headers = {"Content-type": "application/json"};
Map<String, String> body = {
'action': "query",
'meta': "tokens",
'type': "login",
'format': "json"
};
Response response = await post(
url,
body: body,
);
//print(response);
// int statusCode = response.statusCode;
// print(statusCode);
var decoded = jsonDecode(response.body);
print(decoded);
var jsonsData = response.body; // toString of Response's body is assigned to jsonDataString
var data = jsonDecode(jsonsData);
var token=data['query']['tokens']['logintoken'];
return _makePostRequest(token);
}
And my failed login as follows
Map<String, String> body = {
'action': "clientlogin",
'username': username,
'password': password,
'loginreturnurl': url,
'logintoken': loginToken,
'format': "json"
};
Response response = await post(
url,
body:body,
);
I solved the problem.For future reference, I have downloaded dio package and added intercepter and cookie manager in order to persist the cookies.