Clerk iOS SDK logo

clerk ios sdk

Set up authentication in iOS apps with Clerk's Swift SDK

$ npx docs2skills add clerk-ios-auth
SKILL.md

Clerk iOS SDK

Set up authentication in iOS apps with Clerk's Swift SDK

What this skill does

Clerk's iOS SDK provides native Swift authentication for iOS applications with zero-config prebuilt UI components and comprehensive user management. Unlike implementing authentication from scratch or using basic OAuth libraries, Clerk handles the complete authentication lifecycle including sign-up flows, email verification, password resets, multi-factor authentication, and session management through native iOS APIs.

The SDK integrates deeply with iOS capabilities like Associated Domains for seamless authentication flows and provides SwiftUI-first components that follow iOS design patterns. It eliminates the need to build custom authentication forms, manage authentication state, or handle security edge cases while providing enterprise-grade features like SSO, role-based access control, and user profile management out of the box.

Clerk fits into the iOS ecosystem as a drop-in authentication solution that works alongside existing Swift/SwiftUI applications, requiring minimal configuration while providing maximum flexibility for customization when needed.

Prerequisites

  • iOS 14.0+ target deployment
  • Xcode 12.0 or later
  • SwiftUI and Swift language
  • Active Clerk account with Native API enabled
  • iOS App ID Prefix and Bundle ID for associated domains
  • Swift Package Manager support

Quick start

Install via Swift Package Manager with URL https://github.com/clerk/clerk-ios, adding both ClerkKit and ClerkKitUI to your target.

// App.swift
import SwiftUI
import ClerkKit

@main
struct MyApp: App {
    init() {
        Clerk.configure(publishableKey: "pk_test_...")
    }
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environment(Clerk.shared)
        }
    }
}

// ContentView.swift
import SwiftUI
import ClerkKit
import ClerkKitUI

struct ContentView: View {
    @Environment(Clerk.self) var clerk
    @State private var showingAuth = false
    
    var body: some View {
        if let user = clerk.user {
            VStack {
                Text("Hello, \(user.firstName ?? "User")")
                UserButton()
            }
        } else {
            Button("Sign in") {
                showingAuth = true
            }
            .sheet(isPresented: $showingAuth) {
                AuthView()
            }
        }
    }
}

Core concepts

Clerk Instance: The Clerk.shared singleton manages authentication state and provides access to the current user, session, and authentication methods. Configure once at app launch and inject into SwiftUI environment for global access.

User Object: Represents the authenticated user with properties like firstName, lastName, emailAddresses, and methods for profile management. Automatically updated when user data changes.

Session Management: Clerk handles token refresh, session persistence, and logout automatically. Sessions persist across app launches and sync across devices when using the same Clerk account.

Associated Domains: Required iOS capability that enables seamless authentication flows by allowing your app to work with Clerk's web-based authentication services. Must match your Clerk frontend API URL.

Prebuilt vs Custom: Clerk provides ready-made SwiftUI views (AuthView, UserButton, UserProfileView) that handle complete flows, or you can build custom interfaces using the underlying authentication methods.

Key API surface

Component/MethodPurpose
Clerk.configure(publishableKey:)Initialize Clerk with your publishable key
Clerk.sharedAccess the singleton Clerk instance
clerk.userCurrent authenticated user or nil
clerk.sessionCurrent session information
AuthView()Prebuilt sign-in/sign-up SwiftUI view
UserButton()Profile button with automatic user menu
UserProfileView()Complete user profile management interface
clerk.signOut()Sign out current user
clerk.signIn(emailAddress:password:)Programmatic sign-in
clerk.signUp(emailAddress:password:firstName:lastName:)Programmatic sign-up

Common patterns

Environment-based authentication state:

struct ContentView: View {
    @Environment(Clerk.self) var clerk
    
    var body: some View {
        Group {
            if clerk.user != nil {
                AuthenticatedView()
            } else {
                UnauthenticatedView()
            }
        }
    }
}

Sheet-presented authentication:

@State private var showingAuth = false

Button("Sign in") { showingAuth = true }
.sheet(isPresented: $showingAuth) {
    AuthView()
        .onReceive(clerk.user.publisher) { user in
            if user != nil { showingAuth = false }
        }
}

Custom authentication with error handling:

func signIn() async {
    do {
        try await clerk.signIn(emailAddress: email, password: password)
    } catch {
        errorMessage = error.localizedDescription
    }
}

Profile management integration:

NavigationView {
    VStack {
        if let user = clerk.user {
            UserButton()
                .navigationBarTitleDisplayMode(.inline)
        }
    }
}

Configuration

Required setup in Clerk Dashboard:

  • Enable Native API in Native applications page
  • Add iOS app with App ID Prefix and Bundle ID
  • Note your publishable key

Associated Domains capability:

webcredentials:{YOUR_FRONTEND_API_URL}

Environment configuration:

// Development
Clerk.configure(publishableKey: "pk_test_...")

// Production  
Clerk.configure(publishableKey: "pk_live_...")

Best practices

Configure Clerk in app initializer, not view lifecycle to ensure authentication state is available before views render.

Inject Clerk into SwiftUI environment at the root level to avoid passing the instance through view hierarchies.

Use prebuilt views for standard flows like AuthView and UserProfileView to get automatic updates, accessibility support, and consistent UX.

Handle authentication state reactively using @Environment(Clerk.self) rather than storing user state in local @State variables.

Implement proper error handling for custom authentication flows, as network and validation errors are common.

Test authentication flows on device rather than simulator for Associated Domains functionality to work correctly.

Gotchas and common mistakes

Forgetting to enable Native API in Clerk Dashboard prevents SDK initialization - enable in Native applications page before configuring.

Missing Associated Domains capability breaks seamless auth flows - must add webcredentials:{YOUR_FRONTEND_API_URL} exactly.

Configuring Clerk in view body instead of app initializer causes authentication state loss during view updates.

Not importing both ClerkKit and ClerkKitUI when using prebuilt views causes compilation errors - ClerkKitUI requires ClerkKit.

Incorrect Bundle ID or App ID Prefix in Clerk Dashboard prevents associated domain verification - must match Xcode project exactly.

Assuming immediate authentication after successful sign-in - user object updates are asynchronous, use reactive patterns.

Hardcoding publishable keys in source code exposes credentials - use build configurations or Info.plist for key management.

Not handling network errors in custom authentication flows leads to poor UX - wrap authentication calls in try-catch blocks.

Testing only in simulator misses Associated Domains issues that only manifest on physical devices with proper provisioning.

Mixing authentication patterns by combining prebuilt views with custom flows in the same screen creates UX inconsistencies.