1
votes

I'm trying to authenticate with uber in my project, the path to go to the uber native app and then return to my application is ok. However, it is only returning the TokenString and the ExpirationDate and the refreshToken is returning as nil.

Here is my code

AuthorizationBaseViewController

 class AuthorizationBaseViewController: UIViewController {

    func delay(delay: Double, closure: ()->()) {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(delay*Double(NSEC_PER_SEC))), dispatch_get_main_queue(), closure)
    }

    func showMessage(message: String) {
        let alert = UIAlertController(title: nil, message: message, preferredStyle: UIAlertControllerStyle.Alert)
        let okayAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil)
        alert.addAction(okayAction)
        self.presentViewController(alert, animated: true, completion: nil)
    }

    func checkError(response: Response) {
        // Unauthorized
        if response.statusCode == 401 {
            TokenManager.deleteToken()
            dispatch_async(dispatch_get_main_queue(), {
                self.reset()
            })
        }
    }

    func reset() {

    }

    // Mark: LoginButtonDelegate

    func loginButton(button: LoginButton, didLogoutWithSuccess success: Bool) {
        if success {
            showMessage(NSLocalizedString("Integration with uber canceled.", comment: ""))
        }
    }

    func loginButton(button: LoginButton, didCompleteLoginWithToken accessToken: AccessToken?, error: NSError?) {
        if let _ = accessToken {


            print(accessToken?.tokenString)
            print(accessToken?.expirationDate)
            print(accessToken?.refreshToken)

            showMessage(NSLocalizedString("Uber user authenticated successfully.", comment: ""))
            if let url = NSURL(string: "xxxxxxxxxxxxxx") {
                let request = NSMutableURLRequest(URL: url)
                request.HTTPMethod = "POST"
                request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
                let token = AccessToken?()
                let jsonObject = ["token" : (token?.tokenString)!, "refresh_token" : (token?.refreshToken)!,"expires_in" : (token?.expirationDate)!, "user_id" : "uber_uuid"  , "token_type" : "Bearer"] as Dictionary <String,AnyObject>

                request.HTTPBody = try? NSJSONSerialization.dataWithJSONObject(jsonObject, options: [])

                NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
                    guard
                        let data = data where
                        error == nil &&
                            (response as? NSHTTPURLResponse)?.statusCode == 200
                        else {
                            print((response as? NSHTTPURLResponse)?.statusCode ?? "no status code")
                            print(error?.localizedDescription ?? "no error description")
                            return
                    }
                    print(String(data: data, encoding: NSUTF8StringEncoding) ?? "no string from data")
                    }.resume()
            }
            showMessage((error?.localizedDescription)!)



        } else if let error = error {
            showMessage(error.localizedDescription)
        } else {
            showMessage("Error")
        }
    }
}

LoginViewController

    class ImplicitGrantLoginViewController: AuthorizationBaseViewController, LoginButtonDelegate {


    /// The LoginManager to use for login
    let loginManager = LoginManager(loginType: .Native)

    /// The RidesClient to use for endpoints
    let ridesClient = RidesClient()

    // The Uber button to use for UI

    var uberLoginButton: LoginButton?

    // The Uber Scopes

    var uberScopes: [RidesScope]?

    @IBOutlet weak var logoutBgView: UIView!


    override func viewDidLoad() {
        super.viewDidLoad()

        //UberScopes to get authentication

        uberScopes = [.History, .Profile, .HistoryLite,.Places, .RideWidgets]

        uberLoginButton = LoginButton(frame: CGRectZero,scopes:uberScopes! ,loginManager: loginManager)


        // Uber Login Button Creation

        let loginButton = LoginButton(frame: CGRectZero, scopes: uberScopes!, loginManager: loginManager)
        loginButton.presentingViewController = self
        loginButton.delegate = self
        loginButton.frame = logoutBgView.bounds
        loginButton.autoresizingMask =
            [.FlexibleWidth, .FlexibleHeight]
        logoutBgView.addSubview(loginButton)


   }

Basically, if the refresh Token is returning to my application, a POST request is made along with the TokenString and the ExpirationDate

When authentication is done, before displaying the authorization view it appears the following error

MyApp[18136:615342] -canOpenURL: failed for URL: "uberauth://connect?third_party_app_name=MyApp &callback_uri_string=xxxxxx &client_id=xxxxxxxxxx &login_type=default&scope=history%20profile%20history_lite%20places%20ride_widgets&sdk=ios&sdk_version=0.6.0

Even with this error, the screen to authorize the scopes is displayed and when I hit Allow I see the return in the debug area however the app crashes due to the refreshtoken is nil and HTTP request not receiving it.

l Error when App Crashes due to refreshtoken is nil

I already checked the plist file and fill according uber documentation/github repository's. Callback URI, LSApplicationQuerieScheme,Client ID,DisplayName it is correct.

1
Based on the error message I'd assume you're missing the security changes proposed in the README in order to enable calls to uberauth.Alexander Graebe
@agraebe I already set this in LSApplicationQuerieSchemesuser7189581
Why do you care about the refresh token? It's marked as optional, so you have to be prepared for it not to be there.Dave Weston

1 Answers

1
votes

So reading through your question I see a few issues. It looks like you are trying to do Native login via the Uber app, which should return you an access token and a refresh token. If you are not doing Native login, then you will not get a refresh token, and that would be why it is nil.

The error message you listed:

MyApp[18136:615342] -canOpenURL: failed for URL: "uberauth://connect?third_party_app_name=MyApp &callback_uri_string=xxxxxx &client_id=xxxxxxxxxx &login_type=default&scope=history%20profile%20history_lite%20places%20ride_widgets&sdk=ios&sdk_version=0.6.0

Means that you have not added uberauth into the plist of your app under LSApplicationQueriesSchemes. I noticed that you referred to it as LSApplicationQuerieScheme which is misspelled. So that might be your problem there.

You say that the authorization code screen is still shown, which makes me think that it is falling back to Implicit Grant in a webview, which will not return a refresh token to you.

Additionally, in the code you provided where you are making your post request, you never use the access token you get back:

let token = AccessToken?()
let jsonObject = ["token" : (token?.tokenString)!,
                  "refresh_token" : (token?.refreshToken)!,
                  "expires_in" : (token?.expirationDate)!, 
                  "user_id" : "uber_uuid"  , 
                  "token_type" : "Bearer"] as Dictionary <String,AnyObject>

You initialize a new empty AccessToken and then force unwrap several optional values on that token (not the one you got back from the initial login). So those values are almost certainly nil, and the force unwrap is causing the crash