Alamofire API(Digest Access Authentication) data access error - ios

I tried Alamofire to communicate with my server API to get the JSON data.
My API uses Digest Access Authentication, but I had problems in facing the server Challenges initially and managed to overcome with below code.
let userNameValue = "username"
let passwordValue = "password"
let credential = URLCredential(user: userNameValue, password: passwordValue, persistence: .forSession)
let sessionMananager = Alamofire.SessionManager.default
let request = sessionMananager.request("http://httpbin.org/basic-auth/\(userNameValue)/\(passwordValue)")
.authenticate(usingCredential: credential)
.responseJSON { response in
print("Response: \(String(describing: response.response))") // http url response
print("Result: \(response.result)") // response serialization result
}
The Output looked like
Response:
{ Status Code: 500, Headers {
Connection = (
close
);
"Content-Length" = (
0
);
"Content-Type" = (
"text/html; charset=UTF-8"
);
} }
Result: FAILURE
After some search I changed .responseJSON to .responseString and the output changed as below
Response:
{ Status Code: 500, Headers {
Connection = (
close
);
"Content-Length" = (
0
);
"Content-Type" = (
"text/html; charset=UTF-8"
);
} }
Result: SUCCESS
To make sure the challenge is handled I gave a wrong password and tried with .responseString, it gave the output with Status Code: 401.
Suggestions Needed
To get the data from API,
Even if Status Code: 500 is an internal error, I don't think it is the problem of server.

I did so like this:
let sessionMananager = Alamofire.SessionManager.default
let credential = URLCredential(user: "bruce", password: "dickinson", persistence: .forSession)
sessionMananager.request("https://httpbin.org/digest-auth/undefined/bruce/dickinson")
.authenticate(usingCredential: credential)
.responseJSON { response in
print("Result: \(String(describing: response.response?.statusCode))")
print(response.result)
print(response.description)
}

Related

Post Request using Alamofire to Node Server

I am consuming a Login API from my node.js server deployed on EB. It works completely file in Postman when I do a post request to :
Secure://mydomain dot com/login
Body :
{
"email" : email,
"password" : password
}
But I am trying to do it in Swift and it keeps throwing errors. Here is my code :
func loginFunction()
{
let loginURL = "login URL"
if let email = emailField.text, let password = passwordField.text
{
let login = [
"email" : email as String,
"password" : password as String]
let headers : HTTPHeaders = ["Content-Type" : "application/json"]
AF.request(URL.init(string: loginURL)!, method: .post, parameters: login,
encoding: JSONEncoding.default, headers: headers).responseString { (response) in
print(response.result)
}
}
}
I keep getting 502 Bad Gateway error, even though it works okay when I test this in Postman. What am I doing wrong?

Alamofire not creating autnentication header to send credentials

I'm attempting to access an api using my username and api key. An example they give, which I believe is .NET, is:
Public Sub GET_Products()
Dim request As HttpWebRequest = WebRequest.Create("https://api.ssactivewear.com/v2/products/?style=39")
request.Method = "GET"
request.Credentials = New NetworkCredential("YOurCustomerNumber", "YourAPIKey")
Try
Dim response As HttpWebResponse = request.GetResponse
Dim StreamReader As New StreamReader(response.GetResponseStream())
Result = StreamReader.ReadToEnd
If response.StatusCode = HtppStatusCode.OK Then
Products = serializer.Deserialize(Of List(Of Sku))(Result)
Else
End If
Catch ex As Exception
End Try
End Sub
I've used the following to test the request for a response:
guard let url = URL(string: "https://api.ssactivewear.com/v2/products/") else { return }
let username = "myusername"
let password = "myapikey"
AF.request(url).authenticate(username: username, password: password).responseJSON { response in
print("Request: \(String(describing: response.request))")
print("Response: \(String(describing: response.response))")
print("HeaderFields: \(String(describing: response.request?.allHTTPHeaderFields))")
if let json = response.value {
print("JSON: \(json)")
//self.responseText.text = "JSON: \(json)"
}
if let error = response.error {
print("ERROR: \(error.localizedDescription)")
//self.responseText.text = "ERROR: \(error.localizedDescription)"
}
}
This fails authentication because no authentication header is sent. I believe I read this is expected behavior but didn't find a solution.
create APIMiddle class:
class APIManager
{
class func headers() -> HTTPHeaders
{
let headers: HTTPHeaders = [
"Content-Type": "application/json",
"Accept": "application/json"
]
return headers
}
}
your api call:
let request = AF.request(path, method: .post, parameters: params, encoding: JSONEncoding.default, headers: APIManager.headers(), interceptor: nil)
request.responseDecodable(of: UserModel?.self) {(resposnse) in
let user = resposnse.value
print(user)
}
Alamofire's authenticate method adds a URLCredential to the Request which is used to respond to server challenges. If the server never sends a challenge for those credentials, the credentials will never be used. api.ssactivewear.com appears to use HTTP Basic auth, which should work fine, but I couldn't find any specific documentation about that. There may be other requirements to properly make a request to the API. I suggest you investigate those requirements as well as the actual network traffic being sent to see what's actually happening.

