Uber 在 ios Swift 中提供的 Uber 身份验证无效 OAuth 2.0 凭据

Uber Invalid OAuth 2.0 credentials provided Uber Authentication In ios Swift

我正在实施 Uber's Request Endpoint in my iOS (Swift) App. The Request API/Endpoint requires the user authentication with the app, here is the doc

为此,我正在使用这个 Oauth2.0 library

我做的是

  1. 在给定的安装说明的帮助下,成功地将库集成到我的项目中 (xCode)。

  2. 在我的 AppDelegate 中

    let uber_OAuth_Settings = [
    "client_id": "XXXXXXX9vtKzobvXXXXXX",
    "client_secret": "EXXXXXXXXyFUNCa_Wez6AXXXXXXXnrXtxus",
    "authorize_uri": "https://login.uber.com/oauth/authorize",
    "token_uri": "https://login.uber.com/oauth/token",
    "redirect_uris": ["jamesappv2://oauth/callback"],   // don't forget to register this scheme
    ] as OAuth2JSON
    

    var oauth:OAuth2CodeGrant!

  3. 在我的 AppdelegatedidFinishLaunchingWithOptions 方法中

     oauth = OAuth2CodeGrant(settings: uber_OAuth_Settings)
    oauth.viewTitle = "Uber Login Service"      // optional
    oauth.verbose = true // For Logs
    
  4. 不要忘记注册 url 方案即 ("redirect_uris": ["jamesappv2://oauth/callback"])

转到您应用的目标 -> 信息选项卡 -> Url 类型 -> 单击 (+),附加图像

  1. 在 AppDelegate 中添加下面给出的方法并处理回调 Url

    func application(application: UIApplication,
    openURL url: NSURL,
    sourceApplication: String?,
    annotation: AnyObject?) -> Bool {
        // you should probably first check if this is your URL being opened
    
       var splitUrl = url.absoluteString!.componentsSeparatedByString(":")
    
        if splitUrl[0] == ("jamesappv2") {
    
            oauth.handleRedirectURL(url)
        }
    
        return true
    }
    
  2. 现在在我的 viewController 我在 myBtnClick 上喜欢这个

    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
    
    let url = appDelegate.oauth.authorizeURL()
    UIApplication.sharedApplication().openURL(url)        
    appDelegate.oauth.onAuthorize = { parameters in
        println("Did authorize with parameters: \(parameters)")
    
        self.navigationController?.pushViewController(self.PersonalDriverUber_VC, animated: true)
    //On Authorization Goto another ViewController using pushViewController of navigationcontroller Method
    
    }
    appDelegate.oauth.onFailure = { error in        // `error` is nil on cancel
        if nil != error {
            println("Authorization went wrong: \(error!.localizedDescription)")
        }
    }
    

这是我的调试日志,我得到了有效的响应:

    OAuth2: Handling redirect URL jamesappv2://oauth/callback?state=4B0EB812&code=0sXXXXXXTX7yEbS1XXXXXHuw
OAuth2: Successfully validated redirect URL
OAuth2: Authorizing against https://login.uber.com/oauth/token?state=38158941&grant_type=authorization_code&code=0sXXXXXXXX1jxTrdFQT9Huw&client_secret=EIXXXXXXXNCa_Wez6XXXXXw0BlnrXtxus&client_id=fXXXXXXXy2LOUo9vtKXXXXXQ1nUDO&redirect_uri=jamesappv2%3A%2F%2Foauth%2Fcallback
OAuth2: Exchanging code 0swNXXXXX7yXXXXXXdFQT9Huw with redirect jamesappv2://oauth/callback for token at Optional("https://login.uber.com/oauth/token")
OAuth2: Did receive access token: Dfq3XXXXXXuWgpaqFXXXXXXXgXW, refresh token: EmStT7FEXHRMlS8odPzs1nsha0ObjK
Did authorize with parameters: [token_type: Bearer, expires_in: 2592000, access_token: XXXXXXOZuWgXXXXXXXXuJYOmgXW, refresh_token: EXXXXXHRMlS8oXXXXXXXa0ObjK, scope: profile, last_authenticated: 1430121470]

通知 我收到了有效的access_token

我卡在这里了

按照 DOCs 在第 4 步中所说 *USE BEARER TOKEN

传递授权 header 响应中返回的 access_token 类型 Bearer 以代表用户发出请求。*

curl -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' 'https://api.uber.com/v1/products?latitude=37.7759792&longitude=-122.41823'

我没听懂。我应该如何通过 Bearer 类型在 Header 中传递 access_token?我做了如下

func callRequestAPI(url:String){

    let request = appDelegate.oauth.request(forURL: NSURL(string:url)!)



    request.HTTPMethod = "POST"


    let postString = "product_id="+selectedUberProductId+"&start_latitude="+start_lat+"&start_longitude="+start_lng+"&end_latitude="+end_lat+"&end_longitude="+end_lng

    println(postString)


    let tempData: NSData = appDelegate.oauth.accessToken.dataUsingEncoding(NSUTF8StringEncoding)!
    let base64LoginString = tempData.base64EncodedStringWithOptions(nil)

    request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    request.addValue("application/json", forHTTPHeaderField: "Accept")




   request.setValue("Bearer \(base64LoginString)", forHTTPHeaderField: "Authorization")

    let session = NSURLSession.sharedSession()

    let task = session.dataTaskWithRequest(request) { data, response, error in


        if error != nil {
            println("error=\(error)")
            return
        }

        println("response = \(response)")

        let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)
        println("responseString = \(responseString)")

    }
    task.resume()
}

