mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-04 21:04:37 +08:00
## What 1. **Backend dual-accept**: `isAcceptedNativeAppUrl()` accepts both `stack-auth-mobile-oauth-url://` (legacy) and `hexclave-mobile-oauth-url://` (canonical). 2. **Swift SDK switches to the canonical scheme**: `StackAuth` Swift SDK now emits and intercepts `hexclave-mobile-oauth-url://` for native-app OAuth callbacks. Before this PR, `hexclave-mobile-oauth-url` existed only inside `RENAME-TO-HEXCLAVE.md` — not in any code. ## Why the Swift SDK change is safe The Swift SDK uses `ASWebAuthenticationSession(url:callbackURLScheme:completion:)` ([StackClientApp.swift:197-199](sdks/implementations/swift/Sources/StackAuth/StackClientApp.swift#L197)). With this API, iOS intercepts the callback scheme **ephemerally** — no `Info.plist` registration is required. The Swift SDK source has no `Info.plist`, and the example apps' `pbxproj` registers no `CFBundleURLSchemes`. So: - New customer builds against the updated SDK → emit new scheme → backend accepts → `ASWebAuthenticationSession` intercepts on new scheme → works. - Already-shipped customer App Store binaries on older SDK versions → emit old scheme → backend still accepts → works. - **No customer ever has to update an `Info.plist`.** The only real backward-compat constraint is that the backend can never drop the old scheme (already-shipped customer binaries have the constant baked into them). Hence the dual-accept. (Note: `RENAME-TO-HEXCLAVE.md` line 88 incorrectly attributes the constraint to `Info.plist` registration. That's not how the SDK works — the scheme is baked into the SDK binary, not the customer's plist. The fix described in that doc is essentially the right shape; only the mechanism description is wrong.) ## Changes | File | Change | |---|---| | `packages/stack-shared/src/utils/redirect-urls.tsx` | `isAcceptedNativeAppUrl()` accepts either protocol. | | `apps/backend/src/lib/redirect-urls.test.tsx` | Adds positive assertions for the new scheme in `isAcceptedNativeAppUrl`; parity negative assertions in `validateRedirectUrl`. | | `sdks/implementations/swift/Sources/StackAuth/StackClientApp.swift` | `callbackScheme` → `"hexclave-mobile-oauth-url"`; fatalError example strings updated. | | `sdks/implementations/swift/Tests/StackAuthTests/OAuthTests.swift` | Test fixture URLs updated (no assertions depend on the scheme literal). | | `sdks/implementations/swift/Examples/StackAuthiOS/.../StackAuthiOSApp.swift` | Default values in the example UI. | | `sdks/implementations/swift/Examples/StackAuthMacOS/.../StackAuthMacOSApp.swift` | Default values in the example UI. | | `sdks/implementations/swift/README.md` | Documents the new canonical scheme; compat note for the legacy one. | | `sdks/spec/src/apps/client-app.spec.md` | New scheme is canonical; legacy is "accepted indefinitely for already-shipped customer app binaries built against older SDK versions." | ## Verification - `pnpm test run apps/backend/src/lib/redirect-urls.test.tsx` — 34/34 passing (was 33; one new `it` block plus parity assertions). - `pnpm --filter @stackframe/stack-shared --filter @stackframe/backend run lint` — clean. - `pnpm --filter @stackframe/stack-shared --filter @stackframe/backend run typecheck` — clean. - Swift assertions in `OAuthTests.swift` do not check the scheme literal — they only check `oauth/authorize/<provider>`, state/verifier non-emptiness, and that `redirectUrl` round-trips. The fixture-value change is mechanical. ## Risk Low. Backend behavior strictly widens (every URL accepted before is still accepted). Swift SDK change is internal to OAuth callback handling, requires no customer migration, and is paired with the backend dual-accept landing in the same PR. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Adopted the canonical OAuth callback scheme "hexclave-mobile-oauth-url://" for native apps while continuing to accept the legacy "stack-auth-mobile-oauth-url://". * **Documentation** * Updated SDK docs, examples, and spec guidance to reference the canonical callback scheme and clarify legacy acceptance. * **Tests & Samples** * Updated tests and example apps to use and validate the canonical scheme. * **Style** * Rebranded the dev-tool trigger icon to the new Hexclave monochrome logo. <!-- review_stack_entry_start --> [](https://app.coderabbit.ai/change-stack/hexclave/stack-auth/pull/1501?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|---|---|---|
| .. | ||
| .swiftpm/xcode/package.xcworkspace | ||
| StackAuthiOS | ||
| StackAuthiOS.xcodeproj | ||
| README.md | ||
Hexclave iOS Example
An interactive iOS application for testing all Hexclave Swift SDK functions.
Prerequisites
- Xcode 15.0 or later
- iOS 17.0+ Simulator or device
- Running Hexclave backend (default:
http://localhost:8102)
Running the Example
Option 1: Xcode
-
Open the project in Xcode:
open StackAuthiOS.xcodeproj -
Select an iOS Simulator (e.g., "iPhone 15 Pro" or any available device) as the destination
-
Press ⌘R to build and run
Option 2: Command Line
# Build (replace device name with an available simulator on your system)
xcodebuild -scheme StackAuthiOS -destination 'platform=iOS Simulator,name=iPhone 15 Pro' build
# Build and run (opens simulator)
xcodebuild -scheme StackAuthiOS -destination 'platform=iOS Simulator,name=iPhone 15 Pro' run
Features
The app uses a tab-based interface optimized for mobile:
- Settings: Configure API endpoint, project ID, and keys
- Auth: Sign up, sign in, sign out, get current user
- User: Update display name, metadata, view tokens
- Teams: Create, list, and manage teams
- Logs: View all SDK calls with full details (tap for more, long-press to copy)
Additional functions are accessible via navigation links in Settings:
- Contact Channels
- OAuth URL generation
- Token operations
- Server Users (admin)
- Server Teams (admin)
- Sessions (impersonation)
SDK Functions Covered
Client App
signUpWithCredential(email:password:)signInWithCredential(email:password:)signOut()getUser()/getUser(or:)getAccessToken()/getRefreshToken()getAuthHeaders()getOAuthUrl(provider:)
Current User
setDisplayName(_:)update(clientMetadata:)listTeams()/getTeam(id:)createTeam(displayName:)listContactChannels()
Server App
createUser(email:password:...)listUsers(limit:)getUser(id:)createTeam(displayName:)listTeams()createSession(userId:)
Logging
The Logs tab shows all SDK activity in real-time:
- Green checkmark: Successful calls with full response data
- Red X: Errors with details
- Blue info: In-progress calls
Tap any log entry to see full details. Long-press to copy to clipboard.
Network Configuration
For iOS Simulator to connect to your local backend:
- The default
localhost:8102should work in the simulator - For a real device, use your computer's local IP address instead
Troubleshooting
"Could not connect to server"
- Ensure your Hexclave backend is running
- Check the Base URL in Settings tab
- For real devices, use your computer's IP instead of localhost
Build errors
- Make sure you have Xcode 15+ installed
- Try cleaning: Product → Clean Build Folder (⇧⌘K)