Add native AuthKit sign-in to your iOS app with the WorkOS iOS SDK
A step-by-step guide to PKCE-based sign-in with the WorkOS iOS SDK's PublicClient.
WorkOS just shipped its first native mobile SDK: workos-ios. It gives Swift apps async-first access to AuthKit and the full WorkOS API, with generated typed resource clients, structured error handling, safe retries, and AsyncSequence-based auto-pagination, plus helpers for native auth flows, webhook verification, and Vault's local crypto.
The headline feature for mobile teams is PublicClient. Since a mobile app is a public client, it never needs an API key or client secret baked into the binary - it authenticates with just your application's client ID, using PKCE. This tutorial walks through wiring that up: from a blank SwiftUI project to a working "Sign in with AuthKit" button.
What you'll build
A single-screen SwiftUI app with a sign-in button that opens AuthKit in a secure system browser session, then exchanges the result for an authenticated session - no server required for this part of the flow.
Prerequisites
- A WorkOS account and an application configured in the dashboard, with AuthKit enabled
- Xcode 26+, targeting iOS 16+ (the SDK also supports Mac Catalyst 16+, macOS 13+, tvOS 16+, watchOS 9+, and visionOS 1+)
- Swift 6.2+
1. Configure your app in the WorkOS dashboard
In the Applications section of the WorkOS Dashboard, open your application and go to the Redirects tab. Add the redirect URI your app will call back to after sign-in and mark it as the default. WorkOS rejects the flow if you send it to a redirect URI that isn't registered here first, so this has to happen before you write any code.
For a native app, this is typically a custom URL scheme or a universal link, for example:
Note that in production environments the redirect URI can't use http: or localhost (both are fine in sandbox for local testing). If you go with a custom scheme, you'll also need to register it in Xcode under your target's Info → URL Types, so iOS routes the callback into your app.
Copy the application's client ID - you'll need it in code. You will not need an API key for this flow; keep API keys out of the app entirely.
2. Add the SDK
In Xcode: File → Add Package Dependencies, then enter:
Or add it directly to Package.swift:
3. Kick off the PKCE flow
Create a PublicClient with your client ID, then ask it for an authorization URL. The SDK generates the PKCE code verifier and challenge for you:
authorization gives you back the URL to present to the user, plus the codeVerifier and state you'll need after the redirect. Hold on to codeVerifier (e.g., in memory for the duration of the flow) - you'll need it to complete the exchange.
4. Present the sign-in screen
Use ASWebAuthenticationSession to open authorization.url in a secure, system-managed browser session, so cookies and passkeys from the user's default browser are available and the flow feels native:
(Adjust the PublicClient.PKCEAuthorization type name to whatever the SDK's generated type is called if it differs - check autocomplete or the DocC reference for the exact signature in the version you install.)
5. Validate state and exchange the code
Before exchanging anything, confirm the state your app receives matches the state from step 3 - this is what protects the flow from CSRF. Then hand the authorization code and the original PKCE verifier back to PublicClient:
A successful exchange gives you back an authenticated session for the user - their profile plus the tokens your app needs going forward. Store any tokens in the Keychain rather than UserDefaults or in-memory-only state, and check the SDK's API reference for the exact shape of the response in the version you're using, since generated SDKs like this one iterate quickly.
6. Wire it into SwiftUI
Putting it together in a minimal view:
Where to go from here
That's a full native sign-in loop with zero secrets in the app bundle. From here, the same SDK covers a few things worth exploring next:
- Calling the WorkOS API from a trusted server with
WorkOSClient(apiKey:), using the generated typed resource methods and structured errors - Auto-pagination over list endpoints via
AsyncSequence, so you canfor awaitthrough results instead of hand-rolling cursor loops - Vault's local crypto helpers, if you need to encrypt sensitive data on-device
- Webhook verification helpers, for the server side of your integration
Full reference: github.com/workos/workos-ios and the AuthKit docs.