Filestack iOS getting 400 error "Parameters are invalid" on the image upload

I'm trying to use Filestack iOS SDK inside React Native project. So I passing local file URL from JavaScript and using the following code to upload image
#objc(upload:callback:)
func upload(file: String, callback: #escaping RCTResponseSenderBlock) {
let localURL = URL(string: file)!
client?.upload(from: localURL, uploadProgress: { (progress) in
// Here you may update the UI to reflect the upload progress.
print("progress = \(String(describing: progress))")
}) { (response) in
// Try to obtain Filestack handle
if let json = response?.json, let handle = json["handle"] as? String {
// Use Filestack handle
print(json)
callback([json]);
} else if let error = response?.error {
// Handle error
print(error)
callback([error]);
}
print(response)
}
}
I'm getting progress data so I supose image is uploading. But getting error - aborted
here is a print of response in the MultipartUpload.swift
(request: Optional(https://upload.filestackapi.com/multipart/complete),response: Optional(<NSHTTPURLResponse: 0x6000032664e0> { URL: https://upload.filestackapi.com/multipart/complete } { Status Code: 400, Headers {
"Access-Control-Allow-Headers" = (
"Origin,Content-Type,Accept,User-Agent,UJID,UJID-Path,Filestack-Upload-Region,Filestack-Source"
);
"Access-Control-Allow-Methods" = (
"HEAD,OPTIONS,POST,PUT"
);
"Access-Control-Allow-Origin" = (
"*"
);
Allow = (
"HEAD, OPTIONS, POST, PUT"
);
Connection = (
"keep-alive"
);
"Content-Length" = (
128
);
"Content-Type" = (
"text/plain; charset=utf-8"
);
Date = (
"Thu, 13 Dec 2018 17:11:35 GMT"
);
Server = (
nginx
);
"X-Filestack-Apikey" = (
xxxxxxxxxxxxxx
);
} }), json: Optional(["i": , "c": {
ujid = "c916857b-0a22-4305-9324-6f1055b610f2";
"ujid_path" = "ul-0";
}, "error": Parameters are invalid, "t": 1544721095]), error: nil)
Am I doing anything wrong?
Following pull request https://github.com/filestack/filestack-swift/pull/12 resolve my issue.

Getting token from an asp.net web api in iOS / swift

