439 lines
11 KiB
Plaintext
439 lines
11 KiB
Plaintext
---
|
|
title: Swift authentication SDK reference
|
|
description: Sign up, sign in, verify email, manage sessions, and configure OAuth URL schemes for iOS, macOS, tvOS, and watchOS with the InsForge Swift SDK.
|
|
---
|
|
|
|
import SwiftSdkInstallation from '/snippets/swift-sdk-installation.mdx';
|
|
|
|
## Installation
|
|
|
|
<SwiftSdkInstallation />
|
|
|
|
## signUp()
|
|
|
|
Create a new user account with email and password.
|
|
|
|
### Parameters
|
|
|
|
- `email` (String) - User's email address
|
|
- `password` (String) - User's password
|
|
- `name` (String, optional) - User's display name
|
|
|
|
### Returns
|
|
|
|
```swift
|
|
SignUpResponse
|
|
```
|
|
|
|
### SignUpResponse
|
|
|
|
```swift
|
|
public struct SignUpResponse: Codable, Sendable {
|
|
/// User object (nil when email verification is required)
|
|
public let user: User?
|
|
/// Access token (nil when email verification is required)
|
|
public let accessToken: String?
|
|
/// Refresh token (nil when email verification is required)
|
|
public let refreshToken: String?
|
|
/// Indicates if email verification is required before sign-in
|
|
public let requireEmailVerification: Bool?
|
|
|
|
/// Check if email verification is required
|
|
public var needsEmailVerification: Bool
|
|
/// Check if sign up completed with session (no verification required)
|
|
public var hasSession: Bool
|
|
}
|
|
```
|
|
|
|
### Example (Complete Flow with Verification)
|
|
|
|
```swift
|
|
func handleSignUp(email: String, password: String, name: String?) async {
|
|
do {
|
|
let result = try await insforge.auth.signUp(
|
|
email: email,
|
|
password: password,
|
|
name: name
|
|
)
|
|
|
|
if result.needsEmailVerification {
|
|
// Show verification code input screen
|
|
// User will receive a 6-digit code via email
|
|
showEmailVerificationScreen(email: email)
|
|
} else if result.hasSession {
|
|
// Registration complete, user is signed in
|
|
navigateToDashboard()
|
|
}
|
|
} catch {
|
|
showError(error.localizedDescription)
|
|
}
|
|
}
|
|
|
|
// Called when user enters the verification code
|
|
func handleVerifyEmail(email: String, code: String) async {
|
|
do {
|
|
try await insforge.auth.verifyEmail(email: email, code: code)
|
|
// Verification successful, user can now sign in
|
|
navigateToSignIn()
|
|
} catch {
|
|
showError("Invalid verification code")
|
|
}
|
|
}
|
|
|
|
// Called when user requests a new verification email
|
|
func handleResendCode(email: String) async {
|
|
do {
|
|
try await insforge.auth.resendVerificationEmail(email: email)
|
|
showMessage("Verification email sent to \(email)")
|
|
} catch {
|
|
showError("Failed to resend verification email")
|
|
}
|
|
}
|
|
```
|
|
|
|
### Email Verification
|
|
|
|
For users who register with email, the InsForge backend provides three options:
|
|
|
|
1. **No email verification** - Users can sign in immediately after registration. `SignUpResponse` will have `hasSession = true`.
|
|
2. **Link-based verification** - Users must open their email and click the verification link before they can sign in.
|
|
3. **Code-based verification** - The InsForge backend sends a 6-digit verification code to the user's email. The client app needs to display a verification screen where users can enter the code, then call `verifyEmail(email:code:)` to complete verification. Only after this can users sign in with email + password.
|
|
|
|
When `requireEmailVerification` is `true`, the response will have:
|
|
- `accessToken = nil`
|
|
- `user = nil`
|
|
- `needsEmailVerification = true`
|
|
|
|
This indicates that verification via option 2 or 3 is required before the user can sign in.
|
|
|
|
### Related Methods
|
|
|
|
| Method | Description |
|
|
|--------|-------------|
|
|
| `verifyEmail(email:code:)` | Verify email with 6-digit code |
|
|
| `resendVerificationEmail(email:)` | Resend verification email |
|
|
|
|
---
|
|
|
|
## signIn()
|
|
|
|
Sign in an existing user with email and password.
|
|
|
|
### Parameters
|
|
|
|
- `email` (String) - User's email address
|
|
- `password` (String) - User's password
|
|
|
|
### Example
|
|
|
|
```swift
|
|
do {
|
|
let result = try await insforge.auth.signIn(
|
|
email: "user@example.com",
|
|
password: "secure_password123"
|
|
)
|
|
|
|
if let user = result.user {
|
|
print("Welcome back, \(user.profile?.name ?? user.email)")
|
|
}
|
|
} catch {
|
|
print("Sign in failed: \(error)")
|
|
}
|
|
```
|
|
|
|
### Email Verification
|
|
|
|
If the sign in response is:
|
|
```json
|
|
{"error":"FORBIDDEN","message":"Email verification required","statusCode":403,"nextActions":"Please verify your email address before logging in"}
|
|
```
|
|
This indicates that verification via option 2 or 3 (link or code, see [signUp()](#email-verification)) is required before the user can sign in.
|
|
|
|
---
|
|
|
|
## signOut()
|
|
|
|
Sign out the current user.
|
|
|
|
### Example
|
|
|
|
```swift
|
|
do {
|
|
try await insforge.auth.signOut()
|
|
print("User signed out")
|
|
} catch {
|
|
print("Sign out failed: \(error)")
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## getCurrentUser()
|
|
|
|
Get authenticated user with profile data.
|
|
|
|
### Example
|
|
|
|
```swift
|
|
do {
|
|
if let user = try await insforge.auth.getCurrentUser() {
|
|
print("Email: \(user.email)")
|
|
print("Name: \(user.profile?.name ?? "N/A")")
|
|
} else {
|
|
print("No user signed in")
|
|
}
|
|
} catch {
|
|
print("Error: \(error)")
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## setProfile()
|
|
|
|
Update current user's profile.
|
|
|
|
### Example
|
|
|
|
```swift
|
|
do {
|
|
let result = try await insforge.auth.setProfile([
|
|
"name": "JohnDev",
|
|
"bio": "iOS Developer",
|
|
"avatar_url": "https://example.com/avatar.jpg"
|
|
])
|
|
print("Profile updated")
|
|
} catch {
|
|
print("Update failed: \(error)")
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Password Reset
|
|
|
|
InsForge supports two password reset methods, configured in the backend:
|
|
|
|
- **Code method**: User receives a 6-digit code via email, verifies it to get a reset token, then resets password
|
|
- **Link method**: User receives a magic link via email containing the reset token, then resets password directly
|
|
|
|
### sendPasswordReset()
|
|
|
|
Send a password reset email to the user. The email will contain either a 6-digit code or a magic link depending on the backend configuration.
|
|
|
|
#### Parameters
|
|
|
|
- `email` (String) - User's email address
|
|
|
|
#### Example
|
|
|
|
```swift
|
|
do {
|
|
try await insforge.auth.sendPasswordReset(email: "user@example.com")
|
|
// Show message to check email
|
|
showMessage("If your email is registered, you will receive a password reset email.")
|
|
} catch {
|
|
print("Failed to send reset email: \(error)")
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### exchangeResetPasswordToken()
|
|
|
|
Exchange a 6-digit reset code for a reset token. **This method is only used with the code-based reset flow.**
|
|
|
|
#### Parameters
|
|
|
|
- `email` (String) - User's email address
|
|
- `code` (String) - 6-digit numeric code received via email
|
|
|
|
#### Returns
|
|
|
|
```swift
|
|
ResetPasswordTokenResponse
|
|
```
|
|
|
|
#### ResetPasswordTokenResponse
|
|
|
|
```swift
|
|
public struct ResetPasswordTokenResponse: Codable, Sendable {
|
|
/// Reset token to use with resetPassword()
|
|
public let token: String
|
|
/// Token expiration timestamp
|
|
public let expiresAt: Date?
|
|
}
|
|
```
|
|
|
|
#### Example
|
|
|
|
```swift
|
|
do {
|
|
let response = try await insforge.auth.exchangeResetPasswordToken(
|
|
email: "user@example.com",
|
|
code: "123456"
|
|
)
|
|
// Store the token and proceed to password reset screen
|
|
let resetToken = response.token
|
|
showPasswordResetScreen(token: resetToken)
|
|
} catch {
|
|
print("Invalid or expired code: \(error)")
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### resetPassword()
|
|
|
|
Reset the user's password using a reset token.
|
|
|
|
#### Parameters
|
|
|
|
- `otp` (String) - Reset token (from `exchangeResetPasswordToken()` for code flow, or from magic link URL for link flow)
|
|
- `newPassword` (String) - New password meeting the configured requirements
|
|
|
|
#### Example
|
|
|
|
```swift
|
|
do {
|
|
try await insforge.auth.resetPassword(
|
|
otp: resetToken,
|
|
newPassword: "newSecurePassword123"
|
|
)
|
|
// Password reset successful
|
|
showMessage("Password reset successfully. You can now sign in.")
|
|
navigateToSignIn()
|
|
} catch {
|
|
print("Password reset failed: \(error)")
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## signInWithOAuthView()
|
|
|
|
Sign in directly with a specific OAuth provider. This method opens the OAuth provider's authentication page directly.
|
|
|
|
On iOS 12+ and macOS 10.15+, the SDK uses `ASWebAuthenticationSession` to present an in-app authentication browser with automatic callback handling.
|
|
|
|
### Supported Providers
|
|
|
|
```swift
|
|
public enum OAuthProvider: String, Sendable {
|
|
case google
|
|
case github
|
|
case discord
|
|
case linkedin
|
|
case facebook
|
|
case instagram
|
|
case tiktok
|
|
case apple
|
|
case x
|
|
case spotify
|
|
case microsoft
|
|
}
|
|
```
|
|
|
|
### Parameters
|
|
|
|
- `provider` (`OAuthProvider`) - The OAuth provider to authenticate with
|
|
- `redirectTo` (`String`) - Callback URL where InsForge will redirect after authentication
|
|
|
|
### Returns
|
|
|
|
```swift
|
|
AuthResponse
|
|
```
|
|
|
|
Returns `AuthResponse` containing the authenticated user and session tokens.
|
|
|
|
### Authentication Flow
|
|
|
|
```
|
|
1. App calls signInWithOAuthView(provider:redirectTo:)
|
|
2. SDK fetches the OAuth authorization URL from InsForge
|
|
3. SDK opens in-app authentication browser (ASWebAuthenticationSession)
|
|
4. User authenticates with the provider (Google, GitHub, etc.)
|
|
5. SDK automatically handles callback and creates session
|
|
6. Method returns AuthResponse with user data
|
|
```
|
|
|
|
### Example
|
|
|
|
```swift
|
|
import SwiftUI
|
|
import InsForge
|
|
|
|
struct LoginView: View {
|
|
let client: InsForgeClient
|
|
@State private var currentUser: User?
|
|
@State private var errorMessage: String?
|
|
|
|
var body: some View {
|
|
VStack(spacing: 16) {
|
|
Text("Sign in with")
|
|
.font(.headline)
|
|
|
|
// Google Sign In
|
|
Button {
|
|
Task {
|
|
do {
|
|
let response = try await client.auth.signInWithOAuthView(
|
|
provider: .google,
|
|
redirectTo: "yourapp://auth/callback"
|
|
)
|
|
currentUser = response.user
|
|
} catch {
|
|
errorMessage = error.localizedDescription
|
|
}
|
|
}
|
|
} label: {
|
|
HStack {
|
|
Image(systemName: "g.circle.fill")
|
|
Text("Continue with Google")
|
|
}
|
|
.frame(maxWidth: .infinity)
|
|
}
|
|
.buttonStyle(.bordered)
|
|
|
|
if let error = errorMessage {
|
|
Text(error)
|
|
.foregroundColor(.red)
|
|
.font(.caption)
|
|
}
|
|
}
|
|
.padding()
|
|
}
|
|
}
|
|
```
|
|
|
|
### URL scheme configuration
|
|
|
|
Register a callback URL for your app, pass that exact value to `redirectTo`, and add the same value to `allowedRedirectUrls` in Auth Settings. For example, you can use a deep link such as `yourapp://auth/callback` or a claimed HTTPS callback such as `https://app.example.com/auth/callback`. Requests fail with HTTP 400 if `redirectTo` is not allowlisted.
|
|
|
|
---
|
|
|
|
## Error Handling
|
|
|
|
```swift
|
|
do {
|
|
let result = try await insforge.auth.signIn(
|
|
email: email,
|
|
password: password
|
|
)
|
|
} catch let error as InsForgeAuthError {
|
|
switch error {
|
|
case .invalidCredentials:
|
|
print("Invalid email or password")
|
|
case .userNotFound:
|
|
print("User not found")
|
|
case .emailNotVerified:
|
|
print("Please verify your email")
|
|
case .networkError(let underlying):
|
|
print("Network error: \(underlying)")
|
|
default:
|
|
print("Auth error: \(error.localizedDescription)")
|
|
}
|
|
}
|
|
```
|