Swift Api Key Authentication - swift

I'm trying to make a simple get request for using Zomato's API to get JSON data. I have an API Key but I'm not sure how to use it in my normal NSURLSession call. I don't have a username or password to provide, just an 32 char API key.
The curl command is given as:
curl -X GET --header "Accept: application/json" --header "user_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxx" "https://developers.zomato.com/api/v2.1/search?entity_id=280&entity_type=city&count=5&cuisines=55"
My request code is here:
let url = NSURL(string: myURL)!
let urlSession = NSURLSession.sharedSession()
//add api key to header somewhere here?
let myQuery = urlSession.dataTaskWithURL(url, completionHandler: { data, response, error -> Void in
//I have some error handling here
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as! NSDictionary
let myArray:NSArray = jsonResult["restaurants"] as! NSArray
})
myQuery.resume()

The documentation for NSURLSession.sharedSession() says:
In other words, if you’re doing anything with caches, cookies, authentication, or custom networking protocols, you should probably be using a custom session instead of the shared session.
You can create your own custom session and include your headers as follows:
let url = NSURL(string: myURL)!
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
config.HTTPAdditionalHeaders = [
"Accept": "application/json",
"user_key": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
]
let urlSession = NSURLSession(configuration: config)
let myQuery = urlSession.dataTaskWithURL(url, completionHandler: {
data, response, error -> Void in
/* ... */
})
myQuery.resume()

Related

Swift - Convert URLRequest to cURL

How to convert URL Request to cURL?
I know there are plugins available in Alamofire / Moya.
But I'm using native code.
Here is how I'm generating URLRequest.
var urlRequest = URLRequest(url: url) // URL is a param herel
var newHeaders: [String: String]
if let cookies = HTTPCookieStorage.shared.cookies {
newHeaders = HTTPCookie.requestHeaderFields(with: cookies)
} else {
newHeaders = [: ]
}
newHeaders = // add few more headers here
urlRequest.allHTTPHeaderFields = newHeaders
urlRequest.httpBody = data // set request body
How to log a cURL of above request?
You can simply try this
URLRequest to cURL
To use it in your code first import that extension and then simply call urlRequest.cURL() or urlRequest.cURL(pretty: true) to print pretty formatted curl.
EDIT: Now the above gist has Alamofire support also

pho.to API Request Failing in Swift

Im currently trying to work with the pho.to API in my iOS application. I am experimenting with making simple requests according to the documentation, however I cannot seem to get the request to go through successfully. Inside my API client file, I have this code:
let dataStr = """
<image_process_call>
<image_url>http://developers.pho.to/img/girl.jpg</image_url>
<methods_list>
<method order="1">
<name>desaturation</name>
</method>
<method order="2">
<name>caricature</name>
<params>type=1;crop_portrait=true</params>
</method>
</methods_list>
<thumb1_size>100</thumb1_size>
</image_process_call>
"""
let encodedStr = dataStr.replacingOccurrences(of: "\n", with: "").replacingOccurrences(of: " ", with: "")
let signData = encodedStr.hmac(key: key)
let urlStr = "https://opeapi.ws.pho.to/addtask/?app_id=\(appId)&key=\(key)&sign_data=\(signData)&data=\(encodedStr.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!))"
The HMAC encoding is being done according to this Stack Overflow post. Unfortunately when making a request to this URL using URLSession I get this response:
<?xml version=\"1.0\"?>\n<image_process_response><status>SecurityError</status><err_code>614</err_code><description>Error in POST parameters: one or more parameters (DATA , SIGN_DATA or APP_ID) are empty</description></image_process_response>
I feel like my issue is more related to actually forming the request rather than something specific to the API itself. I know my code is a little messy, however I was hoping that somebody could point me in the right direction in terms of making a request like this. Thanks!
As per their documentation you can see that data sent over from POST requests are in body (In cURL calls -d specifies the body of the request)
You are sending params/data in query, which the pho.to API doesn't accept, hence the error.
Here's a sample on how you can do:
let defaultSessionConfiguration = URLSessionConfiguration.default
let defaultSession = URLSession(configuration: defaultSessionConfiguration)
// Setup the request with URL
let url = URL(string: "https://opeapi.ws.pho.to/addtask")!
var urlRequest = URLRequest(url: url)
// Convert POST string parameters to data using UTF8 Encoding
let postData = yourXMLString.data(using: .utf8)
// Set the httpMethod and assign httpBody
urlRequest.httpMethod = "POST"
urlRequest.httpBody = postData
// Create dataTask
let dataTask = defaultSession.dataTask(with: urlRequest) { (data, response, error) in
// Handle your response here
}
// Fire the request
dataTask.resume()

