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() { }
}
Related
I am trying to get a Client Credential token, which is needed for Spotify's public Web API to search for public tracks.
It is extremely simple to get a token using postman.
REQUEST BODY PARAMETER: VALUE: grant_type Set it to client_credentials.
The header of this POST request must contain the following parameter:
HEADER PARAMETER: VALUE: Authorization Base 64 encoded string that contains the client ID and client secret key. The field must have the format: Authorization: Basic <base64 encoded client_id:client_secret>
I need to get a Spotify token in Swift. I started with this decodable struct:
struct SpotifyAuth: Decodable {
var access_token: String
var expires_in: Int
}
I have then tried dozens of variations of the following code to no avail:
let headers : HTTPHeaders = ["Content-Type":"application/x-www-form-urlencoded"]
let paramaters : Parameters = ["grant_type": "client_credentials", ]
AF.request("https://accounts.spotify.com/api/token", method: .post, parameters: paramaters, encoding: URLEncoding.httpBody, headers: headers ).authenticate(username: "{clientID}", password:"{clientSecrent}").responseJSON { response in
if response.error == nil {
do {
let spotifyAuth = try JSONDecoder().decode(SpotifyAuth.self, from: response.data!)
completion(.success(spotifyAuth))
} catch let error {
completion(.failure(error))
}
} else {
completion(.failure(response.error!))
}
}
Is anyone aware of what I am doing wrong/the correct way of acquiring a simple token from Spotify?
authenticate() is used to respond to authentication challenges. It does not unconditionally add the header. If the server does not respond with a Basic challenge you'll need to add the header yourself. Alamofire has a convenience method to help: HTTPHeader.authorization(username:password:). This will properly generate the Basic header for you.
My API includes authorization bearer token and three additional headers. My problem is I'm not sending the bearer token right (Postman return the correct data not my simulator). I see a lot of examples for using the request adapter but can I not use that? Thanks!
The auth is actually in the authorization tab not in the header.
**Updated:
Solved the problem by following the documentation.
HTTP Headers
Here is the Alamofire function with working codes:
func getBetsData(completion: ((Bool) -> ())? = nil) {
guard let token = defaults.string(forKey: "token") else {
return
}
let headers: HTTPHeaders = [
.authorization(bearerToken: token),
.init(name: "bet_type", value: type),
.init(name: "bet_status", value: status),
.init(name: "page", value: String(page))
]
AF.request("https://example.com", headers: headers).responseDecodable(of: Bets.self) { response in
switch response.result {
case .success:
if let data = response.data {
do {
let bets = try JSONDecoder().decode(Bets.self, from: data)
print("message: \(bets.message)")
self.setupTableData()
completion?(true)
} catch {
print("Error: \(error)")
completion?(false)
}
}
case.failure(let error):
print(error)
completion?(false)
}
}
}
You can add the headers directly:
let headers: HTTPHeaders = [.authorization(bearerToken: token)]
Additionally, if you're decoding a Decodable value from the response, you should not use responseJSON, as that decodes the Data using JSONSerialization and then you just parse it again. Instead, you should use responseDecodable.
AF.request(...).responseDecodable(of: Bets.self) { response in
// Use response.
}
That will be much more efficient and will capture errors for you automatically.
As mention by Dilan only token is not enought you will need to Bearer in the same Header parameter.
Here is one of the best method to handle Token Request and Retrier in all the request you send to server in the application
https://www.avanderlee.com/swift/authentication-alamofire-request-adapter/
By this you don't need to handle token manually in all the webservice.
I'm trying to find the correct syntax for calling ecobee's API from Swift 4 using Alamofire.
Their cURL example:
curl -H "Content-Type: text/json" -H "Authorization: Bearer ACCESS_TOKEN" 'https://api.ecobee.com/1/thermostat?format=json&body=\{"selection":\{"selectionType":"registered","selectionMatch":"","includeRuntime":true\}\}'
The closest I've been to a solution is this
func doRequest() {
guard let url = URL(string: "https://api.ecobee.com/1/thermostat?format=json") else { return }
let parameters: Parameters = [
"selection": [
"selectionType": "registered",
"selectionMatch": ""
]
]
let headers: HTTPHeaders = [
"Content-Type": "text/json",
"Authorization": "Bearer \(core.accessToken)"
]
let req = AF.request(url, method: .get, parameters: parameters, encoding: JSONEncoding.default, headers: headers)
.responseJSON { response in
print("Error:", response.error?.localizedDescription ?? "no error")
print("Data:", String(data: response.data!, encoding: .utf8)!)
}
debugPrint(req)
}
When I run this, the call ultimately fails with status code 408, a server timeout.
When I change the HTTP method to use .post, the call completes, but the response is an internal status 3 with message "Update failed due to a communication error."
Can anyone help me figure out what I'm doing wrong before I waste another day trying to hack my way through it?
Ecobee's request format is a bit bizarre, as it uses form encoded parameters, but one of the values is a JSON encoded body. You'll have to do a little bit of prep work, as Alamofire doesn't naturally support something like this. This is just sample code, you'll need to do the work to make it safer.
First, encode the JSON parameters and get the String value:
let jsonParameters = ["selection": ["selectionType": "registered", "selectionMatch": ""]]
let jsonData = try! JSONEncoder().encode(jsonParameters)
let jsonString = String(decoding: jsonData, as: UTF8.self)
Then, create the actual parameters and headers values:
let parameters = ["format": "json", "body": jsonString]
let token = "token"
let headers: HTTPHeaders = [.authorization(bearerToken: token), .contentType("text/json")]
let url = URL(string: "https://api.ecobee.com/1/thermostat")!
And make the request:
AF.request(url, parameters: parameters, headers: headers).responseJSON { response in ... }
I want to validate the OTP of created user. I'm using POST RESTful API for this. All created user have their Auth token. So when i'm validating the user OTP, it says 'Invalid Authentication', but i'm sending the Token in the POST Request Header?
Here is my code :-
let urlString = "http://192.168.182.81:8080/serviceplus/user/validateotp.json"
if let url = NSURL(string: urlString) {
let URLRequest = NSMutableURLRequest(URL: url)
let headers = [
"Authorization": "\(token)",
"Accept": "application/json"
]
Alamofire.request(.POST, URLRequest, headers: headers, parameters: ["otpcode": fields[0].text!]).responseJSON { response in
print("Error :- \(response.result.error)")
print("Result values :- \(response.result.value)")
}
}
What should i do?
Thanks.. :)
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()