Evaluate the server’s security credentials in your app.
When you use a secure connection (such as
https) with a URL request, your
URLSession receives an authentication challenge with an authentication type of
NSURLAuthentication. Unlike other challenges where the server is asking your app to authenticate itself, this is an opportunity for you to authenticate the server’s credentials.
Determine When Manual Server Trust Evaluation Is Appropriate
In most cases, you should let the URL Loading System’s default handling evaluate the server trust. You get this behavior when you either don’t have a delegate or don’t handle authentication challenges. However, performing your own evaluation may be useful for scenarios like the following:
You want to accept server credentials that would otherwise be rejected by the system. For example, your app makes a secure connection to a development server that uses a self-signed certificate, which would ordinarily not match anything in the system’s trust store.
You want to reject credentials that would otherwise be accepted by the system. For example, you want to “pin” your app to a set of specific keys or certificates under your control, rather than accept any valid credential.
Figure 1 illustrates how an app performs manual credential evaluation by providing a delegate method to handle the authentication challenge. This bypasses the default handling. Instead, the delegate directly compares the server certificate or its public key against a copy of the certificate or key (or a hash of either of these) stored in the app bundle itself. If the delegate decides the server credential is valid, it accepts the server trust and allows the connection to continue.
Handle Server Trust Authentication Challenges
To perform manual server trust authentication, implement the
url. When this method is called, the first things your implementation needs to do are to check that:
The challenge type is server trust, and not some other kind of challenge.
The challenge’s host name matches the host that you want to perform manual credential evaluation for.
Listing 1 shows how to test these conditions, given the
challenge parameter passed to the
url callback. It gets the challenge's
protection and uses it to perform the two checks listed above. First, it gets the
authentication from the protection space and checks that the type of authentication is
NSURLAuthentication. Then it makes sure the protection space’s
host matches the expected name
example. If either of these conditions are not met, it calls the
completion with the
URLSession disposition to allow the system to handle the challenge.
Evaluate the Credential in the Challenge
To access the server’s credential, get the
server property (an instance of the
Sec class) from the protection space. Listing 2 shows how to access the server trust and accept or reject it. The listing starts by attempting to get the
server property from the protection space, and falls back to default handling if the property is
nil. Next, it passes the server trust to a private helper method
check that compares the certificate or public key in the server trust to known-good values stored in the app bundle.
Once the code determines the validity of the server trust, it takes one of two actions:
If the server trust’s credential is valid, create a new
URLCredentialinstance from the server trust. Then call the
URLSessiondisposition, passing in the newly-created credential. This tells the system to accept the server’s credentials.
.Auth Challenge Disposition .use Credential
If the challenge’s credential is invalid, call the
URLSessiondisposition. This tells the system to reject the server’s credentials.
.Auth Challenge Disposition .cancel Authentication Challenge
Create a Long-Term Server Authentication Strategy
If you determine that you need to evaluate server trust manually in some or all cases, plan for what your app will do if you need to change your server credentials. Keep the following guidelines in mind:
Compare the server’s credentials against a public key, instead of storing a single certificate in your app bundle. This will allow you to reissue a certificate for the same key and update the server, rather than needing to update the app.
Compare the issuing certificate authority’s (CA’s) keys, rather than using the leaf key. This way, you can deploy certificates containing new keys signed by the same CA.
Use a set of keys or CAs, so you can rotate server credentials more gracefully.