How to make an HTTP request + basic auth in Swift

I have a RESTFull service with basic authentication and I want to call it from iOS + swift. How and where should I provide credentials for this request?

My code (sorry, I'm just starting to learn iOS / obj-c / swift):

class APIProxy: NSObject { var data: NSMutableData = NSMutableData() func connectToWebApi() { var urlPath = "http://xx.xx.xx.xx/BP3_0_32/ru/hs/testservis/somemethod" NSLog("connection string \(urlPath)") var url: NSURL = NSURL(string: urlPath) var request = NSMutableURLRequest(URL: url) let username = "hs" let password = "1" let loginString = NSString(format: "%@:%@", username, password) let loginData: NSData = loginString.dataUsingEncoding(NSUTF8StringEncoding) let base64LoginString = loginData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.fromMask(0)) request.setValue(base64LoginString, forHTTPHeaderField: "Authorization") var connection: NSURLConnection = NSURLConnection(request: request, delegate: self) connection.start() } //NSURLConnection delegate method func connection(connection: NSURLConnection!, didFailWithError error: NSError!) { println("Failed with error:\(error.localizedDescription)") } //NSURLConnection delegate method func connection(didReceiveResponse: NSURLConnection!, didReceiveResponse response: NSURLResponse!) { //New request so we need to clear the data object self.data = NSMutableData() } //NSURLConnection delegate method func connection(connection: NSURLConnection!, didReceiveData data: NSData!) { //Append incoming data self.data.appendData(data) } //NSURLConnection delegate method func connectionDidFinishLoading(connection: NSURLConnection!) { NSLog("connectionDidFinishLoading"); } 

}

+55
ios swift
Jun 24 '14 at 6:20
source share
7 answers

You provide credentials in an instance of URLRequest , such as in Swift 3:

 let username = "user" let password = "pass" let loginString = String(format: "%@:%@", username, password) let loginData = loginString.data(using: String.Encoding.utf8)! let base64LoginString = loginData.base64EncodedString() // create the request let url = URL(string: "http://www.example.com/")! var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("Basic \(base64LoginString)", forHTTPHeaderField: "Authorization") // fire off the request // make sure your class conforms to NSURLConnectionDelegate let urlConnection = NSURLConnection(request: request, delegate: self) 

Or in NSMutableURLRequest in Swift 2:

 // set up the base64-encoded credentials let username = "user" let password = "pass" let loginString = NSString(format: "%@:%@", username, password) let loginData: NSData = loginString.dataUsingEncoding(NSUTF8StringEncoding)! let base64LoginString = loginData.base64EncodedStringWithOptions([]) // create the request let url = NSURL(string: "http://www.example.com/") let request = NSMutableURLRequest(URL: url) request.HTTPMethod = "POST" request.setValue("Basic \(base64LoginString)", forHTTPHeaderField: "Authorization") // fire off the request // make sure your class conforms to NSURLConnectionDelegate let urlConnection = NSURLConnection(request: request, delegate: self) 
+104
Jun 24 '14 at 7:34
source

// create the encoding string of the authentication database

  let PasswordString = "\(txtUserName.text):\(txtPassword.text)" let PasswordData = PasswordString.dataUsingEncoding(NSUTF8StringEncoding) let base64EncodedCredential = PasswordData!.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.Encoding64CharacterLineLength) //let base64EncodedCredential = PasswordData!.base64EncodedStringWithOptions(nil) 

// create authentication URL

  let urlPath: String = "http://...../auth" var url: NSURL = NSURL(string: urlPath) 

// create and initialize a basic authentication request

  var request: NSMutableURLRequest = NSMutableURLRequest(URL: url) request.setValue("Basic \(base64EncodedCredential)", forHTTPHeaderField: "Authorization") request.HTTPMethod = "GET" 

// You can use one of the following methods

// 1 URL request with NSURLConnectionDataDelegate

  let queue:NSOperationQueue = NSOperationQueue() let urlConnection = NSURLConnection(request: request, delegate: self) urlConnection.start() 

// 2 Request a URL using AsynchronousRequest

  NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {(response, data, error) in println(NSString(data: data, encoding: NSUTF8StringEncoding)) } 

// 2 Request a URL using AsynchronousRequest with json output

  NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler:{ (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in var err: NSError var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary println("\(jsonResult)") }) 

