Dart OAuth 1.0 - Invalid signature - provided signature does not match

1,093

So I abandoned the Woocommerce package to create a function that parses the url with new parameters for oauth 1.0 authentication

import 'dart:collection';
import 'dart:math';
import 'package:crypto/crypto.dart' as crypto;
import 'package:http/http.dart' as http;
import 'dart:convert';

/// This Generates a valid OAuth 1.0 URL
///
/// if [isHttps] is true we just return the URL with
/// [consumerKey] and [consumerSecret] as query parameters
String _getOAuthURL(String requestMethod, String queryUrl) {
      String consumerKey = cKey;
      String consumerSecret = cSecret;

    String token = "";
    String url = queryUrl;
    bool containsQueryParams = url.contains("?");

    Random rand = Random();
    List<int> codeUnits = List.generate(10, (index) {
      return rand.nextInt(26) + 97;
    });

    /// Random string uniquely generated to identify each signed request
    String nonce = String.fromCharCodes(codeUnits);

    /// The timestamp allows the Service Provider to only keep nonce values for a limited time
    int timestamp = DateTime.now().millisecondsSinceEpoch ~/ 1000;

    String parameters = "oauth_consumer_key=" +
        consumerKey +
        "&oauth_nonce=" +
        nonce +
        "&oauth_signature_method=HMAC-SHA1&oauth_timestamp=" +
        timestamp.toString() +
        "&oauth_token=" +
        token +
        "&oauth_version=1.0&";

    if (containsQueryParams == true) {
      parameters = parameters + url.split("?")[1];
    } else {
      parameters = parameters.substring(0, parameters.length - 1);
    }

    Map<dynamic, dynamic> params = QueryString.parse(parameters);
    Map<dynamic, dynamic> treeMap = new SplayTreeMap<dynamic, dynamic>();
    treeMap.addAll(params);

    String parameterString = "";

    for (var key in treeMap.keys) {
      parameterString = parameterString +
          Uri.encodeQueryComponent(key) +
          "=" +
          treeMap[key] +
          "&";
    }

    parameterString = parameterString.substring(0, parameterString.length - 1);

    String method = requestMethod;
    String baseString = method +
        "&" +
        Uri.encodeQueryComponent(
            containsQueryParams == true ? url.split("?")[0] : url) +
        "&" +
        Uri.encodeQueryComponent(parameterString);

    String signingKey = consumerSecret + "&" + token;
    crypto.Hmac hmacSha1 =
        crypto.Hmac(crypto.sha1, utf8.encode(signingKey)); // HMAC-SHA1

    /// The Signature is used by the server to verify the
    /// authenticity of the request and prevent unauthorized access.
    /// Here we use HMAC-SHA1 method.
    crypto.Digest signature = hmacSha1.convert(utf8.encode(baseString));

    String finalSignature = base64Encode(signature.bytes);

    String requestUrl = "";

    if (containsQueryParams == true) {
      requestUrl = url.split("?")[0] +
          "?" +
          parameterString +
          "&oauth_signature=" +
          Uri.encodeQueryComponent(finalSignature);
    } else {
      requestUrl = url +
          "?" +
          parameterString +
          "&oauth_signature=" +
          Uri.encodeQueryComponent(finalSignature);
    }

    return requestUrl;
  }

With this function above I am able to make requests in an asynchronous function as seen below:

Future fetchWooProducts() async {
    http.Response response = await http.get(_getOAuthURL("GET", '$productsUrl'),
         headers: {"Content-Type": "Application/json"});//using JWT token for WP authentication is not needed
    print(response.body);
}

Share:
1,093
Achin
Author by

Achin

#SOreadytohelp

Updated on December 22, 2022

Comments

  • Achin
    Achin over 1 year

    I am calling an api with OAuth 1.0 and i am using the below package for the api call. But I am getting the below error. Please anyone guide me to fix this error.

    Library for api call:

    https://github.com/nbspou/dart-oauth1

    My Code:

    const String apiKey = 'ck_789b63aee985c4569bfa5ae4724861ae5c74c337';
      const String apiSecret = 'cs_0f0addbc9c16042d5689a4cfe6fbfd209b00d55b';
      var clientCredentials = new oauth1.ClientCredentials(Uri.encodeComponent(apiKey), Uri.encodeComponent(apiSecret));
    
      // create Authorization object with client credentials and platform definition
      //var auth = new oauth1.Authorization(clientCredentials, platform);
      var auth = new oauth1.Credentials(apiKey, apiSecret);
      // yeah, you got token credentials
      // create Client object
      var client = new oauth1.Client(platform.signatureMethod, clientCredentials, auth);
    
      // now you can access to protected resources via client
      client.get('http://demo2.signitydemo.in/foodemporium/wp-json/wc/v3/products/categories').then((res) {
        print("res.body===${res.body}");
        print("statusCode===${res.statusCode}");
        print("headers===${res.headers}");
    
      });
    
    
    
    
    {"code":"woocommerce_rest_authentication_error","message":"Invalid signature - provided signature does not match.","data":{"status":401}}
    

    Headers:

    {link: <http://demo2.signitydemo.in/foodemporium/wp-json/>; rel="https://api.w.org/", access-control-allow-headers: Authorization, Content-Type, connection: keep-alive, date: Fri, 03 Jul 2020 05:32:04 GMT, transfer-encoding: chunked, vary: Origin, access-control-expose-headers: X-WP-Total, X-WP-TotalPages, x-robots-tag: noindex, content-type: application/json; charset=UTF-8, x-content-type-options: nosniff, server: nginx}
    

    I have tested the API in Postman. It is working fine, I am getting the response. Please see the below postman API request. enter image description here

  • Aashutosh
    Aashutosh over 2 years
    thanks a lot, it worked!