'HERE API OAuth Access Token Request - Swift
I am trying to request an OAuth access token from HERE API. It is working however I am receiving intermittent errors. Around 50% of the time I am receiving this response:
{"errorId":"ERROR-8638f6e6-4fe9-420e-a31c-600f3062105b","httpStatus":401,"errorCode":401300,"message":"Signature mismatch. Authorization signature or client credential is wrong.","error":"invalid_client","error_description":"errorCode: '401300'. Signature mismatch. Authorization signature or client credential is wrong."}
Here is my code:
let url = URL(string: "https://account.api.here.com/oauth2/token")!
//Credentials
let accessKeyId = "xxxxxxxxxxxxxxxx"
let accessKeySecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
//Base String
let timeStamp = String(Int(Date().timeIntervalSince1970))
let nonce = String(Int(Date().timeIntervalSince1970 * 1000))
let grant_type = "grant_type=client_credentials"
let oauth_consumer_key = "&oauth_consumer_key=" + accessKeyId
let oauth_nonce = "&oauth_nonce=" + nonce
let oauth_signature_method = "&oauth_signature_method=HMAC-SHA256"
let oauth_timestamp = "&oauth_timestamp=" + timeStamp
let oauth_version = "&oauth_version=1.0"
let paramsString = grant_type + oauth_consumer_key + oauth_nonce + oauth_signature_method + oauth_timestamp + oauth_version
let baseString = "POST&" + url.absoluteString.urlEncoded()! + "&" + paramsString.urlEncoded()!
//Key
let secret = accessKeySecret + "&"
let key = SymmetricKey(data: Data(secret.utf8))
//Signature
let signature = HMAC<SHA256>.authenticationCode(for: Data(baseString.utf8), using: key)
let baseEncodedSignature = Data(signature).base64EncodedString().urlEncoded()!
//Request
var request = URLRequest(url: url)
request.httpMethod = "POST"
//Request Headers
let authString = "OAuth oauth_consumer_key=\"\(accessKeyId)\",oauth_nonce=\"\(nonce)\",oauth_signature=\"\(baseEncodedSignature)\",oauth_signature_method=\"HMAC-SHA256\",oauth_timestamp=\"\(timeStamp)\",oauth_version=\"1.0\""
request.setValue(authString, forHTTPHeaderField: "Authorization")
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField:"Content-Type")
//Request Body
var requestBodyComponents = URLComponents()
requestBodyComponents.queryItems = [URLQueryItem(name: "grant_type", value: "client_credentials")]
request.httpBody = requestBodyComponents.query?.data(using: .utf8)
let config = URLSessionConfiguration.default
config.timeoutIntervalForRequest = TimeInterval(20)
config.timeoutIntervalForResource = TimeInterval(20)
let urlSession = URLSession(configuration: config)
urlSession.dataTask(with:request, completionHandler: { (data, response, error) in
completion(data, response, error)
}).resume()
Extension for URL encoding...
public extension String {
func urlEncoded() -> String? {
addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)?
.replacingOccurrences(of: "&", with: "%26")
.replacingOccurrences(of: "=", with: "%3D")
}
}
Any ideas what is happening?
Many thanks
Solution 1:[1]
Hi would you please test below code?
import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
var semaphore = DispatchSemaphore (value: 0)
let parameters = "{\"grantType\":\"client_credentials\",\"expiresIn\":86400}"
let postData = parameters.data(using: .utf8)
var request = URLRequest(url: URL(string: "https://account.api.here.com/oauth2/token")!,timeoutInterval: Double.infinity)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("OAuth oauth_consumer_key=\"*************\",oauth_signature_method=\"HMAC-SHA1\",oauth_timestamp=\"1653538948\",oauth_nonce=\"fLlPzE4HBxJ\",oauth_version=\"1.0\",oauth_signature=\"vy9BT5dF3EBk0DR9JdxDu7StKeM%3D\"", forHTTPHeaderField: "Authorization")
request.httpMethod = "POST"
request.httpBody = postData
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
print(String(describing: error))
semaphore.signal()
return
}
print(String(data: data, encoding: .utf8)!)
semaphore.signal()
}
task.resume()
semaphore.wait()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Younjae Park |
