Only on macOS catalina, NSURLSession fail with NSURLErrorClientCertificateRequired

The ssl certificates are proper according to new requirements for catalina. Can see a response 403 from server in console by enabling CFNETWORK DIAGNOSTICS but it is failing with NSURLErrorClientCertificateRequired. The certificates are also being shared properly confirmed from wireshark & CFNETWORK DIAGNOSTICS. Authentication works properly on safari and chrome, without any error
One observation: There are multiple api calls throughout the session. When tried these call explicitly on chrome twice or thrice, the authentication worked proplerly on app too. How does authentication on chrome/safari affect an app? Is it something to with security settings on catalina. After this there are not authentication errors at all on my system. The issue is only observed on macOS Catalina.

Replies

The authentication taking place in Safari should have no bearing upon what happens in the app. These two processes are running completely independent of each other. If authenticating in Safari does affect the outcome of your app then I would look at the server for more information. Are you possible testing with localhost between the two etc..

| One observation: There are multiple api calls throughout the session. When tried these

| call explicitly on chrome twice or thrice, the authentication worked proplerly on app

| too. How does authentication on chrome/safari affect an app?


When you receive the NSURLErrorClientCertificateRequired in your app, are you responding to an authentication challenge or just sending an API request?


Matt Eaton

DTS Engineering, CoreOS

meaton3 at apple.com

No, there is no localhost between client and server.


There are multiple calls to delegate method

-(void)URLSession:(NSURLSession *)session

didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge

completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler
Both kinds of authentication method are received, NSURLAuthenticationMethodServerTrust and NSURLAuthenticationMethodClientCertificate. I share NSURLCredential for both. For NSURLAuthenticationMethodClientCertificate, along with certificate identity, I have tried sharing nil as well as certificate chain for certificate parameter for NSURLCredential.
The authentication via smarcard.

It sounds like you want to focus in on the NSURLCredential that is being sent to the server in NSURLAuthenticationMethodClientCertificate. As mentioned, you are able to see the certificate being delivered for the challenge, and the fact that your are receiving a 403 most likely means the server received the certificate, but responded with forbidden. This leaves the certificate that is being sent; To narrow down what is happening here I would do the following to debug:


1) Check that the certificate(s) being sent to the server is/are from a trusted CA that is known by the server. Wireshark could help you do this.


2) Examine the successful certificates being passed in from Safari for this same challenge and compare the two. Wireshark could help you do this.


3) Enabled verbose access logs in your server to see where the breakdown is in the client certificate evaluation process. Your access logs may reveal more to about this.



Matt Eaton

DTS Engineering, CoreOS

meaton3 at apple.com

Thanks for the reply. I have been looking into this for a while.
The certificate is from trusted CA and same as I get in safari.
Following the steps with observation:
1. Make request
2. Auth challenge thrown, and I share certificate identity.
3. Request fails with NSURLErrorClientCertificateRequired error, though I can see 403 response in console by enabling CFNETWORK DIAGNOSTICS. 403 is expected in response.
4. Make the same request again.
5. 403 received in response. (No Authchallenge thrown this time)
6. Request completes without any error.
I am not able to understand why the above beahvior is observed. Why the response is not received first time when I actually share certificate with auth challenge.

The common thread here is the 403 response when you send the certificate to your server. I would encourage you to dig into how your server is evaluating the array of certificates that you are sending for the NSURLAuthenticationMethodClientCertificate case. The server must be performing this evaluation and therefore logging it. I would advise recreating this test in a debug environment where you can turn your server syslog and access logs as verbose as possible and then see what your server tells you. This should allow you to back track to the certificate or iOS functionality to further resolve.



Matt Eaton

DTS Engineering, CoreOS

meaton3 at apple.com

Hi,
403 is an expected response. It is just that in one case I see 403 in console output, and in another i get 403 as response in urlsession delegate.
It's just that Earlier I get NSURLErrorClientCertificateRequired next time I don't. Also, this behavior is only with catalina. In mojave I get 403 response with any NSError. This behaior is expected.
Can it be related to caching of certificate by urlsession? First time it throws auth chalLenge along with NSError and next time it's no auth challenge and no NSError. Just reponse.

This does sound like an odd case based on what you described. I would checkout the certificate requirements for macOS 10.15 and I would also look at the logs your server is providing. Usually when there is random trust failures like this your are talking to a server that you did not expect to through process of external network configuration.



Matt Eaton

DTS Engineering, CoreOS

meaton3 at apple.com