> ## Documentation Index
> Fetch the complete documentation index at: https://docs.insforge.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Swift authentication SDK reference

> Sign up, sign in, verify email, manage sessions, and configure OAuth URL schemes for iOS, macOS, tvOS, and watchOS with the InsForge Swift SDK.

## Installation

Add InsForge to your Swift Package Manager dependencies:

```swift theme={null}
dependencies: [
    .package(url: "https://github.com/insforge/insforge-swift.git", from: "0.0.9")
]
```

```swift theme={null}
import InsForge

let insforge = InsForgeClient(
    baseURL: URL(string: "https://your-app.insforge.app")!,
    anonKey: "your-anon-key"
)
```

### Enable Logging (Optional)

For debugging, you can configure the SDK log level and destination:

```swift theme={null}
let options = InsForgeClientOptions(
    global: .init(
        logLevel: .debug,
        logDestination: .osLog,
        logSubsystem: "com.example.MyApp"
    )
)

let insforge = InsForgeClient(
    baseURL: URL(string: "https://your-app.insforge.app")!,
    anonKey: "your-anon-key",
    options: options
)
```

**Log Levels:**

| Level       | Description                                 |
| ----------- | ------------------------------------------- |
| `.trace`    | Most verbose, includes all internal details |
| `.debug`    | Detailed information for debugging          |
| `.info`     | General operational information (default)   |
| `.warning`  | Warnings that don't prevent operation       |
| `.error`    | Errors that affect functionality            |
| `.critical` | Critical failures                           |

**Log Destinations:**

| Destination | Description                                                |
| ----------- | ---------------------------------------------------------- |
| `.console`  | Standard output (print)                                    |
| `.osLog`    | Apple's unified logging system (recommended for iOS/macOS) |
| `.none`     | Disable logging                                            |
| `.custom`   | Provide your own LogHandler factory                        |

<Note>
  Use `.info` or `.error` in production to avoid exposing sensitive data in logs.
</Note>

## 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 theme={null}
SignUpResponse
```

### SignUpResponse

```swift theme={null}
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 theme={null}
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 theme={null}
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 theme={null}
{"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 theme={null}
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 theme={null}
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 theme={null}
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 theme={null}
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 theme={null}
ResetPasswordTokenResponse
```

#### ResetPasswordTokenResponse

```swift theme={null}
public struct ResetPasswordTokenResponse: Codable, Sendable {
    /// Reset token to use with resetPassword()
    public let token: String
    /// Token expiration timestamp
    public let expiresAt: Date?
}
```

#### Example

```swift theme={null}
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 theme={null}
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 theme={null}
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 theme={null}
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 theme={null}
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 theme={null}
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)")
    }
}
```
