Back to OSS
Swift Package 認証 / 課金

swift-authentication

Google / Apple Sign-In を async/await で扱う Firebase 認証統合パッケージ

Swift
firebaseauthenticationsign-in

English | 日本語

swift-authentication

A modular authentication package that wires Firebase / Apple / Google / REST concretions into a vendor-agnostic core — one target at a time.

Swift Platforms SPM License

Design

Authentication is split into three responsibilities, each defined as a vendor-agnostic protocol. Concrete implementations live in separate targets and are composed at the app's composition root.

Responsibility Protocol (core) Concrete (separate target)
Credential acquisition CredentialProvider AppleCredentialProvider / GoogleCredentialProvider
Session exchange Authenticator FirebaseAuthenticator
Post-auth action (idempotent) PostAuthenticationAction APIUserProvisioning (REST)

AuthenticationStore (@Observable, @MainActor) wires these together and exposes a state property that views observe.

Target Layout

Target Role External dependencies
Authentication Core abstractions (protocols, value types, AuthenticationStore) None
AuthenticationUI SwiftUI views + Environment DI SwiftUI (system)
AuthenticationApple Apple credential acquisition AuthenticationServices / CryptoKit (system)
AuthenticationGoogle Google credential acquisition GoogleSignIn
AuthenticationFirebase Firebase session exchange and configuration FirebaseAuth
AuthenticationAPI REST post-authentication action swift-api-client

The core (Authentication) and UI (AuthenticationUI) targets have zero vendor SDK dependencies. Views can depend on only these two, keeping SwiftUI Previews free of Firebase / GoogleSignIn. Concrete implementations (Firebase, etc.) are imported only at the composition root.

Installation

dependencies: [
    .package(url: "https://github.com/no-problem-dev/swift-authentication.git", from: "2.0.0")
]

Add only the products your target needs:

  • Screen modules → AuthenticationUI (+ Authentication)
  • Composition root (App target) → AuthenticationFirebase / AuthenticationApple / AuthenticationGoogle / AuthenticationAPI

Usage

1. Compose AuthenticationStore at the composition root

import SwiftUI
import Authentication
import AuthenticationUI
import AuthenticationFirebase
import AuthenticationApple
import AuthenticationGoogle
import AuthenticationAPI
import APIClient
import FirebaseCore

@main
struct MyApp: App {
    @State private var store: AuthenticationStore

    init() {
        FirebaseConfigurator.configure()   // Production. Use .configure(environment: .emulator()) for local dev.

        let tokenProvider = FirebaseTokenProvider()
        let apiClient = APIClient(
            baseURL: URL(string: "https://api.example.com")!,
            authTokenProvider: APITokenProviderAdapter(tokenProvider)
        )

        let clientID = FirebaseConfigurator.googleClientID ?? ""

        _store = State(initialValue: AuthenticationStore(
            authenticator: FirebaseAuthenticator(),
            postAuthentication: APIUserProvisioning(apiClient: apiClient, path: "/auth/initialize"),
            credentialProviders: [
                AppleCredentialProvider(),
                GoogleCredentialProvider(clientID: clientID)
            ]
        ))
    }

    var body: some Scene {
        WindowGroup {
            AuthenticatedRootView(
                loading: { ProgressView() },
                unauthenticated: {
                    VStack(spacing: 16) {
                        GoogleSignInButton()
                        AppleSignInButton()
                    }
                    .padding(.horizontal, 32)
                },
                error: { error in Text(error.localizedDescription) },
                authenticated: { user in MainView(userID: user.id) }
            )
            .authenticationStore(store)
        }
    }
}

2. Screen views (previewable, vendor-free)

import SwiftUI
import Authentication
import AuthenticationUI

struct MainView: View {
    @Environment(\.authenticationStore) private var store
    let userID: String

    var body: some View {
        VStack {
            Text("Welcome, \(userID)")
            Button("Sign Out") { Task { try? await store?.signOut() } }
        }
    }
}

#Preview {
    // No Firebase needed — uses a stub.
    MainView(userID: "preview")
        .authenticationStore(.previewUnauthenticated)
}

State

AuthenticationState transitions:

  • .checking — verifying stored session on launch
  • .unauthenticated — no active session
  • .authenticatedPendingProvisioning — session exchanged, post-auth action pending
  • .authenticated(AuthUser) — fully authenticated
  • .error(any Error) — an error occurred

Backend API (optional)

When using APIUserProvisioning, provide a POST <path> endpoint (default /auth/initialize). The Firebase ID token is automatically attached as Authorization: Bearer. The store calls provisioning once per authentication session, but the server endpoint should also be idempotent. If provisioning is not required, omit postAuthentication (defaults to NoPostAuthentication).

Custom Providers

AuthProviderID is open-ended. Implement CredentialProvider / Authenticator / PostAuthenticationAction to plug in any backend — direct Firestore access, custom OIDC, etc.

License

MIT License. See LICENSE for details.

同じカテゴリの OSS — 認証 / 課金

swift-subscription

Swift Package

RevenueCat 統合のサブスクリプション管理を SwiftUI でシンプルに

Swift
· 認証 / 課金
revenuecatsubscriptionin-app-purchase

© 2026 Kyoichi Taniguchi. All rights reserved.