Ошибка OAuth2 с Reddit API - Swift - PullRequest
0 голосов
/ 16 мая 2018

Я интегрирую API Reddit в свое приложение для iOS, но у меня возникают проблемы с запросами. Я использую Alamofire для выполнения запросов POST. Когда вы используете API Reddit в установленных приложениях, вы должны следовать их Поток предоставления только приложений . Все работает, кроме того, что я получаю ошибку unsupported_grant_type.

Это мой POST-запрос.

guard let url = URL(string: "https://www.reddit.com/api/v1/access_token") else { return false }
            let params: Parameters = [
                "grant_type" : "https://oauth.reddit.com/grants/installed_client",
                "device_id" : "\(UUID().uuidString)"]

            let username = "MY_CLIENT_ID"
            let password = ""
            let loginString = String(format: "%@:%@", username, password)
            let loginData = loginString.data(using: String.Encoding.utf8)! as NSData
            let base64EncodedString = loginData.base64EncodedString()

            let headers = ["Content-Type" : "application/x-www-form-urlencoded",
                           "Authorization" : "Basic \(base64EncodedString)"]

            Alamofire.request(url, method: .post , parameters: params, encoding: JSONEncoding.default, headers: headers).responseJSON { (response) in
                print(response)

            }

Мой grant_type параметр правильный, хотя? Как я полагаю, потому что документация говорит мне использовать https://oauth.reddit.com/grants/installed_client в качестве типа предоставления для установленных приложений.

1 Ответ

0 голосов
/ 19 ноября 2018

Это работает для меня, Это не использует AlamoFire tho.

Swift 4,2

    let ACCESS_TOKEN_URL = "https://www.reddit.com/api/v1/access_token"
    let GRANT_TYPE = "https://oauth.reddit.com/grants/installed_client"
    let DONT_TRACK = "DO_NOT_TRACK_THIS_DEVICE"
    let timeout = 15
    let uncodedClientIDAndPassword = "\(CLIENT_ID):"
    let encodedClientIDAndPassword = uncodedClientIDAndPassword.toBase64()
    let authStr = "Basic \(encodedClientIDAndPassword!)"
    guard let serviceUrl = URL(string: ACCESS_TOKEN_URL) else {
        completionHandler(nil)
        return
    }
    var request = URLRequest(url: serviceUrl)
    request.httpMethod = "POST"
    request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
    request.addValue(authStr, forHTTPHeaderField: "Authorization")

// Important Edit: You need to manually make the parameters, don't make a String dictionary and convert it to JSON and then sending it. Reddit doesn't accept that.
            let param = "grant_type=\(GRANT_TYPE)&device_id=\(DONT_TRACK)"
            let data = param.data(using: .utf8)
            request.httpBody = data
            // timeout
            let config = URLSessionConfiguration.default
            config.timeoutIntervalForRequest = TimeInterval(timeout)
            config.timeoutIntervalForResource = TimeInterval(timeout)
            let session = URLSession(configuration: config)

            session.dataTask(with: request) { (data, response, error) in
                if data != nil {
                    do {
                        if let json = (try? JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers)) as? [String: Any] {
                            self.accessToken = json["access_token"] as? String
                        } else {
                            self.accessToken = nil
                        }
                    }
                }
                completionHandler(self.getAccessToken())
            }.resume()
        }
...