Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Uber Invalid OAuth 2.0 credentials provided Uber Authentication In ios Swift

I'm implementing the Uber's Request Endpoint in my iOS (Swift) App. The Request API/Endpoint requires the user authentication with the app, here is the doc.

For this I'm using this Oauth2.0 library

What I did is

  1. successfully integrated the Library in my project (xCode) with the help of given installation instructions.

  2. In My 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. in my method didFinishLaunchingWithOptions of Appdelegate

     oauth = OAuth2CodeGrant(settings: uber_OAuth_Settings)
    oauth.viewTitle = "Uber Login Service"      // optional
    oauth.verbose = true // For Logs
    
  4. Don't forget to register url scheme i.e ("redirect_uris": ["jamesappv2://oauth/callback"])

goto your app's Target -> info Tab -> Url Types -> Click (+), image attached

enter image description here

  1. In AppDelegate add method given Below and Handle the Callback 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. Now in my viewController I did like this on 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)")
        }
    }
    

Here is my debug log, I'm getting the valid response:

    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]

Notice I'm getting the valid access_token

Here I'm stuck

As per DOCs says in STEP4 *USE BEARER TOKEN

Pass the access_token returned in the response in the Authorization header with the type Bearer to make requests on behalf of a user.*

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

I am not getting the point. How should I pass the access_token in Header with type Bearer? I have done like below

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

but I'm getting following response

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"})
like image 288
Qadir Hussain Avatar asked Apr 27 '15 12:04

Qadir Hussain


2 Answers

Finally I have done it :)

I changed the method like below and it Worked

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

}

here is the Response I Got, Parsing is also given in my above method

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

Enjoy

like image 108
Qadir Hussain Avatar answered Oct 14 '22 01:10

Qadir Hussain


Updated for Swift 2. I used the same setup and library for oauth that Qadir describes in his question. I updated his request to work in Swift 2. Hope this helps others.

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

It returns:

Result -> Optional(["driver": <null>, "request_id": 5834384c-7283-4fe6-88a7-e74150c6ab30, "surge_multiplier": 1, "location": <null>, "vehicle": <null>, "status": processing, "eta": <null>])
like image 1
tylerSF Avatar answered Oct 13 '22 23:10

tylerSF