These are request headers:
let headers: HTTPHeaders = [
"Accept": "application/json",
"username": "someUserName",
"password": "aPasswordForSomeUserName"
]
When making a request with below code it's giving me "Garbage at the end". However, when I checked the response with JSON parser online. It's a valid JSON.
Alamofire.request("http://myserver/list.svc/random", headers: headers).responseJSON { response in
print(response)
}
I also tried making a request like this:
Alamofire.request("http://myserver/list.svc/random", headers: headers).responseString { response in
print(response)
}
I am getting this message in console: "401 UNAUTHORIZED".
What am I doing wrong? I believe, when using responseJSON completion block it's not complaining about Unauthorization, but it's complaining about bad JSON (or some garbage).
P.S. The same request works fine with Advance Rest Client (a chrome extension) and also in chrome browser.
I don't know how relevant this is to you anymore but I've got a working solution I'll post for any future reference.
So, I had two issues. The first one being that the Authorization header fell of the request when it was redirected. The second one being the NTLM-challenge from the server not being handled. The following code should be quite self explanatory I hope :) It asumes you store the username and password in variables name just that.
let credentialData = "\(username):\(password)".data(using: String.Encoding.utf8)!
let base64Credentials = credentialData.base64EncodedString(options: [])
request.addValue("Basic \(base64Credentials)", forHTTPHeaderField: "Authorization")
let manager = Alamofire.SessionManager.default
let delegate: Alamofire.SessionDelegate = manager.delegate
// This bit will re-add the auth headers for the redirected request
delegate.taskWillPerformHTTPRedirection = { session, task, response, request in
var redirectedRequest = request
if let originalRequest = task.originalRequest, let redirectheaders = originalRequest.allHTTPHeaderFields {
if let authorizationHeaderValue = redirectheaders["Authorization"] {
redirectedRequest.setValue(authorizationHeaderValue, forHTTPHeaderField: "Authorization")
}
if let contentTypeHeaderValue = redirectheaders["Content-Type"] {
redirectedRequest.setValue(contentTypeHeaderValue, forHTTPHeaderField: "Content-Type")
}
}
return redirectedRequest
}
// This bit looks at challenges received and applies the correct credentials
delegate.taskDidReceiveChallenge = { session, task, challenge in
var disposition: URLSession.AuthChallengeDisposition = .useCredential
var credential: URLCredential = URLCredential()
if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodNTLM) {
disposition = URLSession.AuthChallengeDisposition.useCredential
credential = URLCredential(user: username, password: password, persistence: URLCredential.Persistence.forSession)
}
if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
disposition = URLSession.AuthChallengeDisposition.useCredential
credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
}
return(disposition, credential)
}
manager.request(request).responseData { (response) in
// Handle response accordingly
}
Hope this helps someone.
In Swift4.2
Alamofire has built in NTLM auth support.
You can make a request like that
let user = "YOUR_USER_NAME OR EMAIL"
let password = "YOUR_PASSWORD"
let url = "YOUR_API_URL"
let credential = URLCredential(user: user, password: password, persistence: .forSession)
//These headers are optional based on your api and your server.
//There were required for me
let headers = ["Accept": "application/json;odata=verbose",
"Content-type": "application/json;odata=verbose"]
Alamofire.request(url, method: .get, headers: headers).authenticate(usingCredential: credential).responseJSON {
(response) in
switch response.result {
case .success:
if let value = response.result.value {
print("The server response is: ", value)
}else{
print("There is error in the server response")
}
case .failure (let error):
print("The NTLM request error is: ", error.localizedDescription)
}
}
Related
I am trying to integrate braintree payment method in my swift code, but I am stuck in here, it is breaking with an error
{"error":{"statusCode":401,"name":"Error","message":"Authorization Required","code":"AUTHORIZATION_REQUIRED"}}
I have doing exactly the same as mentioned in braintree documentation. I don't know which authorization it is demanding, I do have a authorization token assigned to user when he/she logins, I am wondering if it is demanding that authorization token, but there is no such parameter in this code where I should place that token to generate client's token for payment method. Here the print statement when exeuted gives me this in log, "client Token is :
{"error":{"statusCode":401,"name":"Error","message":"Authorization Required","code":"AUTHORIZATION_REQUIRED"}}", I am bit confused in its calling also. I have just started these thing so I am very sorry I have done any obvious mistake. Thanks.
// TODO: Switch this URL to your own authenticated API
let clientTokenURL = NSURL(string: "https://braintree-sample-
merchant.herokuapp.com/client_token")!
let clientTokenRequest = NSMutableURLRequest(url:
clientTokenURL as URL)
clientTokenRequest.setValue("text/plain", forHTTPHeaderField:
"Accept")
URLSession.shared.dataTask(with: clientTokenRequest as
URLRequest) { (data, response, error) -> Void in
// TODO: Handle errors
if let error = error {
print("Error: \(error.localizedDescription)")
} else {
print("in Session")
let clientToken = String(data: data!, encoding:
String.Encoding.utf8)!
print("Client Token is : \(clientToken)")
}
}.resume()
}
One have to give authorization token in headers to avoid this error. Rather than that, this version of code will work fine.
completionHandler:#escaping (_ response: NSDictionary?, _ error: Error?) -
> ()) {
var headers: HTTPHeaders
// pass the authToken when you get when user login
let authToken = getAuthorizationToken()
if(self.isValidString(object: authToken as AnyObject)) {
headers = ["Authorization": authToken,
"Content-Type": "application/json",
"Accept": "application/json"]
} else {
headers = ["Content-Type": "application/json"]
}
AF.request(apiURL, method: .get, parameters: params as? Parameters,
encoding: JSONEncoding.default, headers: headers).validate().responseJSON
{
response in
self.handleResposne(response: response) { (response, error) in
completionHandler(response, error)
}
}
}
I need to make a request to my own API, and the backend guy requires basic authentication when making request and also I have to put the token in the header. I am using Alamofire when making request to the API.
here is the basic authentication in postman
and here is the X-API-KEY token in the header
but I don't know how to implement both of basic auth and X-API-KEY token in the header. previously I can send request if just using basic authentication using the code below, But i have no idea how to make a request if both of them (Basic authentication and X-API-KEY token in the header) are required when making request using alamofire;
let urlSendDefect = URLService.defects.endPoint
let username = "admin"
let password = "1234"
var headers: HTTPHeaders = [:]
if let authorizationHeader = Request.authorizationHeader(user: username, password: password) {
headers[authorizationHeader.key] = authorizationHeader.value
}
let parameters : [String:Any] = ["defect_id": defectID, "defect_comment" : comment, "status" : status]
Alamofire.request(urlSendDefect,
method: .put,
parameters: parameters,
encoding: URLEncoding.default,
headers:headers)
.validate()
.responseJSON { response in
switch response.result {
case .failure(let error) :
print("Error while making request to send defect comment to server: \(error.localizedDescription)")
completion(nil,error)
case .success(let value) :
let json = JSON(value)
if let message = json["message"].string {
if message.isEmpty {
completion(nil,nil)
} else {
completion(message,nil)
}
} else {
completion(nil,nil)
}
}
}
Can you try to construct it like this
let headers : HTTPHeaders = ["Content-Type":"application/json",
"Authorization":"Basic \(Your_token)"]
and add any other key-value that you want
all.
I can get authentication token by login. but I can authenticate on my server by swift and alamofire.
this is Postman. as you see, if i have token, i can be authenticated on myserver.
this is swift viewcontroller.
import UIKit
import Alamofire
import SwiftyJSON
import KeychainAccess
class ViewController: UIViewController {
let authLoginUrl = "http://ec2-52-79-155-29.ap-northeast-2.compute.amazonaws.com:8000/rest-auth/login/"
let keychain = Keychain(service: "wanote")
let projectUrl = "http://ec2-52-79-155-29.ap-northeast-2.compute.amazonaws.com:8000/api/user/ryulstory"
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let username = "username"
let password = "1234!"
self.doAuth(username: username, password: password)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func doAuth(username:String, password:String) {
let params = ["username": username, "password": password]
var authToken = Alamofire.request(self.authLoginUrl, method: .post, parameters: params)
authToken.responseJSON { response in
let statusCode = response.response?.statusCode ?? 0
switch statusCode {
case 200...299:
let jsonData = JSON(response.result.value)
if let token = jsonData["key"].string{
self.keychain["token"] = token
self.getProjects()
}
case 400...499:
print("Server responded no")
case 500...599:
print("Server error")
default:
print("There was an error with your request")
}
}
}
func getProjects(){
if let token = self.keychain["token"] {
if let Purl = URL(string: self.projectUrl){
var mutableUrlRequest = URLRequest(url: Purl)
mutableUrlRequest.httpMethod = "GET"
mutableUrlRequest.setValue("Token " + token, forHTTPHeaderField: "Authorization")
var manager = Alamofire.SessionManager.default
var getProjectsRequest = manager.request(mutableUrlRequest)
getProjectsRequest.responseJSON { response in
print(response.data)
}
}
} else {
print("no token")
}
}
}
I checked getting token by function doAuth. it is correctly operating.
function getprojects makes error status code 401.
I think there are problem in function getprojects. but i can't find it.
could you help me?
Best regards.
It goes to 401 because you are sending the request without the header authorization.
With Alamofire you can set the header Authorization like this.
let url = "URL_LOGIN"
//Get token logic
let token = ""
let headers = ["Authorization": "Token \(token)"]
let params = ["user": "", "pass":""] //This goes in the body of the request
Alamofire.request(url, method: .post, parameters: params, encoding: URLEncoding.default, headers: headers).responseJSON { (response) in
if let value = response.result.value {
print(value)
}
}
With this you'll send the headers in the request to get what you want.
I think this part have the header authorization.
is it wrong?
mutableUrlRequest.httpMethod = "GET"
mutableUrlRequest.setValue("Token " + token, forHTTPHeaderField: "Authorization")
var manager = Alamofire.SessionManager.default
var getProjectsRequest = manager.request(mutableUrlRequest)
These are my input
1.parameters
let parameters: Parameters = ["username ": "Henry","password":"xxxx","key"="ewq2356"]
2.http header
let headers = [ "Authorization": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==", "Content-Type": "application/x-www-form-urlencoded" ]
3.Authentication with URLCredential
let user = "user1" let password = "password1"
4.URL
http://myapi.com/rest/index.php
So how could I use it using Almofire http post method ?
Sample api ->
func someFunction()
{
Alamofire.request(.POST, "apiName",
parameters:["Key":"Value"],
headers: ["Content-type application":"json"])
.authenticate(user: "userName", password: "Password")
.response { request, response, data, error in
if error == nil {
print(request)
print(response)
}
else {
//Display Error Message
print(error)
}
}
}
I'm using Alamofire to do a simple request
Alamofire.request(.GET, URL)
.authenticate(user: user, password: password)
.responseJSON { response in
...
}
After a first valid request, I changed the credential with invalid ones and the request succeed, but it should fail.
How can I invalidate previous credentials?
After a successful request, if I change the credential, Alamofire authenticates the previous credential.
How can I invalidate previous credentials?
I experienced exactly the same thing. iOS's answer should work, anyway I will provide code snippet using swift3 for someone to reduce research time.
let user = "aaaaa"
let password = "myPassword"
let plainString = "\(user):\(password)"
let plainData = plainString.data(using: .utf8)
let base64String = plainData?.base64EncodedString(options:NSData.Base64EncodingOptions(rawValue: 0))
let authString = "Basic " + base64String!
// Set in in Authorize header like...
let headers: HTTPHeaders = [
"Authorization": authString,
"Accept": "application/json"
]
// And use it like this..
Alamofire.request("https://httpbin.org/headers", headers: headers).responseJSON { response in
debugPrint(response)
}
Here is where this case was discussed >> https://github.com/Alamofire/Alamofire/issues/32
Adding Authorization header helped me.
let user = "user"
let password = "password"
let credentialData = "\(user):\(password)".dataUsingEncoding(NSUTF8StringEncoding)!
let base64Credentials = credentialData.base64EncodedStringWithOptions([])
let headers = ["Authorization": "Basic \(base64Credentials)"]
Alamofire.request(.GET, "https://httpbin.org/basic-auth/user/password", headers: headers)
.responseJSON { response in
debugPrint(response)
}