Skip to Content
SDK IntegrationSwift (iOS & macOS)

iOS SDK

Integrate TrustPin into your iOS application with comprehensive certificate pinning protection.

Platform Requirements

PlatformMinimum VersionSupport
iOS13.0+
macOS13.0+
watchOS7.0+
tvOS13.0+
visionOS2.0+

Swift Version: 5.5+ (requires async/await support)


Installation

Add TrustPin to your project in Xcode:

  1. Go to File → Add Package Dependencies
  2. Enter the repository URL:
    https://github.com/trustpin-cloud/TrustPin-Swift.binary
  3. Select version 2.0.0 or later

Package.swift

For command-line projects:

dependencies: [ .package(url: "https://github.com/trustpin-cloud/TrustPin-Swift.binary", from: "2.0.0") ], targets: [ .target( name: "YourApp", dependencies: [ .product(name: "TrustPinKit", package: "TrustPin-Swift") ] ) ]

CocoaPods

Add to your Podfile:

pod 'TrustPinKit'

Then run:

pod install

Quick Start

1. Get Your Credentials

Sign in to the TrustPin Dashboard  and retrieve:

  • Organization ID
  • Project ID
  • Public Key (Base64-encoded)

2. Initialize TrustPin

Add this to your app’s initialization (e.g., AppDelegate or @main struct):

import TrustPinKit class AppDelegate: UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { Task { do { try await TrustPin.setup( organizationId: "your-org-id", projectId: "your-project-id", publicKey: "your-base64-public-key", mode: .strict ) print("TrustPin initialized") } catch { print("TrustPin setup failed: \(error)") } } return true } }

SwiftUI Apps

import SwiftUI import TrustPinKit @main struct MyApp: App { init() { Task { try? await TrustPin.setup( organizationId: "your-org-id", projectId: "your-project-id", publicKey: "your-base64-public-key", mode: .strict ) } } var body: some Scene { WindowGroup { ContentView() } } }

3. Make Network Requests

After setup, all URLSession requests automatically use certificate pinning:

// URLSession.shared is automatically protected let url = URL(string: "https://api.example.com/data")! let (data, _) = try await URLSession.shared.data(from: url)

Integration Approaches

TrustPin offers three integration methods:

ApproachBest ForComplexity
System-Wide URLProtocol (Default)Most apps🟢 Minimal
URLSessionDelegateCustom URLSession instances🟡 Medium
Helper MethodsExplicit control🟠 Per-request

Automatically protects all URLSession requests across your entire application after setup:

// Setup once during app initialization try await TrustPin.setup( organizationId: "your-org-id", projectId: "your-project-id", publicKey: "your-base64-public-key", mode: .strict // autoRegisterURLProtocol: true (enabled by default) ) // All URLSession requests are now automatically protected let (data, _) = try await URLSession.shared.data(from: url) // Custom URLSession instances are also protected let session = URLSession(configuration: .ephemeral) let (data2, _) = try await session.data(from: url) // Third-party networking libraries using URLSession are also protected automatically!

How it works: TrustPin registers a custom URLProtocol subclass that intercepts all URLSession requests, validates certificates against your configured pins, and either allows or blocks the connection based on the validation result.

Manual Control

For advanced scenarios:

// Disable auto-registration during setup try await TrustPin.setup( organizationId: "your-org-id", projectId: "your-project-id", publicKey: "your-base64-public-key", mode: .strict, autoRegisterURLProtocol: false ) // Enable/disable manually TrustPin.registerURLProtocol() // Enable protection TrustPin.unregisterURLProtocol() // Disable protection

URLSessionDelegate

For granular control over specific URLSession instances:

import TrustPinKit class NetworkManager { private let trustPinDelegate = TrustPinURLSessionDelegate() private lazy var session = URLSession( configuration: .default, delegate: trustPinDelegate, delegateQueue: nil ) func fetchData() async throws -> Data { let url = URL(string: "https://api.example.com/data")! let (data, _) = try await session.data(from: url) return data } }

Helper Methods

Explicit control for individual requests:

import TrustPinKit // Async/await let (data, _) = try await TrustPinURLProtocol.data(from: url) // Completion handler let task = TrustPinURLProtocol.dataTask(with: url) { data, response, error in // Handle response } task.resume() // Create custom session with pinning let session = URLSession.trustPinSession(configuration: .ephemeral)

Configuration

Pinning Modes

Strict Mode

Rejects connections to unregistered domains:

try await TrustPin.setup( organizationId: "your-org-id", projectId: "your-project-id", publicKey: "your-base64-public-key", mode: .strict // Recommended for production )

Permissive Mode

Allows unregistered domains to bypass pinning:

try await TrustPin.setup( organizationId: "your-org-id", projectId: "your-project-id", publicKey: "your-base64-public-key", mode: .permissive // For development/testing )

Logging

Enable debug logging for troubleshooting:

// Set log level before setup await TrustPin.set(logLevel: .debug) // Available levels: // .none - No logging (production) // .error - Errors only // .info - Errors + informational messages // .debug - All messages (development)

Error Handling

TrustPin provides detailed error types:

import TrustPinKit do { try await TrustPin.verify(domain: "api.example.com", certificate: pemCert) print("Certificate is valid") } catch TrustPinErrors.domainNotRegistered { // Domain not configured (strict mode only) print("Domain not registered") } catch TrustPinErrors.pinsMismatch { // Certificate doesn't match pins - possible MITM attack print("SECURITY: Certificate mismatch") } catch TrustPinErrors.allPinsExpired { // All pins expired for this domain print("Pins expired") } catch TrustPinErrors.invalidServerCert { // Invalid certificate format print("Invalid certificate") } catch TrustPinErrors.invalidProjectConfig { // Setup configuration invalid print("Configuration error") } catch TrustPinErrors.errorFetchingPinningInfo { // Network error fetching configuration print("Network error") } catch TrustPinErrors.configurationValidationFailed { // Signature validation failed print("Signature validation failed") } catch { print("Unexpected error: \(error)") }

Best Practices

Setup & Initialization

  1. Call TrustPin.setup() only once during app launch
  2. Handle setup errors gracefully - don’t block app launch
  3. Set log level before setup for complete logging
  4. Never call setup concurrently
  5. Use Task/async context in synchronous lifecycle methods

Security

  1. Use .strict mode in production
  2. Rotate pins before expiration
  3. Monitor pin validation failures
  4. Keep credentials secure (use environment variables)
  5. Use HTTPS for all pinned domains

Performance

  1. Cache is handled automatically (10-minute TTL)
  2. Reuse URLSession instances
  3. Use .error or .none log level in production
  4. Initialize early to avoid delays

Development Workflow

  1. Start with .permissive mode
  2. Test all endpoints with pinning enabled
  3. Validate pin configurations in staging
  4. Switch to .strict mode for production
  5. Use .debug logging to troubleshoot

Integration with Third-Party Libraries

Alamofire

import Alamofire import TrustPinKit class TrustPinAlamofireDelegate: TrustPinURLSessionDelegate, SessionDelegate { // TrustPinURLSessionDelegate handles validation } let delegate = TrustPinAlamofireDelegate() let session = Session( configuration: .default, delegate: delegate ) // Use session for requests let response = try await session.request("https://api.example.com/data") .validate() .serializingData() .value

Troubleshooting

Setup Fails with invalidProjectConfig

  • Verify credentials in TrustPin Dashboard 
  • Check for whitespace in credentials
  • Ensure public key is base64-encoded
  • Avoid concurrent setup calls

Certificate Verification Fails

  • Confirm domain is registered in dashboard
  • Verify certificate format (PEM-encoded)
  • Check pin expiration dates
  • Test with .permissive mode first

Network Requests Hang

  • Verify correct URLSession delegate
  • Check for retain cycles
  • Test network connectivity
  • Ensure URLProtocol is registered

System-Wide Pinning Not Working

  • Confirm autoRegisterURLProtocol: true (default)
  • Test with HTTPS URLs only
  • Verify URLProtocol not unregistered elsewhere
  • Manually call TrustPin.registerURLProtocol()

API Reference

Core Classes

  • TrustPin - Main SDK interface
  • TrustPinMode - Pinning modes (.strict, .permissive)
  • TrustPinURLSessionDelegate - URLSession delegate
  • TrustPinURLProtocol - System-wide pinning (iOS 13.0+)
  • TrustPinErrors - Error types
  • TrustPinLogLevel - Logging configuration

Key Methods

// Setup static func setup( organizationId: String, projectId: String, publicKey: String, mode: TrustPinMode = .strict, autoRegisterURLProtocol: Bool = true ) async throws // Manual verification static func verify(domain: String, certificate: String) async throws // URLProtocol control static func registerURLProtocol() static func unregisterURLProtocol() // Logging static func set(logLevel: TrustPinLogLevel) async

Production Deployment

Production Configuration

1. Set Production Mode

import TrustPinKit // In production build try await TrustPin.setup( organizationId: ProcessInfo.processInfo.environment["TRUSTPIN_ORG_ID"]!, projectId: ProcessInfo.processInfo.environment["TRUSTPIN_PROJECT_ID"]!, publicKey: ProcessInfo.processInfo.environment["TRUSTPIN_PUBLIC_KEY"]!, mode: .strict // Always strict in production ) // Set minimal logging await TrustPin.set(logLevel: .error)

2. Xcode Build Configuration

Add environment variables to your Xcode scheme:

  1. ProductSchemeEdit Scheme
  2. Select RunArguments tab
  3. Add Environment Variables:
    • TRUSTPIN_ORG_ID: Your organization ID
    • TRUSTPIN_PROJECT_ID: Your project ID
    • TRUSTPIN_PUBLIC_KEY: Your public key

3. App Store Submission

Before submitting to App Store:

  • Test on physical devices (not just simulator)
  • Verify certificate pinning works on cellular and WiFi
  • Test with TestFlight beta before production release
  • Document TrustPin usage in App Privacy details
  • Include “Uses TrustPin™ technology” attribution

Info.plist Configuration

Ensure your Info.plist allows network access to TrustPin CDN:

<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <false/> <key>NSExceptionDomains</key> <dict> <key>cdn.trustpin.cloud</key> <dict> <key>NSExceptionAllowsInsecureHTTPLoads</key> <false/> <key>NSExceptionMinimumTLSVersion</key> <string>TLSv1.2</string> </dict> </dict> </dict>

Resources