> ## 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 身份驗證 SDK 參考

> 使用 InsForge Swift SDK 為 iOS、macOS、tvOS 和 watchOS 註冊、登入、驗證電子郵件、管理工作階段和設定 OAuth URL 方案。

## 安裝

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()

使用電子郵件和密碼建立新使用者帳戶。

### 參數

* `email` (String) - 使用者的電子郵件地址
* `password` (String) - 使用者的密碼
* `name` (String, optional) - 使用者的顯示名稱

### 傳回值

```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
}
```

### 範例（包含驗證的完整流程）

```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")
    }
}
```

### 電子郵件驗證

對於使用電子郵件註冊的使用者，InsForge 後端提供三種選擇：

1. **不需要電子郵件驗證** - 使用者可在註冊後立即登入。`SignUpResponse` 將具有 `hasSession = true`。
2. **基於連結的驗證** - 使用者必須打開其電子郵件並按一下驗證連結才能登入。
3. **基於代碼的驗證** - InsForge 後端向使用者的電子郵件傳送 6 位數驗證碼。用戶端應用需要顯示驗證畫面，使用者可以輸入代碼，然後呼叫 `verifyEmail(email:code:)` 完成驗證。只有這樣使用者才能使用電子郵件和密碼登入。

當 `requireEmailVerification` 為 `true` 時，回應將具有：

* `accessToken = nil`
* `user = nil`
* `needsEmailVerification = true`

這表示在使用者登入之前需要透過選項 2 或 3 進行驗證。

### 相關方法

| 方法                                | 描述              |
| --------------------------------- | --------------- |
| `verifyEmail(email:code:)`        | 使用 6 位數代碼驗證電子郵件 |
| `resendVerificationEmail(email:)` | 重新傳送驗證電子郵件      |

***

## signIn()

使用電子郵件和密碼登入現有使用者。

### 參數

* `email` (String) - 使用者的電子郵件地址
* `password` (String) - 使用者的密碼

### 範例

```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)")
}
```

### 電子郵件驗證

如果登入回應是：

```json theme={null}
{"error":"FORBIDDEN","message":"Email verification required","statusCode":403,"nextActions":"Please verify your email address before logging in"}
```

這表示在使用者登入之前需要透過選項 2 或 3（連結或代碼，請參閱 [signUp()](#電子郵件驗證)）進行驗證。

***

## signOut()

登出目前的使用者。

### 範例

```swift theme={null}
do {
    try await insforge.auth.signOut()
    print("User signed out")
} catch {
    print("Sign out failed: \\(error)")
}
```

***

## getCurrentUser()

取得具有設定檔資料的已驗證使用者。

### 範例

```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()

更新目前使用者的設定檔。

### 範例

```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)")
}
```

***

## 密碼重設

InsForge 支援兩種密碼重設方法，在後端中設定：

* **代碼方法**：使用者透過電子郵件接收 6 位數代碼、驗證它以取得重設令牌，然後重設密碼
* **連結方法**：使用者透過電子郵件接收包含重設令牌的魔法連結，然後直接重設密碼

### sendPasswordReset()

向使用者傳送密碼重設電子郵件。電子郵件將包含 6 位數代碼或魔法連結，具體取決於後端設定。

#### 參數

* `email` (String) - 使用者的電子郵件地址

#### 範例

```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()

將 6 位數重設代碼交換為重設令牌。**此方法僅用於基於代碼的重設流程。**

#### 參數

* `email` (String) - 使用者的電子郵件地址
* `code` (String) - 透過電子郵件接收的 6 位數代碼

#### 傳回值

```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?
}
```

#### 範例

```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()

使用重設令牌重設使用者的密碼。

#### 參數

* `otp` (String) - 重設令牌（從 `exchangeResetPasswordToken()` 取得的代碼流程，或從魔法連結 URL 取得的連結流程）
* `newPassword` (String) - 符合設定要求的新密碼

#### 範例

```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()

直接使用特定的 OAuth 提供者登入。此方法打開 OAuth 提供者的驗證頁面。

在 iOS 12+ 和 macOS 10.15+ 上，SDK 使用 `ASWebAuthenticationSession` 顯示應用內驗證瀏覽器，具有自動回呼處理。

### 支援的提供者

```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
}
```

### 參數

* `provider` (`OAuthProvider`) - 要驗證的 OAuth 提供者
* `redirectTo` (`String`) - InsForge 驗證後將重新導向到的回呼 URL

### 傳回值

```swift theme={null}
AuthResponse
```

傳回包含已驗證使用者和工作階段令牌的 `AuthResponse`。

### 驗證流程

```
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
```

### 範例

```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 方案設定

為您的應用註冊回呼 URL，將該確切值傳遞給 `redirectTo`，並將相同值新增至驗證設定中的 `allowedRedirectUrls`。例如，您可以使用深層連結如 `yourapp://auth/callback` 或已宣告的 HTTPS 回呼如 `https://app.example.com/auth/callback`。如果 `redirectTo` 不在允許清單中，要求將以 HTTP 400 失敗。

***

## 錯誤處理

```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)")
    }
}
```
