Reputation: 89
I am following this tutorial to fetch the auth token for the HERE maps. I am able to fetch the token with my iOS app, However I cannot seem to get the token with Android. I keep getting the error errorCode: '401300'. Signature mismatch. Authorization signature or client credential is wrong."
Below is my code to fetch the token :
HEREOAuthManager.java
public void fetchOAuthToken(final HereTokenFetchListener callback) {
String timestamp = String.valueOf(String.valueOf(Instant.now().getEpochSecond()));
String nonce = Util.randomStringGenerator();
String grant_type = "grant_type=client_credentials";
String oauth_consumer_key = "&oauth_consumer_key=" + clientID ;
String oauth_nonce = "&oauth_nonce=" + nonce;
String oauth_signature_method = "&oauth_signature_method=HMAC-SHA256";
String oauth_timestamp = "&oauth_timestamp=" + timestamp;
String oauth_version = "&oauth_version=1.0";
String paramsString = grant_type + oauth_consumer_key + oauth_nonce + oauth_signature_method + oauth_timestamp + oauth_version;
String baseString = "POST&" + Util.urlEncode(tokenEndpoint) + "&" + Util.urlEncode(paramsString);
// Generate signature
String secret = Util.urlEncode(clientSecret) + "&";
String signature = Util.calculateHmacSha256(secret, baseString);
// Construct Authorization header
String authString = "OAuth oauth_consumer_key=\"" + clientID + "\",oauth_nonce=\"" + nonce +
"\",oauth_signature=\"" + Util.urlEncode(signature) + "\",oauth_signature_method=\"HMAC-SHA256\"," +
"oauth_timestamp=\"" + timestamp + "\",oauth_version=\"1.0\"";
// Create HTTP client
OkHttpClient client = new OkHttpClient();
// Create request body
RequestBody requestBody = new FormBody.Builder()
.add("grant_type", "client_credentials")
.build();
// // Create HTTP request
Request request = new Request.Builder()
.url(tokenEndpoint)
.post(requestBody)
.addHeader("Authorization", authString)
.addHeader("Content-Type", "application/x-www-form-urlencoded")
.build();
}
Utils.java
public static String calculateHmacSha256(String secret, String data) {
try {
String secretWithAmpersand = secret + "&";
SecretKeySpec secretKeySpec = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(secretKeySpec);
byte[] hmacData = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
String baseEncodedSignature = Base64.getEncoder().encodeToString(hmacData);
return urlEncode(baseEncodedSignature);
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
e.printStackTrace();
return null;
}
}
public static String urlEncode(String stringToEncode) {
try {
return java.net.URLEncoder.encode(stringToEncode, "UTF-8")
.replace("+", "%20") // Replace '+' with '%20'
.replace("=", "%3D")
.replace("*", "%2A") // Replace '*' with '%2A'
.replace("&", "%26")
.replace( "~","%7E"); // Replace '~' with '%7E';
} catch (java.io.UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
public static String randomStringGenerator()
{
String ALLOWED_CHARACTERS ="0123456789qwertyuiopasdfghjklzxcvbnm";
final Random random=new Random();
final StringBuilder sb=new StringBuilder(8);
for(int i=0;i<8;++i)
sb.append(ALLOWED_CHARACTERS.charAt(random.nextInt(ALLOWED_CHARACTERS.length())));
return sb.toString();
}
What could I be missing? Any help is appreciated
Upvotes: 0
Views: 71
Reputation: 89
Finally figured out. For anyone facing the same issue, I was trying to url encode my Base64 signature string after calculating the signature. I changed the calculation to below code and it worked.
public static String calculateHmacSha256(String secret, String data) {
try {
String secretWithAmpersand = secret + "&";
SecretKeySpec secretKeySpec = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(secretKeySpec);
byte[] hmacData = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
String baseEncodedSignature = Base64.getEncoder().encodeToString(hmacData);
return baseEncodedSignature;
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
e.printStackTrace();
return null;
}
}
Upvotes: 0