I am a .net developer but very new to iOS and swift development, just need help with consuming Web API using Swift2
The Asp.net Web API has been built with OAuth2 authentication, published to my Azure VM server with SSL certificate installed. The API site itself works properly, tested through Postman
However I got stuck when started writing first few lines of code in Swift trying to get Authentication token. After reading some online tutorials I decided to engage Alamofire, and produced below codes snippet:
func GetToken() {
let params = [
"grant_type" : "password",
"username" : "123456#qq.com",
"password" : "averygoodpassword"
]
let headers = [
"Content-Type" : "application/x-www-form-urlencoded"
]
request(.POST, "https://api.example.com/token",
parameters: params,
headers: headers,
encoding: .JSON)
.responseJSON { request, response, result in
print (request)
print (response?.description)
print (result)
switch result {
case .Success(let JSON):
print("Success with JSON: \(JSON)")
case .Failure(let data, let error):
print("Request failed with error: \(error)")
if let data = data {
print("Response data: \(NSString(data: data, encoding: NSUTF8StringEncoding)!)")
}
}
}
}
It ends up with below output in Xcode which didn't seem to be OK. The error = unsupported_grant_type told me that the request were sent to server but the parameters were not sent with request properly. I really cannot figure out the reason and solution, had been digging on Internet for a few days but still feeling desperate with it. Can anyone help please? Even if someone can provide a pure swift solution without any 3rd party library will be greatly helpful. Thanks!
Xcode output:
Optional( { URL: https://api.example.com/token })
Optional(" { URL: https://api.example.com/token } { status code: 400, headers {\n \"Access-Control-Allow-Headers\" = \"Content-Type\";\n \"Access-Control-Allow-Methods\" = \"GET, POST, PUT, DELETE, OPTIONS\";\n \"Access-Control-Allow-Origin\" = \"*\";\n \"Cache-Control\" = \"no-cache\";\n \"Content-Length\" = 34;\n \"Content-Type\" = \"application/json;charset=UTF-8\";\n Date = \"Fri, 30 Sep 2016 10:30:31 GMT\";\n Expires = \"-1\";\n Pragma = \"no-cache\";\n Server = \"Microsoft-IIS/8.5\";\n \"X-Powered-By\" = \"ASP.NET\";\n} }")
SUCCESS
Success with JSON: {
error = "unsupported_grant_type";
}
I had a similar problem trying to POST to MailGun for some automated emails I was implementing in an app.
I was able to get this working properly with a large HTTP response. I put the full path into Keys.plist so that I can upload my code to github and broke out some of the arguments into variables so I can have them programmatically set later down the road.
// Email the FBO with desired information
// Parse our Keys.plist so we can use our path
var keys: NSDictionary?
if let path = NSBundle.mainBundle().pathForResource("Keys", ofType: "plist") {
keys = NSDictionary(contentsOfFile: path)
}
if let dict = keys {
// variablize our https path with API key, recipient and message text
let mailgunAPIPath = dict["mailgunAPIPath"] as? String
let emailRecipient = "bar#foo.com"
let emailMessage = "Testing%20email%20sender%20variables"
// Create a session and fill it with our request
let session = NSURLSession.sharedSession()
let request = NSMutableURLRequest(URL: NSURL(string: mailgunAPIPath! + "from=FBOGo%20Reservation%20%3Cscheduler#<my domain>.com%3E&to=reservations#<my domain>.com&to=\(emailRecipient)&subject=A%20New%20Reservation%21&text=\(emailMessage)")!)
// POST and report back with any errors and response codes
request.HTTPMethod = "POST"
let task = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
if let error = error {
print(error)
}
if let response = response {
print("url = \(response.URL!)")
print("response = \(response)")
let httpResponse = response as! NSHTTPURLResponse
print("response code = \(httpResponse.statusCode)")
}
})
task.resume()
}
The Mailgun Path is in Keys.plist as a string called mailgunAPIPath with the value:
https://API:key-<my key>#api.mailgun.net/v3/<my domain>.com/messages?
I'm slightly opposed to using 3rd party libraries, especially for small things like a http POST and this seems like a much more maintainable solution to me. Anyways, hope this helps, let me know if you have any questions!

Twitter API in SWIFT via Alamofire

I currently try to send a simple query - in Postman it works fine for me, but in SWIFT I simply cant get it working
My Code looks like:
func TWITTER_getPosts(username:String){
let headers = [
"screen_name": "username",
"authorization": "OAuth oauth_consumer_key=\"<KEY>\",oauth_token=\"<KEY>\",oauth_signature_method=\"HMAC-SHA1\",oauth_timestamp=\"1469246792\",oauth_nonce=\"n6Sxbq\",oauth_version=\"1.0\",oauth_signature=\"<KEY>\"",
"include_rts": "false"
]
Alamofire.request(.GET, "https://api.twitter.com/1.1/statuses/user_timeline.json", parameters: headers)
.responseJSON { response in
print(response.request) // original URL request
print(response.response) // URL response
print(response.data) // server data
print(response.result) // result of response serialization
if let JSON = response.result.value {
print("JSON: \(JSON)")
}
}
}
I Always end in a
errors = (
{
code = 215;
message = "Bad Authentication data.";
One of the parameters for the request method is incorrect.
If you are passing headers, they shouldn't be passed in parameters, they should be passed as the following:
let headers = [
"Authorization": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==",
"Accept": "application/json"
]
Alamofire.request(.GET, "https://httpbin.org/get", headers: headers)
.responseJSON { response in
debugPrint(response)
}
headers: headers should be the way to go.

Resources