Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OAuthSwift returns "The operation couldn’t be completed. (OAuthSwiftError error -10.)". #307

Closed
5 of 18 tasks
the-freshlord opened this issue Nov 7, 2016 · 9 comments
Closed
5 of 18 tasks

Comments

@the-freshlord
Copy link

Description:

When logging in with Facebook, I am able to get the redirect url with the oauthtoken. I have a custom view controller that I set to my instance of OAuthSwift as the authorizeURLHandler. In the custom view controller, I implemented the UIWebViewDelegate method for shouldStartLoadWith where I check for the redirect URL. I then pass the URL into OAuthSwift.handle(). After doing this, I get this error message from OAuthSwift: "The operation couldn’t be completed. (OAuthSwiftError error -10.)". What does this mean and what am I'm doing wrong to get this error?

OAuth Provider (Twitter, Github, ..):

Facebook

OAuth Version:

  • Version 1
  • Version 2

OS (Please fill the version) :

  • iOS :
  • OSX :
  • TVOS :
  • WatchOS :

Installation method:

  • Carthage
  • CocoaPods
  • Manually

Library version:

  • head
  • v1.0.0
  • v0.6
  • other: (Please fill in the version you are using.)

Xcode version:

  • 8.0 (Swift 3.0)

  • 8.0 (Swift 2.3)

  • 7.3.1

  • other: (Please fill in the version you are using.)

  • objective c

Code Sample

let oauthSwift = OAuth2Swift(consumerKey: ConfigManager.shared().facebookAppId, consumerSecret: ConfigManager.shared().facebookSecret, authorizeUrl: _facebookAuthorizationUrlString, accessTokenUrl: _facebookAccessTokenUrlString, responseType: _facebookResponseType)
        let facebookSocialAuthViewController = _internalFacebookSocialAuthWebViewController
        facebookSocialAuthViewController.userCanceledOAuthFlowClosure = {
            failure(nil, true, nil, nil)
        }
        parentController.navigationController?.pushViewController(facebookSocialAuthViewController, animated: true)
        oauthSwift.authorizeURLHandler = facebookSocialAuthViewController
        oauthSwift.authorize(withCallbackURL: _socialRedirectUrl, scope: _facebookScopeParameters, state: generateState(withLength: 20) as String, success: { (credential, response, parameters) in
            let oauthObject = OAuthObject(oAuthTwoWithProviderName: SocialAuthProviderNames.facebook, andOAuthTwoAuthorizationCode: credential.oauthToken, andOAuthTwoRedirectUrlForProvider: self._socialRedirectUrl.absoluteString)!
            self.postSocialAuth(oauthObject, success: { (user: User) in
                success(user)
            }, failure: { (error: Error, response: HTTPURLResponse) in
                if error.localizedDescription == SocialAuthErrors.noEmailProvided {
                    failure(oauthObject, false, error, response)
                    return
                }
                failure(nil, false, error, response)
            })
        }, failure: { (error) in
            failure(nil, false, error, nil)
        })

Here is my custom web vie controller for handling the login.

import UIKit
import OAuthSwift

final class LTFSocialAuthWebViewController: LTFAuthViewController {
    
    // MARK: - Attributes
    fileprivate let _previousCookieAcceptPolicy = HTTPCookieStorage.shared.cookieAcceptPolicy
    fileprivate var _webView = UIWebView()
    fileprivate var _authorizeWithCallBackUrl: URL!
    fileprivate var _targetUrl: URL!
    fileprivate var _socialAuthName: String!
    var userCanceledOAuthFlowClosure: (() -> Void)?
    
    
    // MARK: - Initializers
    init(_ authorizeWithCallBackUrl: URL, socialAuthName: String) {
        super.init(nibName: nil, bundle: nil)
        _authorizeWithCallBackUrl = authorizeWithCallBackUrl
        _socialAuthName = socialAuthName
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
}


// MARK: - Lifecycle
extension LTFSocialAuthWebViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        initializeView()
    }
}


// MARK: - OAuthSwiftURLHandlerType
extension LTFSocialAuthWebViewController: OAuthSwiftURLHandlerType {
    func handle(_ url: URL) {
        _targetUrl = url
        loadAuthorizationUrl()
    }
}


// MARK: - UIWebViewDelegate
extension LTFSocialAuthWebViewController: UIWebViewDelegate {
    func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
        guard let authorizationUrl = request.url, authorizationUrl.host == _authorizeWithCallBackUrl.host else {
            return true
        }
        OAuthSwift.handle(url: authorizationUrl)
        _ = navigationController?.popViewController(animated: true)
        return false
    }
}


