I am using OAuthSwift and whenever I run this function
func doOAuthTwitter(){
let oauthswift = OAuth1Swift(
consumerKey: "...",
consumerSecret: "...",
requestTokenUrl: "https://api.twitter.com/oauth/request_token",
authorizeUrl: "https://api.twitter.com/oauth/authorize",
accessTokenUrl: "https://api.twitter.com/oauth/access_token"
)
oauthswift.authorize_url_handler = WebViewController()
oauthswift.authorizeWithCallbackURL( NSURL(string: "oauth-swift://oauth-callback/twitter")!, success: {
credential, response in
self.showAlertView("Twitter", message: "auth_token:\(credential.oauth_token)\n\noauth_toke_secret:\(credential.oauth_token_secret)")
var parameters = Dictionary<String, AnyObject>()
oauthswift.client.get("https://api.twitter.com/1.1/statuses/home_timeline.json", parameters: parameters,
success: {
data, response in
let jsonDict: AnyObject! = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: nil)
println(jsonDict)
}, failure: {(error:NSError!) -> Void in
println(error)
})
}, failure: {(error:NSError!) -> Void in
println(error.localizedDescription)
}
)
}
the function seems to run until after this point
oauthswift.authorize_url_handler = WebViewController()
authorizeWithCallbackURL doesn't even start and the jsonDict does not print. I've tried my access codes through the OAuthSwift demo, and it works fine with the tableView, printing out the JsonDict. I have no idea why authorizeWithCallbackURL goes completely ignored when I use it outside of the demo.
Related
I have problem on ssl certificate pinning in my ios app, what I want is add ssl pinning certificate to all requests using alamofire, so below is my code of the alamofire manager, when I run the app I always get this error:
load failed with error Error Domain=NSURLErrorDomain Code=-999
"cancelled"
UserInfo={NSErrorFailingURLStringKey=https://myWebsite.com/token,
NSErrorFailingURLKey=https://myWebsite.com/token,
_NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask .<1>" ), _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask .<1>,
NSLocalizedDescription=cancelled} [-999]
class AFManager : NSObject{
private var sessionManager: SessionManager?
required override init() {
super.init()
enableCertificatePinning()
}
private func enableCertificatePinning() {
let certificates = getCertificates()
let trustPolicy = ServerTrustPolicy.pinCertificates(
certificates: certificates,
validateCertificateChain: true,
validateHost: true)
let trustPolicies = [ "myWebsite.com": trustPolicy ]
let policyManager = ServerTrustPolicyManager(policies: trustPolicies)
sessionManager = SessionManager(
configuration: .default,
serverTrustPolicyManager: policyManager)
}
private func getCertificates() -> [SecCertificate] {
let url = Bundle.main.url(forResource: "myWebsitessl", withExtension: "cer")!
let localCertificate = try! Data(contentsOf: url) as CFData
guard let certificate = SecCertificateCreateWithData(nil, localCertificate)
else { return [] }
return [certificate]
}
///without headers (post)
//used this to registration
class func requestPOSTURL(_ strURL : String, params : [String : AnyObject]?, success:#escaping (JSON) -> Void, failure:#escaping (Error) -> Void){
URLCache.shared.removeAllCachedResponses()
self.init().sessionManager?.request(strURL, method: .post, parameters: params, encoding: URLEncoding.httpBody).responseJSON { (responseObject) -> Void in
//print(responseObject)
if responseObject.result.isSuccess {
let resJson = JSON(responseObject.result.value!)
success(resJson)
}
if responseObject.result.isFailure {
let error : Error = responseObject.result.error!
failure(error)
}
}
}
///// response string (post)
//used this in login // used in change password
class func strRequestPOSTURL(_ strURL : String, params : [String : String]?, headers : [String : String]?, success:#escaping (JSON) -> Void, failure:#escaping (Error) -> Void){
URLCache.shared.removeAllCachedResponses()
self.init().sessionManager?.request(strURL, method: .post, parameters: params, encoding: URLEncoding.httpBody, headers: headers).responseJSON { (response) in
//print(response)
if response.result.isSuccess {
let resJson = JSON(response.result.value!)
success(resJson)
}
if response.result.isFailure {
let error : Error = response.result.error!
failure(error)
}
}
}
}
My code was like this, see code below, and it was working, but I want certificate pinning for security so I add the things(Like sessionManager, init(),enableCertificatePinning() and getCertificates()) in the above code and after that its not working
class AFManager : NSObject{
///without headers (post)
//used this to registration
class func requestPOSTURL(_ strURL : String, params : [String : AnyObject]?, success:#escaping (JSON) -> Void, failure:#escaping (Error) -> Void){
URLCache.shared.removeAllCachedResponses()
Alamofire.request(strURL, method: .post, parameters: params, encoding: URLEncoding.httpBody).responseJSON { (responseObject) -> Void in
//print(responseObject)
if responseObject.result.isSuccess {
let resJson = JSON(responseObject.result.value!)
success(resJson)
}
if responseObject.result.isFailure {
let error : Error = responseObject.result.error!
failure(error)
}
}
}
///// response string (post)
//used this in login // used in change password
class func strRequestPOSTURL(_ strURL : String, params : [String : String]?, headers : [String : String]?, success:#escaping (JSON) -> Void, failure:#escaping (Error) -> Void){
URLCache.shared.removeAllCachedResponses()
Alamofire.request(strURL, method: .post, parameters: params, encoding: URLEncoding.httpBody, headers: headers).responseJSON { (response) in
//print(response)
if response.result.isSuccess {
let resJson = JSON(response.result.value!)
success(resJson)
}
if response.result.isFailure {
let error : Error = response.result.error!
failure(error)
}
}
}
}
I added the certificate to my project by drag and drop it inside the project, please help, I feel my code has some mistakes
thanks in advance
Error -999 is most commonly seen when your SessionManager is deinit'd while being used, causing all of your requests to be cancelled. From your code its looks like you're not using the sessionManager variable you've created with your custom ServerTrustPolicy at all and even if you were it's likely that whatever instance of AFManager you've created is going out of scope, causing the deinit.
You may use sessionManager, I use this class below, it creates array of certificates from your bundle;
class NetworkManager
{
static let sharedInstance = NetworkManager()
var manager: SessionManager?
init()
{
var certificates = ServerTrustPolicy.certificates(in: Bundle.main)
let serverTrustPolicies: [String: ServerTrustPolicy] = [
"yourUrl.com": .pinCertificates(
certificates: ServerTrustPolicy.certificates(in: Bundle.main),
validateCertificateChain: true,
validateHost: true
)
]
manager = SessionManager(
serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
)
}
}
Then I do request like that,
//request depends on your needs. Post, get etc..
var request = URLRequest(url: yourUrl)
request.httpMethod = HTTPMethod.get.rawValue
request.setValue("application/json; charset=UTF-8", forHTTPHeaderField: "Content-Type")
networkManager.manager!.request(request).responseJSON
By the way don't forget to create your networkManager object
var networkManager = NetworkManager.sharedInstance
I am using oAuth2.0 for reading email from my Gmail account. And here is my code
oauthswift = OAuth2Swift(
consumerKey: "242468529977-xxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com",
consumerSecret: "GfGVl_xxxxxxxxxxmjnAX",
authorizeUrl: "https://accounts.google.com/o/oauth2/auth",
accessTokenUrl: "https://accounts.google.com/o/oauth2/token",
responseType: "code"
)
oauthswift?.allowMissingStateCheck = true
let _ = oauthswift?.authorize(
withCallbackURL: URL(string: "urn:ietf:wg:oauth:2.0:oob")!, scope: "https://www.googleapis.com/auth/gmail.metadata", state: "",
success: { credential, response, parameters in
let parameters = Dictionary<String, AnyObject>()
// Multi-part upload
print(credential)
print(response)
},
failure: { error in
print("ERROR: \(error.localizedDescription)")
}
)
but after I allow permission it is showing me this screen
and says 'Please copy this code and switch to application and paste it there.' but I don't know where to paste code.
Please Update Your code with mine one and replace secret with your key.i'm using OAuthSwift library in my project. Also Don't forgot to add URL Type Schemes in your project. and Make Role as Editor
let kClientID = ""
func doOAuthGoogle(){
let oauthswift = OAuth2Swift(
consumerKey: kClientID,
consumerSecret: "",
authorizeUrl: "https://accounts.google.com/o/oauth2/auth",
accessTokenUrl: "https://accounts.google.com/o/oauth2/token",
responseType: "code"
)
// For googgle the redirect_uri should match your this syntax: your.bundle.id:/oauth2Callback
self.oauthswift = oauthswift
oauthswift.authorizeURLHandler = getURLHandler()
// in plist define a url schem with: your.bundle.id:
let _ = oauthswift.authorize(
withCallbackURL: URL(string: "com.cearsinfotech.GmailAttachements:/oauth2Callback")!, scope: "https://www.googleapis.com/auth/gmail", state: "GMAIL",
success: { credential, response, parameters in
// self.showTokenAlert(name: "Gmail", credential: credential)
print(credential.oauthToken)
let jsonDict = try? response?.jsonObject()
print("SUCCESS: \(jsonDict)")
print(parameters)
let _ = oauthswift.client.get("https://www.googleapis.com/gmail/v3/about", success: { response in
let jsonDict:NSDictionary = try! response.jsonObject() as! NSDictionary
print("SUCCESS: \(jsonDict)")
if let arrayMessages = jsonDict.value(forKey:"messages") as? NSArray{
let dict = arrayMessages[2] as! NSDictionary
let id = dict.value(forKey: "id") as! String
let _ = oauthswift.client.get("https://www.googleapis.com/gmail/v1/users/me/messages/\(id)", success: { response in
let jsonDict:NSDictionary = try! response.jsonObject() as! NSDictionary
print("SUCCESS: \(jsonDict)")
if let payload = jsonDict.value(forKey: "payload") as? NSDictionary
{
print(payload)
if let parts = payload.value(forKey: "parts") as? NSArray
{
print(parts)
let partDict = parts[0] as! NSDictionary
if let body = partDict.value(forKey: "body") as? NSDictionary
{
print(body)
}
}
}
}, failure: { error in
print(error)
})
}
}, failure: { error in
print(error)
})
},
failure: { error in
print("ERROR: \(error.localizedDescription)")
//code=4/pYAZQTq2Y5nz0g0hZSAC4wC3AuQLzdJlW6pVjjXDFHM#
}
)
}
You must have to USE Handler Method
//MARK:- Get URL -
func getURLHandler() -> OAuthSwiftURLHandlerType {
guard let type = self.formData.data?.handlerType else {
return OAuthSwiftOpenURLExternally.sharedInstance
}
switch type {
case .external :
return OAuthSwiftOpenURLExternally.sharedInstance
case .`internal`:
if internalWebViewController.parent == nil {
self.addChildViewController(internalWebViewController)
}
return internalWebViewController
case .safari:
#if os(iOS)
if #available(iOS 9.0, *) {
let handler = SafariURLHandler(viewController: self, oauthSwift: self.oauthswift!)
handler.presentCompletion = {
print("Safari presented")
}
handler.dismissCompletion = {
print("Safari dismissed")
}
return handler
}
#endif
return OAuthSwiftOpenURLExternally.sharedInstance
}
}
Go to authorization.py (path: .../python2.7/site-packages/pygsheets/authorization.py)
Currently, the code = input('Enter the authorization code:')
change to
code = 'the code shown in the google page which ask you to copy'
I am trying to extract a post request so it can be re-used and keep my code as DRY as possible bu I'm struggling a little. I started off with:
func createAccount() {
let manager = AFHTTPSessionManager()
let dob = self.dobTextField.text!.components(separatedBy: "/")
let URL = "https://splitterstripeservertest.herokuapp.com/account"
let params = [
"first_name": firstNameTextField.text!.trim(),
"last_name": lastNameTextField.text!.trim(),
"line1": addressLine1TextField.text!.trim(),
"city": cityTextField.text!.trim(),
"postal_code": postCodeTextField.text!.trim(),
"email": emailTextField.text!.trim(),
"day": UInt(dob[0])! as UInt,
"month": UInt(dob[1])! as UInt,
"year": UInt(dob[2])! as UInt] as [String : Any]
manager.requestSerializer = AFHTTPRequestSerializer()
manager.responseSerializer = AFHTTPResponseSerializer()
manager.post(URL, parameters: params, progress: nil, success: {(_ task: URLSessionDataTask, _ responseObject: Any) -> Void in
do {
let response = try JSONSerialization.jsonObject(with: responseObject as! Data, options: .mutableContainers) as? [String: Any]
self.stripeAccountID = response?["id"] as! String
self.stopAnimating()
self.goToFinalStage()
} catch {
print("Serialising new account json object went wrong.")
self.stopAnimating()
}
}, failure: { (operation, error) -> Void in
self.handleError(error as NSError)
self.stopAnimating()
})
}
and have it down to:
func createAccount() {
let request = HttpRequest()
let response = request.post(params: setParams(), URLExtension: "account")
if (response != nil) {
successfulRequest(response: response!)
} else {
failedRequest(response: response!)
}
}
func successfulRequest(response: AnyObject) {
self.stripeAccountID = response["id"] as! String
createMainBillSplitter()
self.stopAnimating()
performSegue(withIdentifier: "segueToFinalRegistrationViewController", sender: self)
}
func failedRequest(response: AnyObject) {
self.stopAnimating()
self.handleError(response["failed"] as! NSError)
}
where HTTPRequest is:
class HttpRequest {
let manager = AFHTTPSessionManager()
let baseURL = "https://splitterstripeservertest.herokuapp.com/account"
func post(params: [String: Any], URLExtension: String) -> AnyObject? {
let URL = baseURL + URLExtension
var response = [String: Any]()
manager.requestSerializer = AFHTTPRequestSerializer()
manager.responseSerializer = AFHTTPResponseSerializer()
manager.post(URL, parameters: params, progress: nil, success: {(_ task: URLSessionDataTask, _ responseObject: Any) -> Void in
do {
response = try JSONSerialization.jsonObject(with: responseObject as! Data, options: .mutableContainers) as! [String: Any]
} catch {
print("Serialising new account json object went wrong.")
}
}, failure: { (operation, error) -> Void in
response = ["failed": error]
})
return response as AnyObject?
}
func handleError(_ error: NSError) -> UIAlertController {
let alert = UIAlertController(title: "Please Try Again", message: error.localizedDescription, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
return alert
}
}
But, I'm getting errors because the response is nil, which I'm sure is because there aren't completion handlers. I just don't understand enough how to implement them in this situation, so would really appreciate a push in the right direction. Thanks in advance!
You are getting confused with sync vs async operations.
The manager.post function will create your http request and will call the success closure when it is done. But since that function is implemented as an async operation, your code will not stop while that http request is being executed. So, your code will continue to be executed, and in your case, the very next line is you returning the response that is basically your empty array of Strings.
func post(params: [String: Any], URLExtension: String) -> AnyObject? {
let URL = baseURL + URLExtension
var response = [String: Any]()
manager.requestSerializer = AFHTTPRequestSerializer()
manager.responseSerializer = AFHTTPResponseSerializer()
manager.post(URL, parameters: params, progress: nil, success: {(_ task: URLSessionDataTask, _ responseObject: Any) -> Void in
// this closure is executed only when the request is completed
do {
response = try JSONSerialization.jsonObject(with: responseObject as! Data, options: .mutableContainers) as! [String: Any]
} catch {
print("Serialising new account json object went wrong.")
}
}, failure: { (operation, error) -> Void in
response = ["failed": error]
})
return response as AnyObject? // <<-- this line is executed right after the manager.post line above, but the success closure was not called yet because the request is still going on.
}
So, what you need to do is to not return the response right after the manager.post was called, but return it from inside the success closure. But you cannot simply use a return response statement. You need to pass the response as a parameter to a callback closure that you would pass to your request.post function.
Something like this:
func createAccount() {
let request = HttpRequest()
let response = request.post(params: setParams(),
URLExtension: "account",
success: {response in
// enter here the code to be executed when request is completed.
successfulRequest(response: response)
},
fail: {response in
failedRequest(response: response)
},)
}
and your class HttpRequest post function would be:
func post(params: [String: Any], URLExtension: String, success:([String: Any] -> Void), fail:([String: Any] -> Void)) -> AnyObject? {
let URL = baseURL + URLExtension
manager.requestSerializer = AFHTTPRequestSerializer()
manager.responseSerializer = AFHTTPResponseSerializer()
manager.post(URL, parameters: params, progress: nil, success: {(_ task: URLSessionDataTask, _ responseObject: Any) -> Void in
do {
response = try JSONSerialization.jsonObject(with: responseObject as! Data, options: .mutableContainers) as! [String: Any]
success(response)
} catch {
print("Serialising new account json object went wrong.")
}
}, failure: { (operation, error) -> Void in
response = ["failed": error]
fail(response)
})
}
PS: your code is assuming that it will always be able to decode the JSON response. Although you are using do / catch, if for some reason the JSON decoding fails, no response is being send back to your calling function. So, the app will just be stuck. I suggest you calling the fail() callback inside your catch block.
I'm trying to create a client (in a private pod) to connect to garmin API (OAuth1) and i've some problem to do it. I'm using OAuthSwift and OAuthSwiftAlamofire
First i'm trying to get all the authorization,
let oauthswift = OAuth1Swift(
consumerKey: "*****************",
consumerSecret: "****************",
requestTokenUrl: "http://connectapitest.garmin.com/oauth-service-1.0/oauth/request_token",
authorizeUrl: "http://connecttest.garmin.com/oauthConfirm",
accessTokenUrl: "http://connectapitest.garmin.com/oauth-service-1.0/oauth/access_token"
)
oauthswift.authorizeURLHandler = SafariURLHandler(viewController: self, oauthSwift: oauthswift)
let _ = oauthswift.authorize(
withCallbackURL: URL(string: "https://www.****.co/api/v2/garminCallback")!,
success: { credential, response, parameters in
print("Success")
print(credential.oauthToken)
print(credential.oauthTokenSecret)
print(credential.oauthVerifier)
},
failure: { error in
print("Error")
print(error.localizedDescription)
})
AppDelegate:
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
if (url.host == "oauth-callback") {
OAuthSwift.handle(url: url)
}
return true
}
So, this part of code open the connection page of garmin in safari, i use my account mail/pwd to connect and that's all. The callback never sucess, or never fail. So i can't access to my credentials. It's like authorize(withCallBackURL...) don't wait the callBack et never get the information in the URL (like oauth-idenfitifier).
I'dont understand why, if you have an idea thank's.
I'm Sharing my Code that's working for me
// create an instance of oAuth and retain it
let oauthSwift = OAuth1Swift(
consumerKey: "*******",
consumerSecret: "*******",
requestTokenUrl: "https://connectapi.garmin.com/oauth-service/oauth/request_token",
authorizeUrl: "https://connect.garmin.com/oauthConfirm",
accessTokenUrl: "https://connectapi.garmin.com/oauth-service/oauth/access_token"
)
// add safari as authorized URL Handler
oauthSwift.authorizeURLHandler = SafariURLHandler(viewController: self, oauthSwift: oauthSwift)
// set redirection URL
guard let redirectURL = URL(string: "oauth-swift://garmin-callback") else { return }
// add callback url to authorized url
oauthSwift.addCallbackURLToAuthorizeURL = true
// authorized the request
oauthSwift.authorize(withCallbackURL: redirectURL, success: { (credentials, response, parameters) in
print(response)
}, failure: { (error) in
print(error)
})
//authorize call has been changed to below
oauthSwift.addCallbackURLToAuthorizeURL = true
oauthSwift.authorize(withCallbackURL: redirectURL) { result in
switch result {
case .success(let (req, response, res)):
print("response=", response ?? "no")
print("req=", req ?? "no")
print("res=", res ?? "no")
print("dataString=",response?.dataString())
if let secrect = res["oauth_token_secret"] as? String{
self.garminAccessTokenSecret = secrect
}
if let token = res["oauth_token"] as? String{
self.garminAccessToken = token
}
case .failure(let error):
print(error.description)
}
}
I'm using OAuthSwift, it works perfectly, but when I click on my Login button, it opens a new Safari page. I would like to open the URL in-app, but I'm beginning and I don't know how do that.
My code :
#IBAction func loginButton(sender: AnyObject) {
doOAuthDribbble()
}
func doOAuthDribbble(){
let oauthswift = OAuth2Swift(
consumerKey: Dribbble["consumerKey"]!,
consumerSecret: Dribbble["consumerSecret"]!,
authorizeUrl: "https://dribbble.com/oauth/authorize",
accessTokenUrl: "https://dribbble.com/oauth/token",
responseType: "code"
)
oauthswift.authorizeWithCallbackURL( NSURL(string: "dribs://oauth-callback/dribbble")!, scope: "public+write+comment+upload", state: "", success: {
credential, response in
// Get User
var parameters = Dictionary<String, AnyObject>()
oauthswift.client.get("https://api.dribbble.com/v1/user?access_token=\(credential.oauth_token)", parameters: parameters,
success: {
data, response in
let jsonDict: AnyObject! = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: nil)
println(jsonDict)
}, failure: {(error:NSError!) -> Void in
println(error)
})
}, failure: {(error:NSError!) -> Void in
println(error.localizedDescription)
})
}
My Login Page
then, the new safari page
In viewDidLoad() of your WebViewController.swift
myUrl = someurl
myWebView.loadRequest(NSURLRequest(URL: NSURL(string: myUrl)!))