Hi team, I am trying to use flutter to make a API call with OAuth1, but there is an error in making the request token, error message as below,
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Connection failed
#0 IOClient.send (package:http/src/io_client.dart:94:7)
<asynchronous suspension>
#1 BaseClient._sendUnstreamed (package:http/src/base_client.dart:93:32)
<asynchronous suspension>
#2 Authorization.requestTemporaryCredentials (package:oauth1/src/authorization.dart:48:31)
<asynchronous suspension>
#3 FatSecretAPI.authenticate (package:fatsecret_app_829/fatsecret_api.dart:38:34)
<asynchronous suspension>
#4 _FatSecretHomePageState.build.<anonymous closure> (package:fatsecret_app_829/main.dart:41:17)
<asynchronous suspension>
########################
attaching the main.dart and fatsecret_api.dart as below. Any insight how to get it right?
Thanks.
------------------------
main.dart
-------
import 'package:flutter/material.dart';
import 'fatsecret_api.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'FatSecret API OAuth1 Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: FatSecretHomePage(),
);
}
}
class FatSecretHomePage extends StatefulWidget {
@override
_FatSecretHomePageState createState() => _FatSecretHomePageState();
}
class _FatSecretHomePageState extends State<FatSecretHomePage> {
final FatSecretAPI _fatSecretAPI = FatSecretAPI();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('FatSecret API OAuth1 Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: () async {
await _fatSecretAPI.authenticate(context);
},
child: Text('Authenticate with FatSecret'),
),
ElevatedButton(
onPressed: () async {
// Example parameters for a POST request to FatSecret API
Map<String, String> parameters = {
'method': 'foods.search',
'search_expression': 'apple',
'format': 'json',
};
await _fatSecretAPI.makeAuthenticatedPostRequest('', parameters);
},
child: Text('Search Food'),
),
],
),
),
);
}
}
fatsecret_api.dart
----
import 'package:oauth1/oauth1.dart' as oauth1;
import 'package:http/http.dart' as http;
import 'package:url_launcher/url_launcher.dart';
import 'dart:convert';
import 'package:flutter/material.dart';
class FatSecretAPI {
final String _consumerKey = 'XX'; // Replace with your Consumer Key
final String _consumerSecret = 'XX'; // Replace with your Consumer Secret
oauth1.Client? _client;
Future<void> authenticate(BuildContext context) async {
print('#### authenticate step');
// Set up OAuth1.0a credentials
final platform = oauth1.Platform(
'https://www.fatsecret.com/oauth/request_token',
'https://www.fatsecret.com/oauth/access_token',
'https://www.fatsecret.com/oauth/authorize',
oauth1.SignatureMethods.hmacSha1,
);
final clientCredentials = oauth1.ClientCredentials(_consumerKey, _consumerSecret);
print('#### clientcredentials');
// Step 1: Get request token
final auth = oauth1.Authorization(clientCredentials, platform);
print('#### auth');
//final requestTokenResponse = await auth.requestTemporaryCredentials('oob');
//try {
// final requestTokenResponse = await auth.requestTemporaryCredentials('oob');
// Handle successful response
//} catch (e) {
// print('Error requesting temporary credentials: $e');
//}
final requestTokenResponse = await auth.requestTemporaryCredentials('oob');
print('#### request token response');
final requestToken = requestTokenResponse.credentials.token;
print('#### request token');
// Step 2: Redirect user to authorization URL in the browser
final authorizationUrl = auth.getResourceOwnerAuthorizationURI(requestToken);
print('#### url');
if (await canLaunch(authorizationUrl)) {
print('launching');
await launch(authorizationUrl);
print('launched');
} else {
throw 'Could not launch $authorizationUrl';
print('Could not launch $authorizationUrl');
}
// Step 3: Ask the user to input the verifier code
String verifier = await _showVerifierInputDialog(context);
// Step 4: Get access token
final tokenCredentialsResponse = await auth.requestTokenCredentials(
oauth1.Credentials(requestToken, requestTokenResponse.credentials.tokenSecret),
verifier,
);
_client = oauth1.Client(
platform.signatureMethod,
clientCredentials,
tokenCredentialsResponse.credentials,
);
print('Authentication successful. Access token obtained.');
}
Future<void> makeAuthenticatedPostRequest(String endpoint, Map<String, String> parameters) async {
if (_client == null) {
print('Client is not authenticated. Please authenticate first.');
return;
}
final url = Uri.parse('https://platform.fatsecret.com/rest/server.api' + endpoint);
// OAuth1.0a automatically handles the signing
final response = await _client!.post(url, body: parameters);
if (response.statusCode == 200) {
print('Response data: ${response.body}');
} else {
print('Request failed with status: ${response.statusCode}');
}
}
Future<String> _showVerifierInputDialog(BuildContext context) async {
TextEditingController verifierController = TextEditingController();
return showDialog<String>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Enter Verifier Code'),
content: TextField(
controller: verifierController,
decoration: InputDecoration(hintText: "Enter verifier code here"),
),
actions: <Widget>[
ElevatedButton(
onPressed: () {
Navigator.of(context).pop(verifierController.text);
},
child: Text('Submit'),
),
],
);
},
).then((value) => value ?? '');
}
}