I am currently trying to implement an API request with flutter. I have implemented the resuest in Postman and tried all the data. The result was successful. Then I tried to implement this request in my programme. However, I have a problem here, which is why I always get the ResponseCode 400. However, I can no longer explain why. I am using the FatSecret API here.
The code I used for this request requires an Authorisation Header according to the documentation. This consists of the clientID and the clientSecret. The body also contains "grant_type": "client_credentials" and "scope": "premier".
class FatSecretAPI extends ConsumerWidget {
const FatSecretAPI({super.key});
final String clientId = "...";
final String clientSecret = "...";
Future<FatSecretToken> fetchAccesToken() async {
final response = await http
.post(Uri.parse("https://oauth.fatsecret.com/connect/token"),
body: {
"grant_type": "client_credentials",
"scope": "premier"
}, headers: {
HttpHeaders.authorizationHeader: "Basic ${base64.encode(utf8.encode('$clientId:$clientSecret'))};"
});
if (response.statusCode == 200) {
var object = FatSecretToken.fromJson(
jsonDecode(response.body) as Map<String, dynamic>);
print(object.accessToken);
return object;
} else {
print(response.statusCode);
throw Exception("Failed to load token");
}
}
Future<void> loadToken(WidgetRef ref) async {
final token = await fetchAccesToken();
ref.read(accesTokenProvider.notifier).state = token.accessToken;
}
}
class FatSecretToken {
final String accessToken;
final String tokenType;
final int expiresIn;
FatSecretToken(
{required this.accessToken,
required this.tokenType,
required this.expiresIn});
factory FatSecretToken.fromJson(Map<String, dynamic> json) {
return FatSecretToken(
accessToken: json['access_token'],
tokenType: json['token_type'],
expiresIn: json['expires_in'],
);
}
}
A response in Json format should actually appear here, which contains information about the accesToken and the token type.
2
Answers
The problem in your code is ";" It looks like.
You should update the ‘headers’ section as follows:
Additionally, the "scope" value must be "basic"
I have reproduced the whole thing and this is how it works. Probably because of the ; in the auth header. This way it is also more readable and easily customisable for other purposes. You should also outsource the secrets so that they are more secure.