Как получить токен доступа MS Translator из Swift 3?

#ios #swift #security #web #oauth-2.0

#iOS #swift #Безопасность #веб #oauth-2.0

Вопрос:

Я пытаюсь работать с API MS Translator из Swift 3 (прямо сейчас играю на игровых площадках, но целевой платформой является iOS). Однако я застрял, когда пытался получить токен доступа для OAuth2. У меня есть следующий код (я попытался перенести код из примера при получении токена доступа):

 let clientId = "id".addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
let clientSecret = "secret".addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
let scope = "http://api.microsofttranslator.com".addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!

let translatorAccessURI = "https://datamarket.accesscontrol.windows.net/v2/OAuth2-13"
let requestDetails = "grant_type=client_credentialsamp;client_id=(clientId)amp;client_secret=(clientSecret)amp;scope=(scope)"

let postData = requestDetails.data(using: .ascii)!
let postLength = postData.count

var request = URLRequest(url: URL(string: translatorAccessURI)!)
request.httpMethod = "POST"
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.setValue("(postLength)", forHTTPHeaderField: "Content-Length")

request.httpBody = postData

URLSession.shared.dataTask(with: webRequest) { (returnedData, response, error) in
    let data = String(data: returnedData!, encoding: .ascii)
    print(data)
    print("**************")
    print(response)
    print("**************")
    print(error)
}.resume()
  

Конечно, я использовал действительный идентификатор клиента и действительный clientSecret.

Теперь обратный вызов выводит следующую информацию. Во-первых, возвращаемые данные содержат сообщение о том, что запрос был недействительным, а также следующее сообщение:

 "ACS90004: The request is not properly formatted."
  

Во-вторых, в ответе содержится код 400 (который соответствует тому факту, что запрос неправильно отформатирован).

В-третьих, ошибка равна нулю.

Теперь я тестировал вызов с помощью Postman, и когда я использовал тот же URI и поместил строку requestDetails в качестве основного сообщения (я добавил Content-Type заголовок вручную), я получил тот же ответ. Однако, когда я изменил тип тела в пользовательском интерфейсе Postman на application/x-www-form-urlencoded и ввел данные запроса в виде пар ключ-значение через его пользовательский интерфейс, вызов был выполнен успешно. Теперь кажется, что я делаю что-то не так с форматированием сообщения или, может быть, даже что-то плохое с API Swift URLRequest / URLSession, однако я не могу понять, что именно. Кто-нибудь может мне помочь, пожалуйста? Спасибо.

Ответ №1:

Хорошо, итак, после еще нескольких отчаянных поисков в Google и экспериментов я нашел свою ошибку. Для будущих поколений:

Проблема заключалась в кодировании параметров в теле http-запроса PUT. Вместо:

 let scope = "http://api.microsofttranslator.com"
             .addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
  

Я должен использовать следующее:

 let scope = "http://api.microsofttranslator.com"
             .addingPercentEncoding(withAllowedCharacters: 
                         CharacterSet(charactersIn: ";/?:@amp;=$ {}<>,").inverted)!
  

Кажется, что API (или протокол HTTP, я не эксперт в этом) имеют проблемы с / : символами и в теле запроса. Я должен отдать должное ответу Studiosus на отчет о проблеме полиглота.