stack/sdks/implementations/swift
Konsti Wohlwend 8052a2be62
Some checks failed
all-good: Did all the other checks pass? / all-good (push) Has been cancelled
Ensure Prisma migrations are in sync with the schema / check_prisma_migrations (22.x) (push) Has been cancelled
DB migration compat / Check if migrations changed (push) Has been cancelled
Docker Server Build and Push / Docker Build and Push Server (push) Has been cancelled
Docker Server Build and Run / docker (push) Has been cancelled
Runs E2E API Tests / E2E Tests (Node ${{ matrix.node-version }}, Freestyle ${{ matrix.freestyle-mode }}) (mock, 22.x) (push) Has been cancelled
Runs E2E API Tests / E2E Tests (Node ${{ matrix.node-version }}, Freestyle ${{ matrix.freestyle-mode }}) (prod, 22.x) (push) Has been cancelled
Runs E2E API Tests with custom port prefix / build (22.x) (push) Has been cancelled
Lint & build / lint_and_build (latest) (push) Has been cancelled
Dev Environment Test With Custom Base Port / restart-dev-and-test-with-custom-base-port (push) Has been cancelled
Dev Environment Test / restart-dev-and-test (push) Has been cancelled
Run setup tests with custom base port / setup-tests-with-custom-base-port (push) Has been cancelled
Run setup tests / setup-tests (push) Has been cancelled
TOC Generator / TOC Generator (push) Has been cancelled
DB migration compat / Back-compat — Current branch migrations with ${{ needs.check-migrations-changed.outputs.base_branch }} branch code (push) Has been cancelled
DB migration compat / Forward-compat — Current branch code with ${{ needs.check-migrations-changed.outputs.base_branch }} branch migrations (push) Has been cancelled
DB migration compat / No migration changes (skipped) (push) Has been cancelled
"Require publishable client key" toggle (#1158)
<!--

Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md

-->

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **High Risk**
> Touches authentication and OAuth token/authorize flows and changes how
client requests are validated, so regressions could cause widespread
login/client-access failures. Also includes a data migration that alters
effective security posture for existing projects.
> 
> **Overview**
> Adds a **project-level toggle**
(`project.requirePublishableClientKey`) to control whether client
requests/OAuth flows must include a publishable client key, including a
DB migration that backfills existing projects to require it.
> 
> Backend auth now treats the publishable client key as *optional when
allowed*, introducing a public sentinel (`__stack_public_client__`) and
returning a new specific error
(`PUBLISHABLE_CLIENT_KEY_REQUIRED_FOR_PROJECT`) across smart request
auth + OAuth `authorize`/`callback`/`token` endpoints.
> 
> Dashboard and SDKs update key generation/display and request
construction to handle missing publishable keys, expose an advanced
toggle on the Project Keys page, and extend internal config overrides to
support a new `project` level; E2E/tests and schema fuzzing are expanded
accordingly, and CI adds a forward-compat migration check job when
back-compat fails.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
5d06c08613. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Project-level config to require publishable client keys; migration
applied to existing projects.

* **Improvements**
* Auth flows now support optional publishable client keys with explicit
validation and a sentinel for keyless OAuth.
* Dashboard/UI and SDKs handle publishable keys as optional and
conditionally show/generate them.
  * Admin/client APIs extended to manage project-level overrides.

* **Bug Fixes**
  * Key validation behavior aligned with project config.

* **Tests**
* Expanded E2E and unit tests covering optional/required publishable-key
scenarios.

* **Documentation**
* Spec and knowledge docs updated to describe the sentinel and config
behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-02-19 10:23:16 -08:00
..
Examples [Fix] [Feat] Update OAuth Sign-In and Get Token Functions to Work (#1130) 2026-01-28 02:17:27 +00:00
Sources/StackAuth "Require publishable client key" toggle (#1158) 2026-02-19 10:23:16 -08:00
Tests/StackAuthTests "Require publishable client key" toggle (#1158) 2026-02-19 10:23:16 -08:00
.gitignore [Fix] [Feat] Update OAuth Sign-In and Get Token Functions to Work (#1130) 2026-01-28 02:17:27 +00:00
package.json chore: update package versions 2026-02-19 10:20:51 -08:00
Package.resolved [Fix] [Feat] Update OAuth Sign-In and Get Token Functions to Work (#1130) 2026-01-28 02:17:27 +00:00
Package.swift [Fix] [Feat] Update OAuth Sign-In and Get Token Functions to Work (#1130) 2026-01-28 02:17:27 +00:00
README.md [Fix] [Feat] Update OAuth Sign-In and Get Token Functions to Work (#1130) 2026-01-28 02:17:27 +00:00

Stack Auth Swift SDK

Swift SDK for Stack Auth. Supports iOS, macOS, watchOS, tvOS, and visionOS.

Requirements

  • Swift 5.9+
  • iOS 15+ / macOS 12+ / watchOS 8+ / tvOS 15+ / visionOS 1+

Installation

Add to your Package.swift:

dependencies: [
    .package(url: "https://github.com/stack-auth/swift-sdk-prerelease", from: <version>)
]

Quick Start

import StackAuth

let stack = StackClientApp(
    projectId: "your-project-id",
    publishableClientKey: "your-key"
)

// Sign in with email/password
try await stack.signInWithCredential(email: "user@example.com", password: "password")

// Get current user
if let user = try await stack.getUser() {
    print("Signed in as \(user.displayName ?? "Unknown")")
}

// Sign out
try await stack.signOut()

Design Decisions

Error Handling

All functions that can fail use Swift's native throws. Errors conform to StackAuthError:

do {
    try await stack.signInWithCredential(email: email, password: password)
} catch let error as StackAuthError {
    switch error.code {
    case "email_password_mismatch":
        print("Wrong password")
    default:
        print(error.message)
    }
}

Token Storage

  • Default: Keychain (secure, persists across app launches)
  • Option: Memory (for testing or ephemeral sessions)
  • Option: Custom TokenStoreProtocol implementation
// Memory storage (for testing)
let stack = StackClientApp(
    projectId: "...",
    publishableClientKey: "...",
    tokenStore: .memory
)

// Custom storage
let stack = StackClientApp(
    projectId: "...",
    publishableClientKey: "...",
    tokenStore: .custom(MyTokenStore())
)

OAuth Flows

Two approaches for OAuth authentication:

1. Integrated (recommended) - Uses ASWebAuthenticationSession:

// Opens auth session, handles callback automatically
// Uses fixed callback scheme: stack-auth-mobile-oauth-url://
try await stack.signInWithOAuth(provider: "google")

2. Manual URL handling - For custom implementations:

Note: The stack-auth-mobile-oauth-url:// scheme is automatically accepted.

// Get the OAuth URL (must provide absolute URLs)
let oauth = try await stack.getOAuthUrl(
    provider: "google",
    redirectUrl: "stack-auth-mobile-oauth-url://success",
    errorRedirectUrl: "stack-auth-mobile-oauth-url://error"
)

// Open oauth.url in your own browser/webview
// Store oauth.state, oauth.codeVerifier, and oauth.redirectUrl

// When callback received:
try await stack.callOAuthCallback(
    url: callbackUrl,
    codeVerifier: oauth.codeVerifier,
    redirectUrl: oauth.redirectUrl
)

Async/Await

All async operations use Swift's native concurrency:

Task {
    let user = try await stack.getUser()
    let teams = try await user?.listTeams()
}

Key Differences from JavaScript SDK

Aspect JavaScript Swift
Token Storage Cookies Keychain
OAuth Browser redirect ASWebAuthenticationSession
Redirect methods Available Not available (browser-only)
React hooks useUser() etc. Not applicable

Not Available in Swift

The following are browser-only and not exposed:

  • redirectToSignIn(), redirectToSignUp(), etc.
  • Cookie-based token storage
  • redirectMethod constructor option

Examples

Interactive example apps are available for testing all SDK functions:

macOS Example

cd Examples/StackAuthMacOS
swift run

Features a sidebar-based UI for testing authentication, user management, teams, OAuth, tokens, and server-side operations.

iOS Example

cd Examples/StackAuthiOS
open Package.swift  # Opens in Xcode

Features a tab-based UI optimized for iOS with the same comprehensive SDK coverage.

Both examples include:

  • Configurable API endpoints
  • Real-time operation logs
  • Error testing scenarios (wrong password, unauthorized access, etc.)
  • Client and server app operations

Testing

Tests use Swift Testing framework against a running backend.

Running Tests

  1. Start the development server:

    pnpm dev
    
  2. Run tests:

    cd sdks/implementations/swift
    swift test
    

The tests connect to http://localhost:8102 (or ${NEXT_PUBLIC_STACK_PORT_PREFIX}02).

API Reference

See the SDK Specification for complete API documentation.