// MARK: - Private Instance Methods
extension LTFSocialAuthWebViewController {
    fileprivate func initializeView() {
        navigationItem.title = _socialAuthName
        navigationItem.backBarButtonItem = UIBarButtonItem(image: UIImage(named: "icon-previous"), style: .plain, target: self, action: #selector(cancelButtonTapped))
        _webView.frame = UIScreen.main.bounds
        _webView.scalesPageToFit = true
        _webView.delegate = self
        view.addSubview(_webView)
    }
    
    fileprivate func loadAuthorizationUrl() {
        HTTPCookieStorage.shared.cookieAcceptPolicy = .always
        let cookies = HTTPCookieStorage.shared.cookies
        HTTPCookieStorage.shared.setCookies(cookies!, for: _targetUrl, mainDocumentURL: _targetUrl)
        _webView.loadRequest(URLRequest(url: _targetUrl, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 60.0))
    }
    
    @objc fileprivate func cancelButtonTapped() {
        HTTPCookieStorage.shared.cookieAcceptPolicy = _previousCookieAcceptPolicy
        _ = navigationController?.popViewController(animated: true)
        guard let closure = userCanceledOAuthFlowClosure else { return }
        closure()
    }
}
@the-freshlord the-freshlord changed the title OAuthSwift returns "The operation couldn’t be completed. (OAuthSwiftError error -10.)". OAuthSwift returns "The operation couldn’t be completed. (OAuthSwiftError error -10.)". Help wanted Nov 7, 2016
@the-freshlord the-freshlord changed the title OAuthSwift returns "The operation couldn’t be completed. (OAuthSwiftError error -10.)". Help wanted OAuthSwift returns "The operation couldn’t be completed. (OAuthSwiftError error -10.)". Nov 7, 2016
@phimage
Copy link
Member

phimage commented Nov 7, 2016

I don't understand why you can see only error code, I implement CustomStringConvertible (maybe CustomDebugStringConvertiblemust also be implemented)

OAuthSwiftError error -10 -> retain, see https://github.com/OAuthSwift/OAuthSwift/blob/master/Sources/OAuthSwiftError.swift

You must retain your oauthSwift object somewhere, have a head reference on it
let oauthSwift = OAuth2Swift is not good if after you do not store it elsewhere

@the-freshlord
Copy link
Author

Where would it need to be stored if it is a retain problem. Or should it be a var?

@phimage
Copy link
Member

phimage commented Nov 7, 2016

yes a var into your controller (see demo app for instance)

you authorise only one time authorize(withCallbackURL:
then you can use the object oauthSwift to do some request from any functions of your controller

@the-freshlord
Copy link
Author

I was able to get it to work. I looked at the demo view controller example and saw you had an instance variable for retaining the oauthswift object. I set it after creating a OAuthSwift object in my class for handling social auth.

@phimage phimage closed this as completed Nov 7, 2016
@the-freshlord
Copy link
Author

Out of curiosity, could it cause a retain cycle?

@phimage
Copy link
Member

phimage commented Nov 7, 2016

No. You must retain it because we do the maximum to not retain anything internally (and our retain exception is thrown in that case instead of keeping reference to the objects)

@the-freshlord
Copy link
Author

the-freshlord commented Nov 7, 2016

Now I am getting a new issue. When getting the oauthcode in the redirect, this is what it looks like: https://app.baseapp.tsl.io/?code=AQBmpqCsISKO-qpynrW1C7syI34HK2qGn0yI4_fmaqNKE_IqEbqxHgwRd9gJ43WT8VBWkTaetp6l61bWp-yhQ45W2v2W217GTTgrRv33yiN5QXJv-Z9ITVBsU8Yjv-0qIavzpVpoou-MHWxkDeNxqBqcMjUjEQjNpOq5KC8aSBYa-fGLNAyglvdX6P78m-7cPafoQGJ_73EJ4yMLKbX23TIt1odtcV9JAG9L8THaDsjCX7Iwb15Ov_eNN1W7PGX9Ecg5GLAlKfJxCtRtZPreMuhSc5ZfNqEsW9XAM6Fs-TH_L3wIzt6ZEkaW_Yol-dRy026rql8rhvGvboTus0DjkH35&state=2iQTuirDDt0783Kipz4V#_=_.
Now when getting this token, it changes to EAAXDphYBK2wBAIQCAeEe8S1OuTTcu8m5jBD8rr2XZBc7eCoMeHyC8q20cWEXo559ByJNSjEYxANZAPZBs8FMHvoscZC3B1Orjes1WtVQORCgmgi09MeQynVt30lH7mWdq2Rlbm1OkiYfvZB5l649sPerBO95Cl24ZD. Why does it change?
When accessing credential.oauthToken, the value should be the one that is in the redirect url.

@the-freshlord
Copy link
Author

Actually figured out its the access token. But is there still a way to get the code thats in the redirect URL?

@phimage
Copy link
Member

phimage commented Nov 8, 2016

a new topic, a new issue

code is just a temporary var to request then the oauth token using url accessTokenUrl
I think this code is not stored anywhere and if last request don't provide it you cannot have it in "parameters" (in success callback)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants