TL DR; . In your example, you are processing authentication incorrectly.
This is what happens when an iOS or MacOS client encounters an authentication URL:
The client requests a resource from the GET www.example.com/protected server GET www.example.com/protected
The server response for this request has a status code of 401 and includes a WWW-Authenticate header. This tells the client that it is a secure resource, and indicates which authentication method to use to access the resource. On iOS and MacOS, this is the "authentication" that the delegate responds to. The WWW-Authenticate header is specifically mentioned in the documentation to highlight this .
Typically on iOS and MacOS, if a delegate is not provided or does not handle authentication problems, the URL loading system will try to find the appropriate credentials for this resource and type of authentication by looking at NSURLCredentialStorage. It searches for the appropriate credentials that have been saved as the default.
If a delegate providing authentication is provided, then before that delegate provide credentials for this resource.
When the system has credentials for authentication, the request again attempts to execute the credentials.
GET www.example.com/protected Authorization: Basic blablahaala
This explains the behavior you see in Charles, and is the correct behavior according to various HTTP specifications.
Obviously, if you do not want to deploy a delegate for your connection, you have the option to enter credentials for the resource that you are accessing in NSURLCredentialStorage. The system will use this and will not require you to run a delegate for credentials.
Create an NSURLCredential:
credential = [NSURLCredential credentialWithUser:@"some user" password:@"clever password" persistence: NSURLCredentialPersistencePermanent];
NSURLCredentialPersistencePermanent will tell NSURLCredentialStorage to keep this forever in the keychain. There are other possible values, such as NSURLCredentialPersistenceForSession . They are described in the documentation. . You should avoid using NSURLCredentialPersistencePermanent with credentials that have not been verified, use the session or not until the credentials are verified. You have probably seen projects using KeychainWrapper or direct access to the Keychain API to store names and passwords on the Internet - this is not the most preferable way to do this, NSURLCredentialStorage is.
Create an NSURLProtectionSpace with the correct host, port, protocol, scope, and authentication method:
protectionSpace = [[NSURLProtectionSpace alloc] initWithHost:[url host] port:443 protocol:[url scheme] realm:@"Protected Area" authenticationMethod:NSURLAuthenticationMethodHTTPBasic];
Note that [[url port] integerValue] will not provide default values ββfor HTTP (80) or HTTPS (443). You must provide them. The area MUST match what the server provides.
Finally, put it in NSURLCredentialStorage :
[[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential forProtectionSpace:protectionSpace];
This will allow the URL loading system to use these credentials from now on. In fact, the same process can also be used to reference the SSL / TLS server trust.
In your question, you are handling server trust, but not NSURLAuthenticationMethodHTTPBasic . When your application receives an authentication request for HTTP Basic Auth, you are not responding, but things are going down. In your case, you probably wonβt need to implement URLSession:didReceiveChallenge:completionHandler: if you follow the steps above to set the default basic authentication credentials for this security space. The system will handle NSURLAuthenticationMethodServerTrust , performing a default trust assessment. The system will then find the default credentials that you set for this security location for basic authentication, and use this.
UPDATE
Based on the new information in the comments and the launch of the modified version of the code, the OP actually receives this error in response to its request: NSURLConnection/CFURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813) This error can be found in SecureTransport.h. The root certificate for the server credentials does not exist or is not supported by the system. This is very rare, but it can happen. Technote 2232 explains how to configure client trust verification of a client to allow this certificate .