AlamoFire Authorization header Oauth

I'm trying to get tweets from a specific user using Alamofire and the twitter API. I have successfully made the call with a cURL command, but I can't make it with AlamoFire. It gives a 215 error for Bad Authentication data.
curl --get 'https://api.twitter.com/1.1/statuses/user_timeline.json' --data 'count=2&screen_name=twitterapi' --header 'Authorization: OAuth oauth_consumer_key="lfa3XmdguuAqu3MoEQ6Fo01s0", oauth_nonce="0d50d7938a68be1ed73bcf02d4cc57e8", oauth_signature="8wZF1F%2B70okWLOi4s7dwKlJKc5w%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1460320508", oauth_version="1.0"' --verbose
let key = "lfa3XmdguuAqu3MoEQ6Fo01s0"
let secret = "25EUfqUstgdjZFgYnecrYuPkG6fDkruCjRXr905kM7475W2G63"
let data = ["screen_name": "twitterapi", "count": 2]
let path = "https://api.twitter.com/1.1/statuses/user_timeline.json"
Alamofire.request(.GET, path, parameters: data)
.authenticate(user: key, password: secret)
.responseJSON { response in
if let JSON = response.result.value {
print("JSON: \(JSON)")
}
}
How do I give the custom header Authorization in AlamoFire? I think I need an auth token, but I'm not sure where to start getting those. thanks
To give a custom Authorization, you have to do this:
let headers = ["Authorization": "Bearer \(Token.sharedInstance.value!)"]
Alamofire.request(.PUT, url, headers: headers, parameters: data, encoding: .JSON).responseJSON { response in
}
Token Class:
class Token {
var value:String?
static let sharedInstance = Token()
private init() { }
}

Setting Headers for OAuth Authenticated User (Bearer)

I am experimenting on OAuth2 (on Laravel) & Swift with Alamofire. I successfully got token, however I couldn't set the headers to be able to get authenticate-specific data from Api.
Without Alamofire, I was setting this header and it was working.
func me(handler: (data: NSDictionary?, error: String?) -> Void)
{
let url = NSURL(string: "/me", relativeToURL: self.baseUrl)
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "GET"
if let t = self.getAccessToken()
{
request.setValue("Bearer \(t)", forHTTPHeaderField: "Authorization")
}
}
However I didn't get what to do with Alamofire.
Now I can use getAccessToken() to get token as a string, but I got really confused adapting it to Alamofire style.
I tried this but doesn't pass the authentication middleware for a reason:
let token = getAccessToken()
print(token!) // prints
let headers = ["Authorization":"Bearer \(token)"]
Alamofire.request(.GET, userDetailsEndpoint!, headers: headers)...
Still getting error The resource owner or authorization server denied the request

How to convert cURL form login code to Swift

I am trying to login (form) into a website and parse data with Swift and NSURLSession.
I have been using cURL to confirm that this is actually possible, and the following code returns the webpage-body as expected.
curl -c cookie.txt -d "username=karl" -d "password=ivar" https://talkmore.no/talkmore3/servlet/Login
curl -b cookie.txt https://talkmore.no/talkmore3/servlet/SubscriptionUsage
When I am trying to do this in Swift, I fetch the Cookie from the response header, then I try to retrieve the SubscriptionUsage-webpage by passing the cookie along. However I cannot get this to work.
How can I convert this simple curl syntax to Swift-code using NSURLSession?
Edit: What I've got so far.
func login() -> Void {
var session = NSURLSession.sharedSession()
var request = NSMutableURLRequest(URL: NSURL(string: "https://www.talkmore.no/talkmore3/servlet/Login")!)
request.HTTPMethod = "POST"
var params = "username=karl&password=ivar"
request.HTTPBody = params.dataUsingEncoding(NSUTF8StringEncoding)
request.addValue("text/html", forHTTPHeaderField: "Content-Type")
var task = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) -> Void in
println("Response: \(response)")
println("Data: \(NSString(data: data, encoding: NSUTF8StringEncoding)))")
let httpResponse = response as NSHTTPURLResponse
var cookie = httpResponse.allHeaderFields["Set-Cookie"] as String
})
task.resume()
All seems good, I receive the response with a header including "Set-Cookie" = "JSESSIONID=D8307BA498EFE061C86636C51B8AC25D; Path=/talkmore3/; Secure; HttpOnly"; And I believe I have to send this cookie with the next request. But I have failed to replicate the cURL behavior.