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

时间:2015-04-27 12:03:36

标签: ios swift oauth uber-api

我在我的iOS(Swift)应用中实现了Uber's Request Endpoint。 Request API / Endpoint需要用户对应用进行身份验证,此处为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. 在Appdelegate的方法didFinishLaunchingWithOptions

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

  5. 转到您应用的目标 - >信息标签 - >网址类型 - >单击(+),附加图像

    enter image description here

    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)")
          }
      }
      
    3. 这是我的调试日志,我得到了有效的回复:

          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在STEP4 *使用承载者中所说的

      将Authorizer标头中响应中返回的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"})
      

3 个答案:

答案 0 :(得分:4)

最后我做到了:)

我改变了下面的方法并且工作了

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()

}

这是我得到的响应,解析也在上面的方法中给出

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

享受

答案 1 :(得分:1)

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

uberRequest:

    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()

它返回:

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

答案 2 :(得分:0)

要使用令牌,只需按照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()