Put a private mobile app behind a VPN and a reasonable person will ask whether it still needs certificate pinning. The question sounds like a choice between two equivalent controls, and it is really a question about two different gates. The VPN decides whether this device may use the path at all; the app decides whether the server it reached is the one it expected. Answer both separately and the design gets simpler.

Two gates, two questions

Network admission is about the client: is this device enrolled, is its credential valid, and does policy allow it onto this path? Application trust is about the server: did the connection reach a service with an identity the app accepts? Those answers come from different systems, fail for different reasons, and are fixed by different teams. A VPN handshake can succeed while the app talks to an expired certificate behind the peer. A perfectly pinned app can still be reached by nobody, because the device never got onto the network.

The two are additive. Dropping either removes a control; adding one does not replace the other.

What a pin actually constrains

A pin narrows the set of server identities the app will accept, usually by naming a public key or a certificate hash rather than trusting every chain a store would vouch for. It is a constraint layered on ordinary validation, not a replacement for it. Ordinary validation answers whether a chain is trustworthy at all; the pin answers whether it is the chain this app expects. An implementation that skips the first step has not gained security, only novelty.

The object being pinned differs between platforms, so the word alone tells you very little. Copying a hash from one product's trust store and treating it as the same thing in a mobile app is a common and quiet mistake.

Platform pinning is a configuration, not a policy

Android exposes pinning through its network security configuration, where a pin set holds digests of a public key and the chain must contain at least one of them. That file is per app and needs a deliberate build change. iOS has no equivalent manifest mechanism, so pinning there lives in the app's own trust evaluation code.

Since the mechanism differs, the requirement has to be written per platform. A policy that says pin the certificate without naming the platform is not implementable.

Rotation decides whether the pin survives

The hard part is not the first release, it is the certificate renewal after it. A restrictive trust policy rejects a legitimate new key exactly as firmly as an attacker's.

Two mechanisms make rotation survivable: a backup pin that is already trusted before it is needed, and an expiration date on the pin set so enforcement lapses instead of bricking the app. Both are policy decisions, and the expiration in particular is a deliberate reduction in security rather than a harmless timer. Name who controls the app build, the TLS endpoint and the certificate renewal, and put them into one change process. If those are three different teams, the pin will eventually cause an outage nobody scheduled.

A lost device is a third problem

Revoking a VPN credential does not necessarily end an application session, and a server pin does nothing at all about a phone in someone else's hand. Device lock, credential storage, session lifetime and remote revocation are separate decisions with separate owners. Folding them into the pinning discussion guarantees that none of them gets designed.

Test four relationships instead of the one you can see: the intended server and operation, an account that should be refused, a server identity that should be rejected, and the planned rotation. A working VPN exercises only the first. Write down what each test proved, because the next person will assume that a green tunnel means all four passed.

Winndannde jowitiiɗe heen