Greetings, traveler!
Most iOS apps talk to servers over HTTPS. In everyday work, certificate validation stays in the background. You create a request, the system sends it, and everything works.
Most of the time, developers do not need to think about certificate validation at all. Still, understanding the basics can be useful when reviewing a server configuration, checking compatibility with supported iOS versions, or investigating an unexpected connection failure. In those cases, it helps to know how iOS evaluates the certificate chain and how to inspect it.
What iOS validates
When an app connects to an HTTPS server, iOS verifies the server before sending application data.
That validation includes a few core checks:
- the certificate matches the requested hostname
- the certificate is still valid
- the certificate can be used for server authentication
- each certificate in the chain has a valid signature
- the chain reaches a root certificate trusted by the system
- publicly trusted certificates meet Apple’s Certificate Transparency requirements where applicable
Apple ships trusted root certificates as part of its Root Store. These certificates act as trust anchors during server trust evaluation.
In normal cases, your app does not need to implement this logic itself. URLSession uses the platform’s built in trust evaluation unless you add custom server trust handling.
The certificate chain
A server certificate is usually not trusted by itself. It is part of a chain.
Server certificate
↓
Intermediate certificate authority
↓
Root certificate authority
The server certificate, often called the leaf certificate, identifies the domain. It is usually signed by an intermediate certificate authority. That intermediate is signed by another authority, and the process continues until the chain reaches a root certificate already trusted by the system.
The server usually sends the leaf certificate and one or more intermediate certificates during the TLS handshake. The trusted root typically comes from the operating system, not from the server.
A missing intermediate is a common problem. A server can appear fine in one environment and fail in another because its chain is incomplete.
Subject and issuer
Every certificate has a subject and an issuer. The subject identifies the certificate owner. For a leaf certificate, this is usually the server or domain. The issuer identifies the certificate authority that signed it.
A simple chain might look like this:
Subject: api.example.com
Issuer: Example Intermediate CA
Subject: Example Intermediate CA
Issuer: Example Root CA
When you inspect a chain, the issuer of one certificate should lead to the subject of the next certificate in the path.
That said, names alone are not enough for exact matching. For reliable analysis, it is better to check fingerprints and certificate identifiers as well.
Cross signed certificates
A certificate with “Root CA” in its name is not always the final trust anchor.
Sometimes a newer certificate authority is cross signed by an older one:
api.example.com
→ New Intermediate CA
→ New Root CA
→ Existing Trusted Root CA
This allows clients that do not yet trust the new root directly to build a valid path to an older root that already exists in the Root Store.
This matters because the list of certificates sent by the server is not always the only possible validation path. The trust engine may build another valid path by combining what the server sends with certificates already available on the device.
Certificate pinning
Certificate pinning adds an application level restriction on top of normal trust evaluation.
Without pinning, the app accepts a server certificate as long as the system can validate it through its normal trust rules. With pinning, the app also requires a specific certificate or public key to match a value it already knows.
Apple also supports pinned domains through App Transport Security. In that model, the app pins public key identities by storing SHA 256 hashes of certificate public keys.
Pinning can improve control, but it also adds operational risk. If a certificate or key changes and the app does not contain a valid backup pin, network access can break. Pinning is not a replacement for standard TLS validation. It is an additional check.
How to inspect a server certificate
The easiest first step is to inspect the server with OpenSSL:
openssl s_client \
-connect example.com:443 \
-servername example.com \
-showcerts \
-verify_hostname example.com \
-verify_return_error
These options do different things:
-connectspecifies the host and port-servernamesends the hostname through SNI so the server can choose the correct virtual host-showcertsprints the certificates sent by the server-verify_hostnamechecks that the certificate matches the requested hostname-verify_return_errorstops on verification errors instead of continuing
Note: -servername does not validate the hostname. It only affects which certificate the server returns.
How to read the OpenSSL output
You will usually see entries like these near the start:
depth=2 CN=Example Root CA
depth=1 CN=Example Intermediate CA
depth=0 CN=api.example.com
depth=0 is the leaf certificate. Higher numbers move up the chain.
You will also see a certificate chain section:
Certificate chain
0 s:CN=api.example.com
i:CN=Example Intermediate CA
1 s:CN=Example Intermediate CA
i:CN=Example Root CA
Here, s means subject and i means issuer.
This section shows the certificates sent by the server. It is not a fully verified chain, and it does not include certificates that the client may use from its local trust store.
At the end, you may see:
Verify return code: 0 (ok)
That means OpenSSL accepted the certificate path using the trust configuration available in that environment.
Inspecting an individual certificate
If you save one of the certificates to a PEM file, you can inspect it in more detail:
openssl x509 \
-in certificate.pem \
-noout \
-subject \
-issuer \
-dates \
-fingerprint \
-text
The most useful fields are usually:
- Subject Alternative Name
- Not Before and Not After
- Basic Constraints
- Key Usage
- Extended Key Usage
- Subject Key Identifier
- Authority Key Identifier
- SHA 256 fingerprint
For hostname checks, pay attention to Subject Alternative Name. That is what modern clients use for domain matching.
OpenSSL is not iOS
A successful OpenSSL check is useful, but it does not prove that every iOS version will trust the same server.
OpenSSL uses the trust configuration of the machine where the command runs. iOS uses Apple’s Root Store. The two environments may contain different root certificates and may build different validation paths.
That leads to a few possible outcomes:
- OpenSSL trusts the chain, but a target iOS version does not
- iOS trusts the chain, but the local OpenSSL installation does not
- both trust the server, but through different paths
- a managed device trusts an extra root installed through a configuration profile
So Verify return code: 0 is a good signal, but it is not an iOS compatibility test.
Checking certificates on an iPhone
iOS provides a few places where you can inspect certificate-related settings.
To view installed configuration profiles, open:
Settings
→ General
→ VPN & Device Management
A profile may contain certificates used by corporate Wi-Fi, VPN connections, device management, or private server trust. Opening a profile shows the payloads it installed. Apple documents this path for viewing and removing configuration profiles.
To view manually installed root certificates that can be trusted for TLS, open:
Settings
→ General
→ About
→ Certificate Trust Settings
This screen shows user-installed root certificates for which full trust can be enabled or disabled. A certificate installed manually through a profile is not automatically trusted for SSL. The user normally has to enable full trust on this screen. Certificates installed through supported device-management mechanisms may be handled differently.
The same screen also shows the version of the Root Store installed on the device. However, it does not provide a browsable list of every root certificate included in Apple’s system store. To inspect that list, use Apple’s published Root Store documentation for the relevant iOS version.
How to check compatibility with iOS
A practical workflow looks like this.
First, retrieve the server chain with openssl s_client.
Second, record the important details for each certificate:
- subject
- issuer
- expiration dates
- SAN entries
- SHA 256 fingerprint
Third, follow the chain until you identify the possible trust anchor. Be careful with cross signed certificates. A certificate that looks like a root may still continue to another authority.
Fourth, compare the possible trust anchor with Apple’s published Root Store for every iOS version your app supports. Use the SHA-256 fingerprint for exact identification because certificate names are not always unique.
Fifth, check whether the app uses custom server trust handling or certificate pinning. If it does, the result may differ from standard system validation.
Finally, test the endpoint on a clean installation of each supported iOS version. A simulator is useful for an initial check, but a physical device gives the strongest confirmation, especially if configuration profiles or managed trust settings may be involved.
Common certificate problems
A few issues may arise:
- the hostname is missing from Subject Alternative Name
- the leaf certificate has expired
- an intermediate certificate has expired
- the server does not send a required intermediate
- the chain ends at a root the target iOS version does not trust
- the server sends an unsuitable cross signed certificate
- pinning contains an outdated certificate or public key
- custom trust handling rejects a valid chain or accepts an invalid one
These issues can affect only some iOS versions because Root Stores and path building behavior change over time.
Final thoughts
In most cases, iOS handles TLS certificate validation for you. The app does not need to load certificates or verify the chain manually.
When you need to check compatibility, look at the full chain, not just the leaf certificate. Identify the possible trust anchor, compare it with Apple’s Root Store, check whether the app changes trust evaluation through pinning or custom logic, and confirm the result on the iOS versions you support.
OpenSSL is a useful inspection tool. It is not the final answer. The final answer comes from how iOS evaluates that server in the environments your app actually supports.
