Reputation: 11
I'm trying to use the Large-Scale Matrix API to run some queries using Python 3.7.7. I believe I've successfully created an access token, yet my requests to the API state that my token is missing.
My code to generate the tokens is drawn entirely from the documentation here (a few print statements added), while querying the API uses the syntax shown on this page.
import time #To generate the OAuth timestamp
import urllib.parse #To URLencode the parameter string
import hmac #To implement HMAC algorithm
import hashlib #To generate SHA256 digest
from base64 import b64encode #To encode binary data into Base64
import binascii #To convert data into ASCII
import requests #To make HTTP requests
grant_type = 'client_credentials'
oauth_consumer_key =
oauth_nonce = str(int(time.time()*1000))
oauth_signature_method = 'HMAC-SHA256'
oauth_timestamp = str(int(time.time()))
oauth_version = '1.0'
def create_parameter_string(grant_type, oauth_consumer_key,oauth_nonce,oauth_signature_method,oauth_timestamp,oauth_version):
parameter_string = ''
parameter_string = parameter_string + 'grant_type=' + grant_type
parameter_string = parameter_string + '&oauth_consumer_key=' + oauth_consumer_key
parameter_string = parameter_string + '&oauth_nonce=' + oauth_nonce
parameter_string = parameter_string + '&oauth_signature_method=' + oauth_signature_method
parameter_string = parameter_string + '&oauth_timestamp=' + oauth_timestamp
parameter_string = parameter_string + '&oauth_version=' + oauth_version
return parameter_string
parameter_string = create_parameter_string(grant_type, oauth_consumer_key,oauth_nonce,oauth_signature_method,oauth_timestamp,oauth_version)
encoded_parameter_string = urllib.parse.quote(parameter_string, safe='')
url = 'https://account.api.here.com/oauth2/token'
encoded_base_string = 'POST' + '&' + urllib.parse.quote(url, safe='')
encoded_base_string = encoded_base_string + '&' + encoded_parameter_string
access_key_secret =
signing_key = access_key_secret + '&'
def create_signature(secret_key, signature_base_string):
encoded_string = signature_base_string.encode()
encoded_key = secret_key.encode()
temp = hmac.new(encoded_key, encoded_string, hashlib.sha256).hexdigest()
byte_array = b64encode(binascii.unhexlify(temp))
return byte_array.decode()
oauth_signature = create_signature(signing_key, encoded_base_string)
encoded_oauth_signature = urllib.parse.quote(oauth_signature, safe='')
body = {'grant_type' : '{}'.format(grant_type)}
headers = {
'Content-Type' : 'application/x-www-form-urlencoded',
'Authorization' : 'OAuth oauth_consumer_key="{0}",oauth_nonce="{1}",oauth_signature="{2}",oauth_signature_method="HMAC-SHA256",oauth_timestamp="{3}",oauth_version="1.0"'.format(oauth_consumer_key,oauth_nonce,encoded_oauth_signature,oauth_timestamp)
}
response = requests.post(url, data=body, headers=headers)
print(eval(response.text))
access_token = eval(response.text)['access_token']
url = 'https://largescalematrix.router.hereapi.com/v1/matrix'
body = {
"origins": [{"lat": 0.0, "lng": 0.0}, {"lat": 0.1, "lng": 0.1}],
# "destinations": [...], // if omitted same as origins
"regionDefinition": {
"type": "circle",
"center": {"lat": 0.0, "lng": 0.0},
"radius": 10000
}
}
headers = {
'Authorization' : 'Bearer="{0}"'.format(access_token),
'Content-Type' : 'application/json'
}
response = requests.post(url, data=body, headers=headers)
print(eval(response.text))
In the above code, the (unfilled) fields of oauth_consumer_key
and access_key_secret
are filled with the key and secret key, respectively, generated from Projects>REST>OAuth 2.0 (JSON Web Tokens).
When I run this code, the token successfully generates -- I get a response of the form
{'access_token': [long string], 'token_type': 'bearer', 'expires_in': 86399}
However, when I then attempt to query the API, I get a 401 error with the following message:
{'error': 'Unauthorized', 'error_description': 'Token or apiKey is missing.'}
I think my error's of one of the two forms:
Upvotes: 1
Views: 208
Reputation: 11
Thanks Paolo for your post, it really helped me. I followed the links to the page you posted for the python example to get the token, and by copy pasting that code I could also get the token. However I also failed in the same way you did, I was getting 401: Unauthorized.
The key for me was this page, under "Authentication Token".
curl https://weather.ls.hereapi.com/weather/1.0/report.json
?product=observation
&name=Berlin
-H "Authorization: Bearer {YOUR_TOKEN}"
This last bit, "Bearer (TOKEN)" was the missing bit I needed to make it work. Finally, here is my code:
import time #To generate the OAuth timestamp
import urllib.parse #To URLencode the parameter string
import hmac #To implement HMAC algorithm
import hashlib #To generate SHA256 digest
from base64 import b64encode #To encode binary data into Base64
import binascii #To convert data into ASCII
import requests #To make HTTP requests
import json
grant_type = 'client_credentials'
oauth_consumer_key = 'HERE.ACCESS.KEY.ID' #From credentials.properties file
oauth_nonce = str(int(time.time()*1000))
oauth_signature_method = 'HMAC-SHA256'
oauth_timestamp = str(int(time.time()))
oauth_version = '1.0'
def create_parameter_string(grant_type, oauth_consumer_key,oauth_nonce,oauth_signature_method,oauth_timestamp,oauth_version):
parameter_string = ''
parameter_string = parameter_string + 'grant_type=' + grant_type
parameter_string = parameter_string + '&oauth_consumer_key=' + oauth_consumer_key
parameter_string = parameter_string + '&oauth_nonce=' + oauth_nonce
parameter_string = parameter_string + '&oauth_signature_method=' + oauth_signature_method
parameter_string = parameter_string + '&oauth_timestamp=' + oauth_timestamp
parameter_string = parameter_string + '&oauth_version=' + oauth_version
return parameter_string
parameter_string = create_parameter_string(grant_type, oauth_consumer_key,oauth_nonce,oauth_signature_method,oauth_timestamp,oauth_version)
encoded_parameter_string = urllib.parse.quote(parameter_string, safe='')
url = 'https://account.api.here.com/oauth2/token'
encoded_base_string = 'POST' + '&' + urllib.parse.quote(url, safe='')
encoded_base_string = encoded_base_string + '&' + encoded_parameter_string
access_key_secret = 'HERE.ACCESS.KEY.SECRET'#From credentials.properties file
signing_key = access_key_secret + '&'
def create_signature(secret_key, signature_base_string):
encoded_string = signature_base_string.encode()
encoded_key = secret_key.encode()
temp = hmac.new(encoded_key, encoded_string, hashlib.sha256).hexdigest()
byte_array = b64encode(binascii.unhexlify(temp))
return byte_array.decode()
oauth_signature = create_signature(signing_key, encoded_base_string)
encoded_oauth_signature = urllib.parse.quote(oauth_signature, safe='')
body = {'grant_type' : '{}'.format(grant_type)}
headers = {
'Content-Type' : 'application/x-www-form-urlencoded',
'Authorization' : 'OAuth oauth_consumer_key="{0}",oauth_nonce="{1}",oauth_signature="{2}",oauth_signature_method="HMAC-SHA256",oauth_timestamp="{3}",oauth_version="1.0"'.format(oauth_consumer_key,oauth_nonce,encoded_oauth_signature,oauth_timestamp)
}
response = requests.post(url, data=body, headers=headers)
r_obj = json.loads(response.text)
token = r_obj['access_token']
print(response.text)
payload = {'name': 'Chicago', 'product': 'forecast_7days_simple'}
r = requests.get('https://weather.ls.hereapi.com/weather/1.0/report.json', params=payload, headers={'Authorization': 'Bearer '+token})
print(r.status_code)
r.encoding = r.apparent_encoding
obj = json.loads(r.text)
print(obj['dailyForecasts'])
Upvotes: 1
Reputation:
Try using following code snippet to generate the token.
import CryptoJS from 'crypto-js';
import axios from 'axios';
export const getToken = (app_key, app_secret) => {
let url = "https://account.api.here.com/oauth2/token";
let key = app_key;
console.log(key);
let secret = app_secret;
console.log(secret);
let nonce = btoa(Math.random().toString(36)).substring(2, 13);
let timestamp = Math.floor(Date.now()/1000);
let normalizedUrl = encodeURIComponent(url);
console.log(normalizedUrl);
let signing_method = "HMAC-SHA256";
let sig_string = "oauth_consumer_key="
.concat(key)
.concat("&oauth_nonce=")
.concat(nonce)
.concat("&oauth_signature_method=")
.concat(signing_method)
.concat("&oauth_timestamp=")
.concat(timestamp)
.concat("&").concat("oauth_version=").concat("1.0");
console.log(sig_string)
let normalised_string = "POST&".concat(normalizedUrl).concat("&").concat(encodeURIComponent(sig_string));
console.log(normalised_string);
let signingKey = secret.concat("&");
console.log(signingKey);
let digest = CryptoJS.HmacSHA256(normalised_string, signingKey);
console.log(">>>>>>>>>>>>>");
console.log(digest);
let signature = CryptoJS.enc.Base64.stringify(digest);
let auth = 'OAuth oauth_consumer_key="'
.concat(key)
.concat('",oauth_signature_method="')
.concat(signing_method)
.concat('",oauth_signature="')
.concat(encodeURIComponent(signature))
.concat('",oauth_timestamp="')
.concat(timestamp)
.concat('",oauth_nonce="')
.concat(nonce)
.concat('",oauth_version="1.0"')
console.log(auth)
return axios({
method: 'post',
url: url,
data: JSON.stringify({grantType: "client_credentials"}),
headers: {
'Content-Type': "application/json",
'Authorization': auth
}
});
}
Upvotes: 0