I have a vapor3 app within which I am trying to connect to the Xero Api, the process is fairly simple. We send the user to a xero web page where they login with the details and authorise our connection, it then redirects back to my vapor 3 app. In the app we then connect to the xero server with the code provided in the redirect, and then xero should be issue an access token to be used going forward. The process is described here
The issue is I can't connect to xero to get the access token. I have tried 2 approaches, the first is to use HTTPClient, with this code:
let m = try decoder.decode(Master.self, from: masterDoc!)
let ci = m.xeroAppKey.data(using: .utf8)?.base64EncodedString() //convert from string to base encoded
let xs = m.xeroAppSec.data(using: .utf8)?.base64EncodedString() //convert from string to base encoded
let authorization = "Basic " + ci! + ":" + xs!
print("authorisation is \(authorization)")
return HTTPClient.connect(hostname: "identity.xero.com", on: req).flatMap{client in
var httpReq = HTTPRequest(method: .POST, url: "https://identity.xero.com/connect/token")
httpReq.headers.add(name: "authorization", value: authorization)
httpReq.headers.add(name: "Content-Type", value: "x-www-form-urlencoded")
httpReq.body = HTTPBody(string: "grant_type=authorization_code&code=\(code)&redirect_uri=http://localhost:8080/XeroAuthRedirect")
return client.send(httpReq).flatMap{resp in
print("response is \(resp) with status \(resp.status)")
return req.future().map{
return .ok
}
}
}
With this I get the following response:
HTTP/1.1 301 Moved Permanently
Server: AkamaiGHost
Content-Length: 0
Location: https://identity.xero.com/connect/token
Expires: Tue, 02 Jun 2020 07:59:59 GMT
Cache-Control: max-age=0, no-cache, no-store
Pragma: no-cache
Date: Tue, 02 Jun 2020 07:59:59 GMT
Connection: keep-alive
Which suggests the end point has moved but the location suggested is the same one that I am trying to connect to. I can't find anywhere in the docs which suggested the end point has changed. It also seems HTTPClient wont follow redirects.
So I tried to connect using URLSession instead using this code:
let url = URL(string:"https://identity.xero.com/connect/token")!
let payload = "grant_type=authorization_code&code=\(code)&redirect_uri=http://localhost:8080/XeroAuthRedirect".data(using: .utf8)
let promise = req.eventLoop.newPromise(HTTPStatus.self)
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue(authorization, forHTTPHeaderField: "authorization")
request.addValue("x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpBody = payload
URLSession.shared.dataTask(with: request) {(data, response, error) in
if let error = error {
print(error.localizedDescription)
promise.fail(error: error) // (!)
return
}
guard let data = data else {
print("empty data")
promise.fail(error: SumUpError.invalidResponse) // (!)
return
}
guard let str = String(data: data, encoding: .utf8) else {
print("invalid data")
promise.fail(error: SumUpError.invalidResponse) // (!)
return
}
print(str)
print("response is \(String(describing: response))")
}.resume()
Where i get the following error message.
{"error":"invalid_request"}
Any ideas what is going on here or how I can get this connection up and running are greatly apprecitated.