Mobile & Web SDKs · v1.1.0

iOS SDK

Pure Swift. SwiftUI + UIKit components. Phone OTP, WhatsApp OTP, marketing attribution. Zero third-party dependencies — your app size barely moves.

Requirements

  • iOS 14.0+
  • Swift 5.9, Xcode 15+

Install

// In your Xcode project:
//   File → Add Packages → enter the URL below.
// Or add manually to Package.swift:

dependencies: [
    .package(url: "https://github.com/quickauthin/quickauth-sdk-ios", from: "1.1.0"),
],
targets: [
    .target(
        name: "YourApp",
        dependencies: [
            .product(name: "QuickAuth", package: "quickauth-sdk-ios"),
        ]
    ),
]

Pod name vs module name

The CocoaPod is named QuickAuthIn (the bare QuickAuth name was already claimed by an unrelated library). Your Swift code still does import QuickAuth — the pod name only matters in your Podfile.

Initialize

App.swift
import SwiftUI
import QuickAuth

@main
struct MyApp: App {
    init() {
        QuickAuth.shared.initialize(config: Config(
            onTokenExpiry: {
                // Call your backend's /api/quickauth-token endpoint.
                let r = try await myAPI.fetch("/api/quickauth-token")
                return r.sessionToken
            },
            onAuthEvent: { event in
                switch event {
                case .otpSent:                       showOtpInput()
                case .otpAutoRead(let code):         prefillInput(code)
                case .verified(let requestId, _):    finishLogin(requestId)
                case .otpFailed(let message):        showError(message)
                case .error(_, let message):         showError(message)
                }
            }
        ))
    }

    var body: some Scene {
        WindowGroup { ContentView() }
    }
}

Never embed client_secret

The SDK never wants your qa_secret_*** key. Your backend mints session tokens; the SDK calls the closure above to refresh. Anyone can extract a string baked into an iOS bundle — keep secrets on the server. See Backend integration.

Consent

swift
QuickAuth.shared.consent.set(true)
let granted = QuickAuth.shared.consent.get()

Headless flow

Two methods. initiate kicks off the auth attempt; submitOtp hands back the user-typed code. All outcomes arrive on the onAuthEvent closure registered at init — including the OneTap silent re-auth path, where the backend emits .verified directly without sending an SMS.

swift
Task {
    do {
        // Step 1 — kick off the attempt. Events arrive via onAuthEvent.
        try await QuickAuth.shared.auth.initiate(
            phone:   "+919876543210",
            channel: .auto
        )
        // → onAuthEvent fires with one of:
        //     .otpSent(sessionId, channel, expiresIn)   // show input
        //     .verified(requestId, _)                   // OneTap fired
        //     .error(code, message)

        // Step 2 — when .otpSent fires and the user types a code:
        try await QuickAuth.shared.auth.submitOtp("123456")
        // → onAuthEvent fires with .verified / .otpFailed / .error

        // On user-initiated logout, drop the OneTap trust token:
        QuickAuth.shared.auth.reset(forgetDevice: true)
    } catch {
        print("Dispatch failed: \(error)")
    }
}

SMS auto-fill

iOS handles OTP auto-fill natively — set textContentType on your text field and the system keyboard offers a "From Messages" suggestion. The SDK ships a helper for both SwiftUI and UIKit:

import QuickAuth

TextField("Code", text: $code)
    .textContentType(.oneTimeCode)   // <-- this is the magic line
    .keyboardType(.numberPad)

Pre-built UI

import SwiftUI
import QuickAuth

struct LoginView: View {
    @State private var phone = "+919876543210"

    var body: some View {
        QuickAuthLoginButton(
            phone: phone,
            onSuccess: { jwt in saveJwt(jwt) },
            onError:   { err in print(err) }
        )
    }
}

WhatsApp OTP

swift
QuickAuth.shared.auth.startWhatsAppLogin(
    businessNumber: "+919574980048",
    returnURL:      URL(string: "https://app.example.com/wa-return")
)

// Handle the return URL in your SwiftUI app:
.onOpenURL { url in
    Task {
        _ = try? await QuickAuth.shared.attribution.captureLaunch(url: url)
    }
}

Attribution

swift
Task {
    try await QuickAuth.shared.attribution.captureLaunch(url: launchURL)

    try await QuickAuth.shared.attribution.trackConversion(
        event:    "signup",
        value:    0,
        currency: "INR"
    )
}

API reference

SymbolDescription
QuickAuth.shared.initialize(...)App-launch entry point.
.consent.set / getConsent gate.
.auth.initiate(phone:channel:)Begin an auth attempt. Emits .otpSent or .verified.
.auth.submitOtp(_:)Submit the user-typed code. Emits .verified or .otpFailed.
.auth.reset(forgetDevice:)Reset the state machine. Pass forgetDevice: true on logout.
.auth.observeOTP()Combine publisher of inbound OTP codes.
.auth.startWhatsAppLogin(...)Start WhatsApp OTP verification.
QuickAuthLoginButtonSwiftUI component.
QuickAuthLoginButtonViewUIKit component.
QuickAuthOTPTextFieldUIKit input field with oneTimeCode pre-set.
.attribution.captureLaunch / trackConversionAttribution APIs.

Source & changelog

Source: github.com/quickauthin/quickauth-sdk-ios. Pod: QuickAuthIn on CocoaPods.