Skip to main content
SSL pinning locks the SDK to a known, trusted certificate instead of trusting any certificate authority, so a compromised CA or a MITM proxy can’t intercept auth traffic. Available from otpless-headless-sdk v2.0.0. Pinning is disabled by default, so upgrading needs no code change.

Enable pinning

Pass sslKind to initialise (the suspend overload — initialize does not take sslKind and always runs with pinning disabled):

OtplessSslKind values

Pin validation failure

If pin validation fails, OtplessSDK.start() returns a terminal response instead of continuing the auth flow:
  • responseType: FAILED
  • statusCode: 5004
  • errorCode: "5004"
  • errorMessage: "SSL pin validation failed"
Handle 5004 like any other terminal auth failure: show a fallback or retry path. Re-initialising resets the failed state and retries the manifest load.

What gets pinned

Pinned traffic goes to sigma.otpless.app. Behind a firewall, proxy, or MDM allowlist, add sigma.otpless.app and d3efyv4lemhheo.cloudfront.net.

How it works

  • Baseline SPKI pins ship in the SDK and install immediately on initialise(sslKind = OtplessSslKind.SslEnabled).
  • A signature-verified remote manifest can refine the pin set — it can add pins, but never remove a baseline pin or introduce a new host. A cached copy is reused for up to 7 days; otherwise a fresh one is fetched and verified.
  • Pins are enforced at every TLS handshake, after system trust validation. Hosts outside the pin set pass through on system trust alone.
  • On a pin mismatch the SDK refreshes the manifest once and re-checks. If it still fails, the connection is cancelled and pinning fails closed for the rest of the process.
  • Certificate rotation needs no app update — new pins arrive via the signed manifest.

Debugging and testing

  • Proxies are blocked by design. Charles, Proxyman, and mitmproxy present their own certificate, so SslEnabled fails them with 5004. Use SslDisabled in debug when you need to inspect traffic; keep SslEnabled in release.
  • Pinning is per connection, not per request — a reused TLS connection is checked once; a new connection is checked again.

Migration notes

  • No code change to upgrade to v2.0.0; add sslKind = OtplessSslKind.SslEnabled when you’re ready to enforce pinning.
  • Hosts reached through an apiBaseUrl override are not pinned — they pass through on system trust.