skip to Main Content

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


  1. The problem in your code is ";" It looks like.

    You should update the ‘headers’ section as follows:

     headers: {
        HttpHeaders.authorizationHeader:
            "Basic ${base64.encode(utf8.encode('$clientId:$clientSecret'))}"
      },
    

    Additionally, the "scope" value must be "basic"

    Login or Signup to reply.
  2. 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.

    Future<FatSecretToken> getToken() async {
        final String basicAuth =
            'Basic ' + base64Encode(utf8.encode('$clientId:$clientSecret'));
    
        final Map<String, String> headers = {
          'Authorization': basicAuth,
          // 'Content-Type': 'application/x-www-form-urlencoded',
        };
    
        final Map<String, String> body = {
          'grant_type': 'client_credentials',
          'scope': 'premier barcode',
        };
    
        final response = await http.post(
          Uri.parse('https://oauth.fatsecret.com/connect/token'),
          headers: headers,
          body: body,
        );
    
        if (response.statusCode == 200) {
          var object = FatSecretToken.fromJson(
              jsonDecode(response.body) as Map<String, dynamic>);
          return object;
        } else {
          throw Exception('Failed to get token: ${response.reasonPhrase}');
        }
      }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search