I'd like to integrate SUUNTO API into a Flutter application. I'm registered to the SUUNTO API Zone, I have my Client ID, API key, secret. I'm only in Developer subscription since I'm testing out the water. I can an authorization code with ease (step 4.4 at https://apizone.suunto.com/how-to-start) but then always slapped with a 401 Unauthorized when I try to use that code to obtain the JWT token (step 4.5).
This is actually mentioned in their FAQ https://apizone.suunto.com/faq, but I'm already using the Basic authentication as advised with my Client ID and secret.
const REDIRECT_URL = "suuntoflutter://redirect/";
Future<SuuntoToken> _getSuuntoToken(
String clientId,
String secret,
String code,
) async {
final encodedRedirectUrl = Uri.encodeQueryComponent(REDIRECT_URL);
final params = "?grant_type=authorization_code&code=$code&redirect_uri=$encodedRedirectUrl";
final tokenRequestUrl = "https://cloudapi-oauth.suunto.com/oauth/token" + params;
final base64String = base64.encode(utf8.encode("$clientId:$secret"));
final tokenResponse = await http.post(Uri.parse(tokenRequestUrl), headers: {"Authorization": "Basic: $base64String"});
The reason I'm posting this because I wrote to SUUNTO but haven't got any response and I hope maybe someone can help here. Each fitness portal has some variations over the OAuth2, I have the Strava integration and Under Armour integration fully working now.
What I've tried with SUUNTO:
grant_type
, code
, and redirect_uri
parameters as form submission in the body instead of URL parameters. Some OAuth2 integrations do it that way. This didn't change anything.I ran out of ideas.
I went back to the beginning and was able to get a JWT token with the SUUNTO doc example curl
command curl -v https://cloudapi-oauth.suunto.com/oauth/token --user <client id>:<client secret> -d grant_type=authorization_code -d redirect_uri=<redirect URI> -d code=<authorization code from step 4.4>
.
After that I went through a lot of variations again (sending the parameters form encoded or in the URL etc.) until I realized that it was just one rogue extra character in the Basic authentication header string interpolation: and extra unintended colon:
"Basic $base64String"
vs "Basic: $base64String"
. That extra colon was the problem.