但我收到以下回复

response = <NSHTTPURLResponse: 0x1a284b50> { URL: https://sandbox-api.uber.com/v1/requests } { status code: 401, headers {
"Content-Length" = 75;
"Content-Type" = "application/json";
Date = "Mon, 27 Apr 2015 10:22:01 GMT";
Server = nginx;
"Strict-Transport-Security" = "max-age=31536000; includeSubDomains; preload";
"x-uber-app" = "uberex-sandbox";
"x-xss-protection" = "1; mode=block";
} }
responseString = Optional({"message":"Invalid OAuth 2.0 credentials provided.","code":"unauthorized"})

要使用令牌,只需按照 OAuth2 库中说明的第 5 步操作,就像您开始尝试自己第二次签名之前所做的那样。请求已经签名并设置了 Bearer 令牌,您无需执行任何操作:

let url = NSURL(string: "https://api.uber.com/v1/products?latitude=37.7759792&longitude=-122.41823")
let req = appDelegate.oauth.request(forURL: url)

// customize your request, if needed. E.g. for POST:
req.HTTPMethod = "POST"

// send the request
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(req) { data, response, error in
    if nil != error {
        // something went wrong
    }
    else {
        // check the response and the data
        // you have just received data with an OAuth2-signed request!
    }
}
task.resume()

我终于做到了:)

我改变了下面的方法并且成功了

func callRequestAPI(url:String){

    var configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
    var session = NSURLSession(configuration: configuration)

    let params:[String: AnyObject] = [
        "product_id" : selectedUberProductId,
        "start_latitude" : start_lat,
        "start_longitude" : start_lng,
        "end_latitude" : end_lat,
        "end_longitude" : end_lng]



    let request = appDelegate.oauth.request(forURL: NSURL(string:url)!)
    request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
    request.HTTPMethod = "POST"
    var err: NSError?
    request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: NSJSONWritingOptions.allZeros, error: &err)

    let task = session.dataTaskWithRequest(request) {
        data, response, error in

        if let httpResponse = response as? NSHTTPURLResponse {
            if httpResponse.statusCode != 202 {
                println("response was not 202: \(response)")

                return
            }
        }
        if (error != nil) {
            println("error submitting request: \(error)")
            return
        }

        // handle the data of the successful response here
        var result = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.allZeros, error: nil) as! NSDictionary


        println(result)

        if let request_id: String = result["request_id"] as? String{

            println(request_id)
        }

        if let driver: String = result["driver"] as? String{

            println(driver)
        }

        if let eta: Int = result["eta"] as? Int{

            println(eta)
        }

        if let location: String = result["location"] as? String{

            println(location)
        }


        if let status: String = result["status"] as? String{

            println(status)
        }


        if let surge_multiplier: Int = result["surge_multiplier"] as? Int{

            println(surge_multiplier)
        }

        if let vehicle: String = result["vehicle"] as? String{

            println(vehicle)
        }

    }

    task.resume()

}

这是我得到的Response,我上面的方法也给出了解析

{
  driver = "<null>";
  eta = 15;
  location = "<null>";
  "request_id" = "ea39493d-b718-429f-8710-00a34dcdaa93";
  status = processing;
  "surge_multiplier" = 1;
  vehicle = "<null>";
}

尽情享受

更新 Swift 2. 我使用了 Qadir 在他的问题中描述的相同的 oauth 设置和库。我更新了他在 Swift 2 工作的请求。希望这对其他人有帮助。

优步请求:

    let params:[String:AnyObject] = [
        "product_id" : uberProduct,
        "start_latitude" : userLat,
        "start_longitude" : userLng,
        "end_latitude" : barLat,
        "end_longitude" : barLng]

    let urlPath = "https://sandbox-api.uber.com/v1/requests"
    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
    var configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
    var session = NSURLSession(configuration: configuration)

    guard let endpoint = NSURL(string: urlPath) else { print("Error creating endpoint");return }

    let request = appDelegate.oauth.request(forURL: NSURL(string:urlPath)!)
    request.setValue("application/json; charset=utf-8", forHTTPHeaderField:"Content-Type")

    request.HTTPBody = try! NSJSONSerialization.dataWithJSONObject(params, options: NSJSONWritingOptions.PrettyPrinted)

    request.HTTPMethod = "POST"

    print("Prepare to make request -> \(request)")

    let task = NSURLSession.sharedSession().dataTaskWithRequest(request){ data, response, error in
        if error != nil{
            print("Error -> \(error)")
            return
        }

        do {
            let result = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)

            print("Result -> \(result)")

        } catch {
            print("Error -> \(error)")
        }
    }

    task.resume()

它returns:

Result -> Optional(["driver": <null>, "request_id": 5834384c-7283-4fe6-88a7-e74150c6ab30, "surge_multiplier": 1, "location": <null>, "vehicle": <null>, "status": processing, "eta": <null>])