// 3 Request URL with SynchronousRequest

  var response: AutoreleasingUnsafePointer<NSURLResponse?>=nil var dataVal: NSData = NSURLConnection.sendSynchronousRequest(request, returningResponse: response, error:nil) var err: NSError var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(dataVal, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary println("\(jsonResult)") 

// 4 Request URL with NSURLSession

  let config = NSURLSessionConfiguration.defaultSessionConfiguration() let authString = "Basic \(base64EncodedCredential)" config.HTTPAdditionalHeaders = ["Authorization" : authString] let session = NSURLSession(configuration: config) session.dataTaskWithURL(url) { (let data, let response, let error) in if let httpResponse = response as? NSHTTPURLResponse { let dataString = NSString(data: data, encoding: NSUTF8StringEncoding) println(dataString) } }.resume() 

// you can get a fatal error if you change request.HTTPMethod = "POST" when requesting a GET server request

+18
Oct 03 '14 at 4:42
source

In Swift 2:

 extension NSMutableURLRequest { func setAuthorizationHeader(username username: String, password: String) -> Bool { guard let data = "\(username):\(password)".dataUsingEncoding(NSUTF8StringEncoding) else { return false } let base64 = data.base64EncodedStringWithOptions([]) setValue("Basic \(base64)", forHTTPHeaderField: "Authorization") return true } } 
+6
Dec 17 '15 at 17:47
source

my solution works as follows:

 import UIKit class LoginViewController: UIViewController, NSURLConnectionDataDelegate { @IBOutlet var usernameTextField: UITextField @IBOutlet var passwordTextField: UITextField @IBAction func login(sender: AnyObject) { var url = NSURL(string: "YOUR_URL") var request = NSURLRequest(URL: url) var connection = NSURLConnection(request: request, delegate: self, startImmediately: true) } func connection(connection:NSURLConnection!, willSendRequestForAuthenticationChallenge challenge:NSURLAuthenticationChallenge!) { if challenge.previousFailureCount > 1 { } else { let creds = NSURLCredential(user: usernameTextField.text, password: passwordTextField.text, persistence: NSURLCredentialPersistence.None) challenge.sender.useCredential(creds, forAuthenticationChallenge: challenge) } } func connection(connection:NSURLConnection!, didReceiveResponse response: NSURLResponse) { let status = (response as NSHTTPURLResponse).statusCode println("status code is \(status)") // 200? Yeah authentication was successful } override func viewDidLoad() { super.viewDidLoad() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } } 

This class can be used as an implementation of ViewController. Connect your fields to annotated vars for IBOutlet and your Button to annotated IBAction function.

Explanation: In the login function, you create your request with NSURL, NSURLRequest, and NSURLConnection. The essential thing here is the delegate that refers to this class (itself). To receive delegate calls you need to

  • Add NSURLConnectionDataDelegate protocol to class
  • Implementing the protocol function "connection: willSendRequestForAuthenticationChallenge" This is used to add credentials to the request
  • Implementing the protocol function "connection: didReceiveResponse" This will check the HTTP response status code
+1
Jun 30 '14 at 17:19
source

I call json when I click the login button

 @IBAction func loginClicked(sender : AnyObject){ var request = NSMutableURLRequest(URL: NSURL(string: kLoginURL)) // Here, kLogin contains the Login API. var session = NSURLSession.sharedSession() request.HTTPMethod = "POST" var err: NSError? request.HTTPBody = NSJSONSerialization.dataWithJSONObject(self.criteriaDic(), options: nil, error: &err) // This Line fills the web service with required parameters. request.addValue("application/json", forHTTPHeaderField: "Content-Type") request.addValue("application/json", forHTTPHeaderField: "Accept") var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in // println("Response: \(response)") var strData = NSString(data: data, encoding: NSUTF8StringEncoding) println("Body: \(strData)") var err1: NSError? var json2 = NSJSONSerialization.JSONObjectWithData(strData.dataUsingEncoding(NSUTF8StringEncoding), options: .MutableLeaves, error:&err1 ) as NSDictionary println("json2 :\(json2)") if(err) { println(err!.localizedDescription) } else { var success = json2["success"] as? Int println("Succes: \(success)") } }) task.resume() } 

Here I made a separate dictionary for the parameters.

 var params = ["format":"json", "MobileType":"IOS","MIN":"f8d16d98ad12acdbbe1de647414495ec","UserName":emailTxtField.text,"PWD":passwordTxtField.text,"SigninVia":"SH"]as NSDictionary return params } 
+1
Sep 06 '14 at 5:34
source

I had a similar problem with trying POST for MailGun for some automatic emails that I implemented in the application.

I managed to get this to work with a great HTTP response. I put the full path in Keys.plist to upload my code to github and break some arguments into variables so that I can set them programmatically later on the way.

 // 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 named mailgunAPIPath with the value:

 https://API:key-<my key>@api.mailgun.net/v3/<my domain>.com/messages? 

Hope this helps find a solution for those trying to avoid using third-party code for their POST requests!

+1
Oct 03 '16 at 2:55
source

Switch to normal mode for SWIFT 3 and APACHE simple Auth:

 func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { let credential = URLCredential(user: "test", password: "test", persistence: .none) completionHandler(.useCredential, credential) } 
+1
Oct 10 '16 at 14:35
source



All Articles