4

This is the code I'm using to send a request using a proxy host and port. I know the implementation is correct because I'm getting a 407 status code (proxy authentication required). I don't know why the username/password to the proxy server aren't working. The credentials are correct and the proxies are active.

class Request: NSOperation, NSURLSessionDelegate {
    private var URL:NSURL = NSURL()
    private var method: String
    private var params: String
    private var session: NSURLSession = NSURLSession.sharedSession()
    private var cookies: [NSHTTPCookie] = [NSHTTPCookie]()
    private var httpResponse: NSHTTPURLResponse?
    private var contentsOfURL: String?
    private var statusCode: Int?
    var isConnecting = false

    var shouldUseProxy = false
    var proxyHost:CFString!
    var proxyPort:CFNumber!
    var proxyUser:CFString!
    var proxyPW:CFString!

    init(URL: NSURL, method: String, params: String, cookies:[NSHTTPCookie]) {
        self.URL = URL
        self.params = params
        self.method = method
        self.cookies = cookies
    }

    override func main() -> () {
        let request = NSMutableURLRequest(URL: self.URL)
        request.HTTPMethod = self.method
        if method == "POST" {
            request.HTTPBody = params.dataUsingEncoding(NSUTF8StringEncoding)
        }
        if self.shouldUseProxy {
            let proxyEnable = NSNumber(int: 1) as NSNumber
            let proxyDict: [NSObject:AnyObject] = [
                kCFNetworkProxiesHTTPEnable: proxyEnable,
                kCFStreamPropertyHTTPProxyHost: self.proxyHost,
                kCFStreamPropertyHTTPProxyPort: self.proxyPort,
                kCFStreamPropertyHTTPSProxyHost: self.proxyHost,
                kCFStreamPropertyHTTPSProxyPort: self.proxyPort,
                kCFProxyTypeKey: kCFProxyTypeHTTPS,
                kCFProxyUsernameKey: self.proxyUser,
                kCFProxyPasswordKey: self.proxyPW
            ]
            let config = NSURLSessionConfiguration.ephemeralSessionConfiguration()
            config.connectionProxyDictionary = proxyDict
            self.session = NSURLSession.init(configuration: config, delegate: self, delegateQueue: NSOperationQueue())
        }

        let task = session.dataTaskWithRequest(request) {
                (data, response, error) in
                if error == nil {
                    let httpResponse = response as! NSHTTPURLResponse
                    let statusCode = httpResponse.statusCode
                    print("statusCode \(statusCode)")
                }
            self.isConnecting = false
        }
        task.resume()
    }
}
dbconfession
  • 1,147
  • 2
  • 23
  • 36
  • 1
    Did you sniff the network connection (e.g. using Charles) to check what's sent over the wire? Does it work using HTTP instead of HTTPS? HTTP would be easier for debugging. – Ortwin Gentz May 03 '16 at 07:48
  • I read a little bit about Charles while doing my research. Is that a third-party application like wire shark? I know that in a browser if I use Http, it does work but it redirects to HTTPS. Am I to assume that there is no way to enter proxy server settings as you can do on the iPhones ui? I'm saying this because I've searched EVERYWHERE and the only thing I could find is what I have above. – dbconfession May 03 '16 at 16:31
  • 1
    It's like WireShark indeed. But it also can sniff HTTPS by adding a spoofing CA on the phone. However, it uses a proxy for its operation so that might interfere with the proxy you wanna debug. I'd try to setup a proxy with HTTP only which makes it easier to sniff the connection as it's plaintext. – Ortwin Gentz May 03 '16 at 16:36
  • You might try using a non-ephemeral session. This could be a bug caused by the way ephemeral sessions try to store credentials in memory. If using a non-ephemeral session works, you can mimic an ephemeral session by writing appropriate session delegate methods, using your own memory-only cache, etc. and then store and handle credential storage yourself. – dgatwood May 08 '16 at 03:49

1 Answers1

0

Add additional headers to your config.

 func main() -> () {
let request = NSMutableURLRequest(URL: self.URL)
request.HTTPMethod = self.method
if method == "POST" {
    request.HTTPBody = params.dataUsingEncoding(NSUTF8StringEncoding)
}
if self.shouldUseProxy {
    let proxyEnable = NSNumber(int: 1) as NSNumber
    let proxyDict: [NSObject:AnyObject] = [
        kCFNetworkProxiesHTTPEnable: proxyEnable,
        kCFStreamPropertyHTTPProxyHost: self.proxyHost,
        kCFStreamPropertyHTTPProxyPort: self.proxyPort,
        kCFStreamPropertyHTTPSProxyHost: self.proxyHost,
        kCFStreamPropertyHTTPSProxyPort: self.proxyPort,
        kCFProxyTypeKey: kCFProxyTypeHTTPS,
        kCFProxyUsernameKey: self.proxyUser,
        kCFProxyPasswordKey: self.proxyPW
    ]
    let config = NSURLSessionConfiguration.ephemeralSessionConfiguration()
    let config.httpAdditionalHeaders = ["Proxy-Authorization":  Request.authorizationHeader(user: self.proxyUser, password: self.proxyPW) ]
    config.connectionProxyDictionary = proxyDict
    self.session = NSURLSession.init(configuration: config, delegate: self, delegateQueue: NSOperationQueue())
}

let task = session.dataTaskWithRequest(request) {
    (data, response, error) in
    if error == nil {
        let httpResponse = response as! NSHTTPURLResponse
        let statusCode = httpResponse.statusCode
        print("statusCode \(statusCode)")
    }
    self.isConnecting = false
}
task.resume()
}
}
Wilson Campusano
  • 616
  • 9
  • 21