-
Notifications
You must be signed in to change notification settings - Fork 501
docs: Document Swift SDK (Preview) #1131
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,190 @@ | ||
| import { CodeExample } from '../lib/code-examples'; | ||
|
|
||
| export const swiftExamples = { | ||
| 'swift': { | ||
| 'installation': [ | ||
| { | ||
| language: 'Swift', | ||
| framework: 'Swift', | ||
| variant: 'package', | ||
| code: `dependencies: [ | ||
| .package(url: "https://github.com/stack-auth/swift-sdk-prerelease", from: "0.1.0") | ||
| ]`, | ||
| highlightLanguage: 'swift', | ||
| filename: 'Package.swift' | ||
| } | ||
| ] as CodeExample[], | ||
|
|
||
| 'init-sdk': [ | ||
| { | ||
| language: 'Swift', | ||
| framework: 'Swift', | ||
| code: `import StackAuth | ||
|
|
||
| let stack = StackClientApp( | ||
| projectId: "your-project-id", | ||
| publishableClientKey: "pck_your-publishable-key" | ||
| )`, | ||
| highlightLanguage: 'swift', | ||
| filename: 'App.swift' | ||
| } | ||
| ] as CodeExample[], | ||
|
|
||
| 'sign-up-sign-in': [ | ||
| { | ||
| language: 'Swift', | ||
| framework: 'Swift', | ||
| code: `// Sign up with email/password | ||
| try await stack.signUpWithCredential( | ||
| email: "user@example.com", | ||
| password: "securepassword123" | ||
| ) | ||
|
|
||
| // Sign in with email/password | ||
| try await stack.signInWithCredential( | ||
| email: "user@example.com", | ||
| password: "securepassword123" | ||
| ) | ||
|
|
||
| // OAuth sign-in (opens system browser) | ||
| try await stack.signInWithOAuth(provider: "google")`, | ||
| highlightLanguage: 'swift', | ||
| filename: 'AuthView.swift' | ||
| } | ||
| ] as CodeExample[], | ||
|
|
||
| 'get-user': [ | ||
| { | ||
| language: 'Swift', | ||
| framework: 'Swift', | ||
| code: `if let user = try await stack.getUser() { | ||
| print("Signed in as \\(user.displayName ?? "Unknown")") | ||
| print("Email: \\(user.primaryEmail ?? "No email")") | ||
| }`, | ||
| highlightLanguage: 'swift', | ||
| filename: 'UserView.swift' | ||
| } | ||
| ] as CodeExample[], | ||
|
|
||
| 'sign-out': [ | ||
| { | ||
| language: 'Swift', | ||
| framework: 'Swift', | ||
| code: `try await stack.signOut()`, | ||
| highlightLanguage: 'swift', | ||
| filename: 'AuthView.swift' | ||
| } | ||
| ] as CodeExample[], | ||
|
|
||
| 'token-storage': [ | ||
| { | ||
| language: 'Swift', | ||
| framework: 'Swift', | ||
| code: `// Default: Keychain (secure, persists across app launches) | ||
| let stack = StackClientApp( | ||
| projectId: "...", | ||
| publishableClientKey: "..." | ||
| ) | ||
|
|
||
| // Memory storage (for testing or ephemeral sessions) | ||
| let stack = StackClientApp( | ||
| projectId: "...", | ||
| publishableClientKey: "...", | ||
| tokenStore: .memory | ||
| ) | ||
|
|
||
| // Explicit tokens (for server-side scenarios) | ||
| let stack = StackClientApp( | ||
| projectId: "...", | ||
| publishableClientKey: "...", | ||
| tokenStore: .explicit(accessToken: "...", refreshToken: "...") | ||
| )`, | ||
| highlightLanguage: 'swift', | ||
| filename: 'App.swift' | ||
| } | ||
| ] as CodeExample[], | ||
|
|
||
| 'error-handling': [ | ||
| { | ||
| language: 'Swift', | ||
| framework: 'Swift', | ||
| code: `do { | ||
| try await stack.signInWithCredential(email: email, password: password) | ||
| } catch let error as StackAuthError { | ||
| switch error.code { | ||
| case "EMAIL_PASSWORD_MISMATCH": | ||
| print("Invalid email or password") | ||
| case "USER_NOT_FOUND": | ||
| print("No account found with this email") | ||
| default: | ||
| print("Error: \\(error.message)") | ||
| } | ||
| }`, | ||
| highlightLanguage: 'swift', | ||
| filename: 'AuthView.swift' | ||
| } | ||
| ] as CodeExample[], | ||
|
|
||
| 'oauth': [ | ||
| { | ||
| language: 'Swift', | ||
| framework: 'Swift', | ||
| variant: 'simple', | ||
| code: `// Opens system browser, handles callback automatically | ||
| // Uses the fixed callback scheme: stack-auth:// | ||
| try await stack.signInWithOAuth(provider: "google")`, | ||
| highlightLanguage: 'swift', | ||
| filename: 'AuthView.swift' | ||
| }, | ||
| { | ||
| language: 'Swift', | ||
| framework: 'Swift', | ||
| variant: 'custom', | ||
| code: `// Get OAuth URL for manual handling | ||
| // Must provide full URLs with scheme | ||
| let oauth = try await stack.getOAuthUrl( | ||
| provider: "google", | ||
| redirectUrl: "stack-auth://oauth-callback", | ||
| errorRedirectUrl: "stack-auth://error" | ||
| ) | ||
|
|
||
| // Open oauth.url in your own browser/webview | ||
| // Store oauth.state, oauth.codeVerifier, and oauth.redirectUrl | ||
|
|
||
| // When callback is received: | ||
| try await stack.callOAuthCallback( | ||
| url: callbackUrl, | ||
| codeVerifier: oauth.codeVerifier, | ||
| redirectUrl: oauth.redirectUrl | ||
| )`, | ||
| highlightLanguage: 'swift', | ||
| filename: 'OAuthHandler.swift' | ||
| } | ||
| ] as CodeExample[], | ||
|
|
||
| 'server-side': [ | ||
| { | ||
| language: 'Swift', | ||
| framework: 'Swift', | ||
| code: `let serverApp = StackServerApp( | ||
| projectId: "your-project-id", | ||
| secretServerKey: "ssk_your-secret-key" | ||
| ) | ||
|
|
||
| // List all users | ||
| let users = try await serverApp.listUsers() | ||
|
|
||
| // Get a specific user | ||
| let user = try await serverApp.getUser(userId: "user-id") | ||
|
|
||
| // Create a user | ||
| let newUser = try await serverApp.createUser( | ||
| primaryEmail: "new@example.com", | ||
| password: "securepassword" | ||
| )`, | ||
| highlightLanguage: 'swift', | ||
| filename: 'Server.swift' | ||
| } | ||
| ] as CodeExample[], | ||
| } | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,131 @@ | ||
| --- | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Citation: Based on the Swift SDK implementation in |
||
| title: Swift SDK (Preview) | ||
| lastModified: "2026-01-22" | ||
| --- | ||
|
|
||
| <Info type="warning"> | ||
| The Swift SDK is currently in preview. APIs may change before the stable release. We'd love your feedback—join our [Discord](https://discord.stack-auth.com) to share your thoughts. | ||
| </Info> | ||
|
|
||
| The Swift SDK provides native authentication for iOS, macOS, watchOS, tvOS, and visionOS apps. It uses async/await, Keychain storage, and system OAuth flows. | ||
|
|
||
| ## Requirements | ||
|
|
||
| - Swift 5.9 or later | ||
| - iOS 15+ / macOS 12+ / watchOS 8+ / tvOS 15+ / visionOS 1+ | ||
|
|
||
| ## Installation | ||
|
|
||
| Add the SDK to your project using Swift Package Manager. In your `Package.swift`: | ||
|
|
||
| <PlatformCodeblock | ||
| document="getting-started/swift" | ||
| examples={["installation"]} | ||
| /> | ||
|
|
||
| Or in Xcode: | ||
| 1. Go to File → Add Package Dependencies | ||
| 2. Enter `https://github.com/stack-auth/swift-sdk-prerelease` | ||
| 3. Select your desired version and add to your target | ||
|
|
||
| ## Quick Start | ||
|
|
||
| ### Initialize the SDK | ||
|
|
||
| <PlatformCodeblock | ||
| document="getting-started/swift" | ||
| examples={["init-sdk"]} | ||
| /> | ||
|
|
||
| Get your project ID and publishable key from the [Stack Auth dashboard](https://app.stack-auth.com). | ||
|
|
||
| ### Sign Up and Sign In | ||
|
|
||
| <PlatformCodeblock | ||
| document="getting-started/swift" | ||
| examples={["sign-up-sign-in"]} | ||
| /> | ||
|
|
||
| ### Get the Current User | ||
|
|
||
| <PlatformCodeblock | ||
| document="getting-started/swift" | ||
| examples={["get-user"]} | ||
| /> | ||
|
|
||
| ### Sign Out | ||
|
|
||
| <PlatformCodeblock | ||
| document="getting-started/swift" | ||
| examples={["sign-out"]} | ||
| /> | ||
|
|
||
| ## Token Storage | ||
|
|
||
| By default, tokens are stored securely in the system Keychain. You can configure alternative storage: | ||
|
|
||
| <PlatformCodeblock | ||
| document="getting-started/swift" | ||
| examples={["token-storage"]} | ||
| /> | ||
|
|
||
| ## Error Handling | ||
|
|
||
| SDK methods use Swift's native `throws` mechanism. Errors conform to `StackAuthError`: | ||
|
|
||
| <PlatformCodeblock | ||
| document="getting-started/swift" | ||
| examples={["error-handling"]} | ||
| /> | ||
|
|
||
| ## OAuth Authentication | ||
|
|
||
| The Swift SDK uses `ASWebAuthenticationSession` for OAuth, providing a secure system browser experience. | ||
|
|
||
| ### Simple OAuth (Recommended) | ||
|
|
||
| For most apps, simply use `signInWithOAuth()` — it handles the entire OAuth flow automatically. It uses the `stack-auth://` callback scheme, which works without any additional configuration: | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Citation: OAuth API changes from PR #1130: |
||
|
|
||
| <PlatformCodeblock | ||
| document="getting-started/swift" | ||
| examples={["oauth"]} | ||
| /> | ||
|
|
||
| ### Manual OAuth Flow | ||
|
|
||
| If you need more control, use `getOAuthUrl()` to get the authorization URL and handle the callback yourself. You'll need to provide redirect URLs: | ||
|
|
||
| - **`redirectUrl`**: Where the provider redirects on success (e.g., `stack-auth://oauth-callback`) | ||
| - **`errorRedirectUrl`**: Where the provider redirects on error (e.g., `stack-auth://error`) | ||
|
|
||
| <Info> | ||
| The `stack-auth://` scheme works out of the box. If you want to use a custom scheme (like `myapp://`), you'll need to add it as a trusted domain in your Stack Auth project settings. | ||
| </Info> | ||
|
|
||
| ## Server-Side Usage | ||
|
|
||
| For server-side operations, use `StackServerApp`: | ||
|
|
||
| <PlatformCodeblock | ||
| document="getting-started/swift" | ||
| examples={["server-side"]} | ||
| /> | ||
|
|
||
| <Info type="warning"> | ||
| Never include your secret server key in client-side code. `StackServerApp` should only be used in secure server environments. | ||
| </Info> | ||
|
|
||
| ## Key Differences from JavaScript SDK | ||
|
|
||
| | Feature | JavaScript SDK | Swift SDK | | ||
| |---------|---------------|-----------| | ||
| | Token Storage | Cookies | Keychain | | ||
| | OAuth Flow | Browser redirect | ASWebAuthenticationSession | | ||
| | Redirect Methods | Available | Not available (browser-only) | | ||
| | React Hooks | `useUser()`, etc. | Not applicable | | ||
|
|
||
| ## Next Steps | ||
|
|
||
| - Check out the [REST API documentation](/api/overview) for all available endpoints | ||
| - Join our [Discord community](https://discord.stack-auth.com) to share feedback on the Swift SDK preview | ||
| - See the [example apps](https://github.com/stack-auth/stack-auth/tree/main/sdks/implementations/swift/Examples) for more usage examples | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Citation: Updated OAuth code examples based on PR #1130. The new API signatures are documented in
sdks/implementations/swift/README.mdand the spec atsdks/spec/src/apps/client-app.spec.md.View source