尝试从 "Here" REST API 获取令牌时,客户端授权无效 header

Invalid Client Authorization header when trying to get token from "Here" REST API

我正在尝试获取 Bearer 令牌以开始使用 HERE REST API,
使用 (OAuth 2.0 (JSON Web 令牌))
经过很多斗争,我坚持 401202 error:

{"errorId":"ERROR-e0242f30-05da-4df0-9beb-b697062240ce","httpStatus":401,"errorCode":401202,"message":"Invalid Client Authorization header, expecting signed request format.","error":"invalid_request","error_description":"errorCode: '401202'. Invalid Client Authorization header, expecting signed request format."}

这是我的代码:

private void GetToken()
{
   try
    {
        var here_client_id = "b1Ibl7XXXXXXXoZtNKb";
        var here_access_key_id = "8DKjlwXXXXXXXXXerGCXPA";
        var here_access_key_secret = "tuU-bGMa1ljancfoXXXXXXXXXXXXXXXK8cMlk4o0EGUpS2fmwkAtlltFPDhYQUgytJLL-X_YNIjmdWcOabQ";
        var url = "https://account.api.here.com/oauth2/token";

        var Parameters = "grant_type=client_credentials&client_id=" + here_client_id + "&oauth_consumer_key=" + here_access_key_secret;

        var hmac = new HMACSHA256();
        var key = Convert.ToBase64String(hmac.Key);
        Guid id = Guid.NewGuid();

        // Create a request for the URL.        
        WebRequest request = WebRequest.Create(url);

        request.Method = "POST";
        request.ContentType = "application/x-www-form-urlencoded";
        var cred = @"OAuth oauth_consumer_key=" + here_access_key_id;

        request.Headers.Add("Authorization", cred);
        //request.Headers.Add("oauth_consumer_key", here_access_key_id);
        request.Headers.Add("oauth_nonce", id.ToString());
        request.Headers.Add("oauth_signature_method", "HMAC-SHA256");
        request.Headers.Add("oauth_signature", key);
        request.Headers.Add("oauth_timestamp", ConvertToUnixTimestamp(DateTime.Now).ToString());
        request.Headers.Add("oauth_version", "1.0");

        byte[] byteArray = Encoding.UTF8.GetBytes(Parameters);
        request.ContentLength = byteArray.Length;

        Stream postStream = request.GetRequestStream();
        // Add the post data to the web request
        postStream.Write(byteArray, 0, byteArray.Length);
        postStream.Close();

        // Get the response.
        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
        // Display the status.
        Console.WriteLine(response.StatusDescription);
        // Get the stream containing content returned by the server.
        Stream dataStream = response.GetResponseStream();
        // Open the stream using a StreamReader for easy access.
        StreamReader reader = new StreamReader(dataStream);
        // Read the content.
        string responseFromServer = reader.ReadToEnd();
        // Display the content.
        MessageBox.Show(responseFromServer);
        // Cleanup the streams and the response.
        reader.Close();
        dataStream.Close();
        response.Close();
    }
    catch (WebException ex)
    {
        using (var stream = ex.Response.GetResponseStream())
        using (var reader = new StreamReader(stream))
        {
           //MessageBox.Show(reader.ReadToEnd());
            textBox1.Text = reader.ReadToEnd();
        }
    }
}

最后我在没有网络的情况下做到了JSON WEB TOKENS。
根据此 API documentation 调用仅使用 API KEY。

public static string ConvertAddressToCoordinate(string address)
{
    try
    {
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;

        var apikey = "xxxxxxxxxxxxxxxxxxxxx_xxxxxxxxx";
        var url = "https://geocoder.ls.hereapi.com/6.2/geocode.json?apiKey=";
        var fullurl = url + apikey + "&searchtext=" + address;
        // Create a request for the URL.        
        WebRequest request = WebRequest.Create(fullurl);
        request.Method = "GET";
        request.ContentType = "application/json";
        // Get the response.
        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
        // Display the status.
        Console.WriteLine(response.StatusDescription);
        // Get the stream containing content returned by the server.
        Stream dataStream = response.GetResponseStream();
        // Open the stream using a StreamReader for easy access.
        StreamReader reader = new StreamReader(dataStream);
        // Read the content.
        string responseFromServer = reader.ReadToEnd();
        // Display the content.
        return responseFromServer;
    }
    catch (WebException ex)
    {
        return "ERROR " + ex.Message;
    }
    catch (Exception ex)
    {
        return "ERROR " + ex.Message;
    }
}

这是我第一次剪,很粗糙。

var accessKey = "";
    var secret = "";
    var url = "https://account.api.here.com/oauth2/token";
    var nonce = GetNonce();
    var timestamp = GetTimeStamp();
    var baseString = @"grant_type=client_credentials&oauth_consumer_key=" + accessKey + "&oauth_nonce=" + nonce + "&oauth_signature_method=HMAC-SHA256&oauth_timestamp=" + timestamp + "&oauth_version=1.0";

    var workingString = new List<string>();
    foreach (var parameter in baseString.Split('&').ToList())
    {
        workingString.Add(Uri.EscapeDataString(parameter.Split('=')[0] + "=" + parameter.Split('=')[1].Trim()));
    }
    var urlEncodeParamaterString = String.Join(Uri.EscapeDataString("&"), workingString.ToArray());
    var fullBaseString = $"POST&{Uri.EscapeDataString(url)}&{urlEncodeParamaterString}";

    var signature = CreateToken(fullBaseString, (Uri.EscapeDataString(secret) + "&"));

    var authHeader = "OAuth oauth_consumer_key=\"" + accessKey + "\",oauth_signature_method=\"HMAC-SHA256\",oauth_timestamp=\"" + timestamp + "\",oauth_nonce=\"" + nonce + "\",oauth_version=\"1.0\",oauth_signature=\"" + Uri.EscapeDataString(signature) + "\"";



    using (HttpClient httpClient = new HttpClient())
    {
        httpClient.DefaultRequestHeaders.Add("Authorization", authHeader);
        var response = await httpClient.PostAsync(url, new StringContent($"grant_type={Uri.EscapeDataString("client_credentials")}",
                                                        Encoding.UTF8,
                                                        "application/x-www-form-urlencoded"));
        var responseContent = response.Content.ReadAsStringAsync();
    }

其他方法是

 private string GetNonce()
    {
        var rand = new Random();
        var nonce = rand.Next(1000000000);
        return nonce.ToString();
    }
    private string CreateToken(string message, string secret)
    {
        secret = secret ?? "";
        var encoding = new System.Text.ASCIIEncoding();
        byte[] keyByte = encoding.GetBytes(secret);
        byte[] messageBytes = encoding.GetBytes(message);
        using (var hmacsha256 = new HMACSHA256(keyByte))
        {
            byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
            return Convert.ToBase64String(hashmessage);
        }
    }
    private string GetTimeStamp()
    {
        var ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
        return Convert.ToInt64(ts.TotalSeconds).ToString();
    }