FirebaseUI ile iOS uygulamanıza oturum açma özelliği ekleme

SwiftUI için FirebaseUI, Firebase Authentication üzerine kurulu, modern ve SwiftUI öncelikli bir kitaplıktır. Bu kitaplık, uygulamanıza önceden oluşturulmuş oturum açma akışları sağlar.

SwiftUI için FirebaseUI'nin aşağıdaki avantajları vardır:

  • Fikre dayalı varsayılan kullanıcı arayüzü: AuthPickerView ile eksiksiz bir oturum açma akışı ekleyin.
  • Özelleştirilebilir: Varsayılan düğmeleri kendi düzeninizde oluşturun veya tamamen özel bir deneyim oluşturun.
  • Anonim hesap bağlama: Anonim kullanıcıları değiştirmek yerine isteğe bağlı olarak yükseltin.
  • Hesap yönetimi: Kaydolma, şifre kurtarma ve hesap yönetimi için yerleşik akışlar.
  • Birden fazla sağlayıcı: E-posta/şifre, e-posta bağlantısı, telefon kimlik doğrulaması, Apple, Google, Facebook, Twitter ve standart OAuth2/OIDC sağlayıcıları.
  • Modern kimlik doğrulama özellikleri: Çok öğeli kimlik doğrulaması (MFA) ve async/await API'leri için yerleşik destek.

Başlamadan önce

  • Firebase'i Apple projenize ekleyin. SwiftUI adımlarını tamamladığınızdan emin olun.

  • Uygulamanızın iOS 17 veya sonraki bir sürümü hedeflediğinden emin olun.

Kurulum

SwiftUI için FirebaseUI, Swift paketi olarak sağlanır. Paketi Xcode projenize yüklemek için aşağıdakileri yapın:

  1. Xcode'da File > Add Package Dependencies'ı (Dosya > Paket Bağımlılıkları Ekle) tıklayın.

  2. Paket URL'sini girin:

    https://github.com/firebase/FirebaseUI-iOS
    
  3. Bağımlılık Kuralı menüsünde Bir Sonraki Ana Sürüme Kadar'ı seçin ve minimum sürümü en son yayınlanan sürüm olarak ayarlayın.

  4. Paket Ekle'yi tıklayın ve projenize eklemek istediğiniz kitaplıkları seçin.

    Aşağıdaki kitaplık her zaman gereklidir. Temel bağımlılıkların yanı sıra e-posta/şifre ile giriş ve e-posta bağlantısı ile giriş desteğini içerir.

    • FirebaseAuthSwiftUI

     Diğer oturum açma yöntemlerini desteklemek istiyorsanız aşağıdaki kitaplıklardan birini veya daha fazlasını da seçin:

    • FirebaseAppleSwiftUI (Apple ile oturum açma)
    • FirebaseGoogleSwiftUI (Google ile oturum açma)
    • FirebaseFacebookSwiftUI (Facebook ile oturum açma)
    • FirebasePhoneAuthSwiftUI (Telefon kimlik doğrulaması)
    • FirebaseTwitterSwiftUI (Twitter ile oturum aç)
    • FirebaseOAuthSwiftUI (GitHub, Microsoft, Yahoo gibi standart OAuth ve OIDC sağlayıcılar)
  5. Seçili kitaplıkları yüklemek için Paket Ekle'yi tıklayın.

  6. FirebaseUI'ın AuthService özelliğini üst düzey başlatıcıda yapılandırın View ve hizmeti ortamı kullanarak alt görünümlere iletin.

    import FirebaseAuthSwiftUI
    import SwiftUI
    
    struct ContentView: View {
      let authService: AuthService
    
      init() {
        let configuration = AuthConfiguration()
    
        authService = AuthService(configuration: configuration)
          .withEmailSignIn() // Or whatever sign-in methods you want to support.
                             // See the next section.
      }
    
      var body: some View {
        AuthPickerView { // AuthPickerView (the prebuilt View) or a custom View.
            Text("Welcome to your app!")
        }
        .environment(authService)
      }
    }
    

Oturum açma yöntemlerini ayarlama

Desteklenen oturum açma yöntemlerinin her biri için ek kurulum adımları gerekir. Aşağıdaki bölümleri genişletin ve tek tek sağlayıcıları ayarlamak için talimatları uygulayın.

E-posta adresi ve şifre

  1. Firebase konsolunun Güvenlik > Kimlik doğrulama > Oturum açma yöntemi bölümünde E-posta/Şifre sağlayıcısını etkinleştirin.

  2. Sağlayıcıyı AuthService örneğinize kaydedin:

    let authService = AuthService()
      .withEmailSignIn()
    

Şifresiz e-posta bağlantısı ile oturum açma özelliğini kullanmak için:

  1. Firebase konsolunun Güvenlik > Kimlik doğrulama > Oturum açma yöntemi bölümünde E-posta/Şifre'yi etkinleştirin, ardından e-posta bağlantısı ile oturum açma özelliğini etkinleştirin. E-posta bağlantısıyla oturum açma özelliğini kullanmak için e-posta veya şifreyle oturum açma özelliğinin etkinleştirilmesi gerektiğini unutmayın.

  2. Bağlantı alanını Yetkilendirilmiş alanlar'a ekleyin.

  3. ActionCodeSettings öğesini yapılandırın, AuthConfiguration öğesine iletin ve sağlayıcıyı kaydedin:

    let actionCodeSettings = ActionCodeSettings()
    actionCodeSettings.handleCodeInApp = true
    actionCodeSettings.url = URL(string: "https://yourapp.firebaseapp.com")
    
    guard let bundleID = Bundle.main.bundleIdentifier else {
      fatalError("Missing bundle identifier for email link authentication setup.")
    }
    actionCodeSettings.setIOSBundleID(bundleID)
    
    let configuration = AuthConfiguration(
      emailLinkSignInActionCodeSettings: actionCodeSettings
    )
    
    let authService = AuthService(configuration: configuration)
      .withEmailLinkSignIn()
    
  4. FirebaseApp.configure() işlevini çağırdığınız AppDelegate içinde, açılan URL bir Firebase Authentication oturum açma bağlantısı olduğunda true döndüren application(_:open:options:) yöntemine mantık ekleyin. Bu mantık, bağlantının FirebaseUI tarafından işlendiğini ve diğer bağlantı işleyiciler tarafından işlenmemesi gerektiğini gösterir.

    import FacebookCore
    import FirebaseAuth
    import UIKit
    
    class AppDelegate: NSObject, UIApplicationDelegate {
      func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
      ) -> Bool {
        FirebaseApp.configure()
        return true
      }
    
      func application(
        _ application: UIApplication,
        open url: URL,
        options: [UIApplication.OpenURLOptionsKey: Any] = [:]
      ) -> Bool {
        if Auth.auth().canHandle(url) {
          return true
        }
        return false
      }
    }
    
  5. Özel görünümler oluşturursanız bağlantı uygulamanızı açtığında authService.handleSignInLink(url:) işlevini çağırın.

Apple

Apple ile oturum açma özelliğini kullanmak için:

  1. Apple ile oturum açma özelliğini yapılandırma:

    1. Apple'ın geliştirici sitesindeki Certificates, Identifiers & Profiles (Sertifikalar, Tanımlayıcılar ve Profiller) sayfasında uygulamanız için Apple ile oturum açma özelliğini etkinleştirin.
    2. Web için Apple ile oturum açma özelliğini yapılandırma başlıklı makalenin ilk bölümünde açıklandığı şekilde web sitenizi uygulamanızla ilişkilendirin. İstendiğinde aşağıdaki URL'yi Dönüş URL'si olarak kaydedin:
      https://YOUR_FIREBASE_PROJECT_ID.firebaseapp.com/__/auth/handler
      Firebase proje kimliğinizi Firebase konsol ayarları sayfasından alabilirsiniz. İşlemi tamamladığınızda yeni hizmet kimliğinizi not edin. Bu kimliğe bir sonraki bölümde ihtiyacınız olacak.
    3. Apple ile oturum açma için özel anahtar oluşturun. Bir sonraki bölümde yeni özel anahtarınız ve anahtar kimliğiniz gereklidir.
    4. E-posta bağlantısıyla oturum açma, e-posta adresi doğrulama, hesap değişikliği iptali gibi kullanıcılara e-posta gönderen Firebase Authentication özelliklerini kullanıyorsanız Apple'ın özel e-posta aktarma hizmetini yapılandırın ve noreply@YOUR_FIREBASE_PROJECT_ID.firebaseapp.com'ü (veya özelleştirilmiş e-posta şablonu alanınızı) kaydedin. Böylece Apple, Firebase Authentication tarafından gönderilen e-postaları anonimleştirilmiş Apple e-posta adreslerine aktarabilir.
  2. Firebase konsolunun Güvenlik > Kimlik doğrulama > Oturum açma yöntemi bölümünde Apple'ı etkinleştirin.

    • Önceki bölümde oluşturduğunuz hizmet kimliğini belirtin.
    • OAuth kod akışı yapılandırması bölümünde, Apple Ekip Kimliğinizi ve önceki bölümde oluşturduğunuz özel anahtarı ve anahtar kimliğini belirtin.
  3. Xcode'da proje düzenleyicisinin Signing & Capabilities (İmzalama ve Yetenekler) bölümünü açın ve Sign in with Apple (Apple ile oturum açma) özelliğini ekleyin.

  4. Sağlayıcıyı AuthService örneğinize kaydedin:

    let authService = AuthService()
      .withAppleSignIn()
    

Google

Google ile oturum açma özelliğini kullanmak için:

  1. Firebase konsolunun Güvenlik > Kimlik doğrulama > Oturum açma yöntemi bölümünde Google sağlayıcısını etkinleştirin.

  2. Projenizin GoogleService-Info.plist dosyasının yeni bir kopyasını indirip Xcode projenize kopyalayın. Mevcut sürümlerin üzerine yeni sürümü yazın.

  3. Xcode projenize özel URL şemaları ekleyin:

    1. Proje yapılandırmanızı açın: Soldaki ağaç görünümünde proje adını tıklayın. HEDEFLER bölümünden uygulamanızı seçin, ardından Bilgi sekmesini seçin ve URL Türleri bölümünü genişletin.

    2. + düğmesini tıklayın ve tersine çevrilmiş müşteri kimliğiniz için bir URL şeması ekleyin. Bu değeri bulmak için GoogleService-Info.plist yapılandırma dosyasını açın ve REVERSED_CLIENT_ID anahtarını bulun. Bu anahtarın değerini kopyalayın ve yapılandırma sayfasındaki URL Şemaları kutusuna yapıştırın. Diğer alanları değiştirmeyin.

      Tamamlandığında yapılandırmanız aşağıdaki gibi görünmelidir (ancak uygulamaya özel değerlerinizle birlikte):

  4. Sağlayıcıyı AuthService örneğinize kaydedin:

    let authService = AuthService()
      .withGoogleSignIn()
    

Facebook

Facebook ile Giriş'i kullanmak için:

  1. Meta for Developers sitesindeki talimatları uygulayarak iOS için Facebook Girişi SDK'sını ayarlayın. Son adım olan "Facebook ile Giriş'i Kodunuza Ekleme" bölümünü atlayın.

  2. Firebase konsolunun Güvenlik > Kimlik doğrulama > Oturum açma yöntemi bölümünde Facebook sağlayıcısını etkinleştirin. Meta for Developers sitesinden Facebook uygulama kimliği ve uygulama istemci sırrı almanız gerekir.

  3. Sağlayıcıyı AuthService örneğinize kaydedin:

    let authService = AuthService()
     .withFacebookSignIn()
    

Telefon numarası

Telefon kimlik doğrulamasını kullanmak için:

  1. Firebase konsolunun Güvenlik > Kimlik doğrulama > Oturum açma yöntemi bölümünde Telefon sağlayıcısını etkinleştirin.

  2. Sessiz bildirimler almaya başlama bölümünde belirtildiği şekilde uygulamanız için APN'leri yapılandırın.

  3. Xcode projenize özel URL şemaları ekleyin:

    1. Proje yapılandırmanızı açın: Soldaki ağaç görünümünde proje adını tıklayın. HEDEFLER bölümünden uygulamanızı seçin, ardından Bilgi sekmesini seçin ve URL Türleri bölümünü genişletin.

    2. + düğmesini tıklayın ve kodlanmış uygulama kimliğinizi URL şeması olarak ekleyin. Bu değeri bulmak için Firebase konsolunda Ayarlar > Genel'i açın.

      Tamamlandığında yapılandırmanız aşağıdaki gibi görünmelidir (ancak uygulamaya özel değerlerinizle birlikte):

  4. AppDelegate içinde FirebaseApp.configure() işlevini çağırdığınız aynı yerde APNs jetonu işleyicilerini ekleyin:

    import FacebookCore
    import FirebaseAuth
    import UIKit
    
    class AppDelegate: NSObject, UIApplicationDelegate {
      func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
      ) -> Bool {
        FirebaseApp.configure()
        return true
      }
    
      func application(
        _ application: UIApplication,
        didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
      ) {
        #if DEBUG
        Auth.auth().setAPNSToken(deviceToken, type: .sandbox)
        #else
        Auth.auth().setAPNSToken(deviceToken, type: .prod)
        #endif
      }
    }
    
  5. Sağlayıcıyı AuthService örneğinize kaydedin:

    let authService = AuthService()
      .withPhoneSignIn()
    

Twitter (X)

Twitter ile giriş özelliğini kullanmak için:

  1. X Developers sitesindeki talimatları uygulayarak X API kimlik bilgileri oluşturun.

  2. Firebase konsolunun Güvenlik > Kimlik doğrulama > Oturum açma yöntemi bölümünde Twitter sağlayıcısını etkinleştirin. X Developer Console'dan API anahtarı ve API gizli anahtarı almanız gerekir.

  3. Sağlayıcıyı AuthService örneğinize kaydedin:

    let authService = AuthService()
      .withTwitterSignIn()
    

Standart OAuth2 ve OIDC sağlayıcıları

FirebaseUI; GitHub, Microsoft ve Yahoo gibi yerleşik OAuth sağlayıcılarının yanı sıra Firebase Authentication'da yapılandırılan özel OIDC sağlayıcılarını da destekler.

 let authService = AuthService()
  .withOAuthSignIn(OAuthProviderSwift.github())
  .withOAuthSignIn(OAuthProviderSwift.microsoft())
  .withOAuthSignIn(OAuthProviderSwift.yahoo())

Özel OIDC sağlayıcıları için önce sağlayıcıyı Firebase Authentication'da yapılandırın, ardından sağlayıcı kimliğiniz ve düğme yapılandırmanızla bir OAuthProviderSwift oluşturun:

let lineProvider = OAuthProviderSwift(
  providerId: "oidc.line",
  buttonLabel: "Sign in with LINE",
  displayName: "LINE",
  iconSystemName: "person.crop.circle.badge.checkmark",
  buttonBackgroundColor: .green,
  buttonForegroundColor: .white
)

let authService = AuthService()
  .withOAuthSignIn(lineProvider)

Hazır kimlik doğrulama görünümünü kullanma

SwiftUI için FirebaseUI, AuthPickerView adlı, önceden oluşturulmuş ve belirli bir görüşe dayalı bir kimlik doğrulama kullanıcı arayüzü sağlar. Bu kullanıcı arayüzü, kimlik doğrulama akışının tamamını sizin için yönetir. Bu, uygulamanıza kimlik doğrulama eklemenin en kolay yoludur.

Örnek

Birden fazla sağlayıcı ve yapılandırma seçeneğiyle kullanılan AuthPickerView örneğini aşağıda bulabilirsiniz:

import FirebaseAppleSwiftUI
import FirebaseAuthSwiftUI
import FirebaseGoogleSwiftUI
import SwiftUI

struct ContentView: View {
  let authService: AuthService

  init() {
    // Create configuration with options
    let configuration = AuthConfiguration(
      tosUrl: URL(string: "https://example.com/tos"),
      privacyPolicyUrl: URL(string: "https://example.com/privacy"),
      shouldAutoUpgradeAnonymousUsers: true
    )

    // Initialize AuthService with multiple providers
    authService = AuthService(configuration: configuration)
      .withEmailSignIn()
      .withAppleSignIn()
      .withGoogleSignIn()
  }

  var body: some View {
    AuthPickerView {
      authenticatedContent
    }
    .environment(authService)
  }

  var authenticatedContent: some View {
    NavigationStack {
      VStack(spacing: 20) {
        if authService.authenticationState == .authenticated {
          Text("Authenticated")
          
          Button("Manage Account") {
            authService.isPresented = true
          }
          .buttonStyle(.bordered)
          
          Button("Sign Out") {
            Task {
              try? await authService.signOut()
            }
          }
          .buttonStyle(.borderedProminent)
        } else {
          Text("Not Authenticated")
          
          Button("Sign In") {
            authService.isPresented = true
          }
          .buttonStyle(.borderedProminent)
        }
      }
      .navigationTitle("My App")
    }
    .onChange(of: authService.authenticationState) { _, newValue in
      // Automatically show auth UI when not authenticated
      if newValue != .authenticating {
        authService.isPresented = (newValue == .unauthenticated)
      }
    }
  }
}

Tipik özelleştirme

AuthConfiguration parametrelerinin tümü isteğe bağlı olsa da çoğu uygulama en azından aşağıdaki ayarları özelleştirir:

let configuration = AuthConfiguration(
    logo: ImageResource.exampleLogoAsset,
    customStringsBundle: .main,
    tosUrl: URL(string: "https://example.com/tos"),
    privacyPolicyUrl: URL(string: "https://example.com/privacy"),
)
  • logo: Kimlik doğrulama sayfasında gösterilen logo resmi. Kendi resim öğenizi ekleme hakkında bilgi için Xcode projenize resim ekleme başlıklı makaleyi inceleyin.

  • customStringsBundle: Belirtilen paketteki özel dizeleri kullanın. Bu, yerelleştirme için olduğu kadar AuthPickerView tarafından kullanılan varsayılan dizeleri özelleştirmek için de kullanılır. Örneğin, kimlik doğrulama sayfasının en üstünde gösterilen mesajı ayarlamak için aşağıdaki içeriklere sahip bir Localizable.strings oluşturun:

    "Sign in with Firebase" = "Sign in to use ExampleApp";
    

Hazır görünümde neler yer alır?

AuthPickerView kullandığınızda:

  1. Sayfa Sunumu: Kimlik doğrulama kullanıcı arayüzü, modal sayfa olarak görünür.
  2. Yerleşik gezinme: Oturum açma, şifre kurtarma, çok faktörlü kimlik doğrulama, e-posta bağlantısı ve telefon doğrulama ekranları arasında otomatik gezinme
  3. Kimlik Doğrulama Durumu Yönetimi: authService.authenticationState temelinde kimlik doğrulama kullanıcı arayüzü ile içeriğiniz arasında otomatik olarak geçiş yapar.
  4. isPresented üzerinden kontrol: authService.isPresented = true/false ayarını yaparak kimlik doğrulama sayfasının ne zaman görüneceğini kontrol edin.

Kendi fikrine göre hareket etme

Varsayılan AuthPickerView, çeşitli karmaşık senaryoların nasıl ele alınacağı konusunda belirli bir yaklaşım benimser:

1. Hesap çakışması çözümü

Hesap çakışması oluştuğunda (ör. başka bir hesaba zaten bağlı olan bir kimlik bilgisiyle oturum açma) AuthPickerView bunu otomatik olarak ele alır:

  • Anonim Yükseltme Çakışmaları: shouldAutoUpgradeAnonymousUsers etkinleştirilmişse ve anonim yükseltme sırasında bir çakışma meydana gelirse sistem, anonim kullanıcının oturumunu otomatik olarak kapatır ve yeni kimlik bilgisiyle oturum açar.
  • Diğer Çakışmalar: Anonim olmayan hesaplar arasındaki kimlik bilgisi çakışmalarında sistem, bekleyen kimlik bilgisini saklar ve başarılı oturum açma işleminden sonra bu kimlik bilgisini bağlamaya çalışır.

Bu, NavigationStack düzeyinde uygulanan AccountConflictModifier ile işlenir.

2. Çok öğeli kimlik doğrulaması (MFA)

Yapılandırmanızda MFA etkinleştirildiğinde:

  • Oturum açma sırasında çok faktörlü kimlik doğrulamanın gerekli olup olmadığını otomatik olarak algılar.
  • Uygun MFA çözünürlüğü ekranlarını (SMS veya TOTP) gösterir.
  • Çok faktörlü kimlik doğrulama kaydı ve yönetim akışlarını işler.
  • Hem SMS tabanlı hem de zamana dayalı tek kullanımlık şifre (TOTP) faktörlerini destekler.
3. Hata işleme

Varsayılan görünümler, yerleşik hata işlemeyi içerir:

  • Uyarı iletişim kutularında kullanıcı dostu hata mesajları gösterir.
  • Dahili olarak işlenen hataları (ör.iptal hataları, otomatik olarak işlenen çakışmalar) otomatik olarak filtreler.
  • StringUtils üzerinden yerelleştirilmiş hata mesajlarını kullanır.
  • Hatalar, reportError ortam anahtarı aracılığıyla yayılır.

E-posta bağlantısı oturum açma özelliği yapılandırıldığında:

  • E-posta adresini uygulama depolama alanında otomatik olarak saklar.
  • E-postadan gelen derin bağlantı gezinmesini işler
  • E-posta doğrulama akışının tamamını yönetir.
  • E-posta bağlantısı üzerinden anonim kullanıcı yükseltmelerini destekler.
5. Anonim kullanıcılar için otomatik yeni sürüme geçiş

shouldAutoUpgradeAnonymousUsers etkinleştirildiğinde:

  • Anonim hesapları yeni oturum açma kimlik bilgileriyle otomatik olarak bağlamaya çalışır.
  • Anonim oturumları değiştirmek yerine yükselterek kullanıcı verilerini korur.
  • Yükseltme çakışmalarını sorunsuz şekilde yönetir.
6. Varsayılan görünümlerde yeniden kimlik doğrulama

Hesap silme, şifre güncelleme veya çok faktörlü kimlik doğrulama faktörlerini kayıttan çıkarma gibi hassas işlemler için yakın zamanda kimlik doğrulama yapılması gerekir. Varsayılan görünümler kullanılırken yeniden kimlik doğrulama, kullanıcının oturum açma sağlayıcısına göre otomatik olarak gerçekleştirilir.

Hassas bir işlem için yeniden kimlik doğrulama gerektiğinde varsayılan görünümler otomatik olarak:

  • OAuth Sağlayıcıları (Google, Apple, Facebook, Twitter vb.): Kullanıcıdan onaylamasını isteyen bir uyarı gösterin, ardından otomatik olarak yeni kimlik bilgileri alın ve işlemi tamamlayın.

  • E-posta/Şifre: Kullanıcıya devam etmeden önce şifresini girmesini isteyen bir sayfa gösterilir.

  • E-posta bağlantısı: Doğrulama e-postası göndermeyi isteyen bir uyarı gösterin, ardından e-postayı kontrol etme talimatlarının yer aldığı bir sayfa gösterin. Kullanıcı, yeniden kimlik doğrulama işlemini tamamlamak için e-postasındaki bağlantıya dokunur.

  • Telefon: Doğrulama gerektiğini açıklayan bir uyarı gösterin, ardından SMS kodu doğrulama için bir sayfa sunun.

İşlem, yeniden kimlik doğrulama başarılı olduktan sonra otomatik olarak yeniden denenir. AuthPickerView veya yerleşik hesap yönetimi görünümleri (UpdatePasswordView, SignedInView vb.) kullanılırken ek kod gerekmez.

İleri düzey: Özel kimlik doğrulama görünümleri oluşturma

Kullanıcı arayüzü veya gezinme akışı üzerinde daha fazla kontrol sahibi olmanız gerekiyorsa kimlik doğrulama mantığı için AuthService'dan yararlanmaya devam ederken kendi özel kimlik doğrulama görünümlerinizi oluşturabilirsiniz.

FirebaseUI öğelerini özel mantıkla birçok şekilde karıştırabilirsiniz. Aşağıdaki bölümlerde, kullanabileceğiniz bazı özelleştirme yaklaşımlarına ilişkin örnekler verilmiştir.

1. yaklaşım: registerProvider() içeren özel düğmeler

Düğme görünümü üzerinde tam kontrol sahibi olmak için herhangi bir sağlayıcıyı sarmalayan ve özel düğme görünümünüzü döndüren kendi özel AuthProviderUI uygulamanızı oluşturabilirsiniz.

Özel sağlayıcı kullanıcı arayüzü oluşturma

Örnek olarak özel bir Twitter düğmesi oluşturma adımları aşağıda verilmiştir:

import FirebaseAuthSwiftUI
import FirebaseTwitterSwiftUI
import SwiftUI

// Step 1: Create your custom button view
struct CustomTwitterButton: View {
  let provider: TwitterProviderSwift
  @Environment(AuthService.self) private var authService
  @Environment(\.mfaHandler) private var mfaHandler

  var body: some View {
    Button {
      Task {
        do {
          let outcome = try await authService.signIn(provider)

          // Handle MFA if required
          if case let .mfaRequired(mfaInfo) = outcome,
             let onMFA = mfaHandler {
            onMFA(mfaInfo)
          }
        } catch {
          // Do Something Else
        }
      }
    } label: {
      HStack { // Your custom icon
        Text("Sign in with Twitter")
          .fontWeight(.semibold)
      }
      .frame(maxWidth: .infinity)
      .padding()
      .background(
        LinearGradient(
          colors: [Color.blue, Color.cyan],
          startPoint: .leading,
          endPoint: .trailing
        )
      )
      .foregroundColor(.white)
      .cornerRadius(12)
      .shadow(radius: 4)
    }
  }
}

// Step 2: Create a custom AuthProviderUI wrapper
class CustomTwitterProviderAuthUI: AuthProviderUI {
  private let typedProvider: TwitterProviderSwift
  var provider: AuthProviderSwift { typedProvider }
  let id: String = "twitter.com"

  init(provider: TwitterProviderSwift = TwitterProviderSwift()) {
    typedProvider = provider
  }

  @MainActor func authButton() -> AnyView {
    AnyView(CustomTwitterButton(provider: typedProvider))
  }
}

// Step 3: Use it in your app
struct ContentView: View {
  let authService: AuthService

  init() {
    let configuration = AuthConfiguration()
    authService = AuthService(configuration: configuration)

    // Register your custom provider UI
    authService.registerProvider(
      providerWithButton: CustomTwitterProviderAuthUI()
    )
    authService.isPresented = true
  }

  var body: some View {
    AuthPickerView {
      usersApp
    }
    .environment(authService)
  }

  var usersApp: some View {
    NavigationStack {
      VStack {
        Button {
          authService.isPresented = true
        } label: {
          Text("Authenticate")
        }
      }
    }
  }
}

Basitleştirilmiş özel düğme örneği

Ayrıca, herhangi bir sağlayıcı için daha basit özel düğmeler de oluşturabilirsiniz:

import FirebaseAuthSwiftUI
import FirebaseGoogleSwiftUI
import FirebaseAppleSwiftUI
import SwiftUI

// Custom Google Provider UI
class CustomGoogleProviderAuthUI: AuthProviderUI {
  private let typedProvider: GoogleProviderSwift
  var provider: AuthProviderSwift { typedProvider }
  let id: String = "google.com"
  
  init() {
    typedProvider = GoogleProviderSwift()
  }
  
  @MainActor func authButton() -> AnyView {
    AnyView(CustomGoogleButton(provider: typedProvider))
  }
}

struct CustomGoogleButton: View {
  let provider: GoogleProviderSwift
  @Environment(AuthService.self) private var authService
  
  var body: some View {
    Button {
      Task {
        try? await authService.signIn(provider)
      }
    } label: {
      HStack {
        Image(systemName: "g.circle.fill")
        Text("My Custom Google Button")
      }
      .frame(maxWidth: .infinity)
      .padding()
      .background(Color.purple) // Your custom color
      .foregroundColor(.white)
      .cornerRadius(10)
    }
  }
}

// Then use it
struct ContentView: View {
  let authService: AuthService
  
  init() {
    let configuration = AuthConfiguration()
    authService = AuthService(configuration: configuration)
      .withAppleSignIn() // Use default Apple button
    
    // Use custom Google button
    authService.registerProvider(
      providerWithButton: CustomGoogleProviderAuthUI()
    )
  }
  
  var body: some View {
    AuthPickerView {
      Text("App Content")
    }
    .environment(authService)
  }
}

Bu yaklaşım Google, Apple, Twitter, Facebook, telefon ve OAuth sağlayıcıları dahil tüm sağlayıcılar için geçerlidir. Özel düğme görünümünüzü oluşturup AuthProviderUI protokolüne uygun bir sınıfa sarmalamanız yeterlidir.

2. yaklaşım: Özel görünümlere sahip varsayılan düğmeler

Kendi düzeninizi ve gezinmenizi sağlarken varsayılan kimlik doğrulama düğmelerini oluşturmak için AuthService.renderButtons() öğesini kullanabilir ve AuthPickerView öğesini atlayabilirsiniz:

import FirebaseAuthSwiftUI
import FirebaseGoogleSwiftUI
import FirebaseAppleSwiftUI
import SwiftUI

struct CustomAuthView: View {
  @Environment(AuthService.self) private var authService

  var body: some View {
    VStack(spacing: 30) {
      // Your custom logo/branding
      Image("app-logo")
        .resizable()
        .frame(width: 150, height: 150)
      
      Text("Welcome to My App")
        .font(.largeTitle)
        .fontWeight(.bold)
      
      Text("Sign in to continue")
        .font(.subheadline)
        .foregroundStyle(.secondary)
      
      // Render default auth buttons
      authService.renderButtons(spacing: 12)
        .padding()
    }
    .padding()
  }
}

struct ContentView: View {
  init() {
    let configuration = AuthConfiguration()
    
    authService = AuthService(configuration: configuration)
      .withGoogleSignIn()
      .withAppleSignIn()
  }
  
  let authService: AuthService

  var body: some View {
    NavigationStack {
      if authService.authenticationState == .authenticated {
        Text("Authenticated!")
      } else {
        CustomAuthView()
      }
    }
    .environment(authService)
  }
}

3. yaklaşım: Özel gezinme içeren özel görünümler

Akışın tamamı üzerinde tam kontrol sahibi olmak için AuthPickerView simgesini atlayabilir ve kendi gezinme sisteminizi oluşturabilirsiniz:

import FirebaseAuth
import FirebaseAuthSwiftUI
import FirebaseGoogleSwiftUI
import SwiftUI

enum CustomAuthRoute {
  case signIn
  case phoneVerification
  case mfaResolution
}

struct ContentView: View {
  private let authService: AuthService
  @State private var navigationPath: [CustomAuthRoute] = []
  @State private var errorMessage: String?

  init() {
    let configuration = AuthConfiguration()
    self.authService = AuthService(configuration: configuration)
      .withGoogleSignIn()
      .withPhoneSignIn()
  }

  var body: some View {
    NavigationStack(path: $navigationPath) {
      Group {
        if authService.authenticationState == .authenticated {
          authenticatedView
        } else {
          customSignInView
        }
      }
      .navigationDestination(for: CustomAuthRoute.self) { route in
        switch route {
        case .signIn:
          customSignInView
        case .phoneVerification:
          customPhoneVerificationView
        case .mfaResolution:
          customMFAView
        }
      }
    }
    .environment(authService)
    .alert("Error", isPresented: .constant(errorMessage != nil)) {
      Button("OK") {
        errorMessage = nil
      }
    } message: {
      Text(errorMessage ?? "")
    }
  }

  var customSignInView: some View {
    VStack(spacing: 20) {
      Text("Custom Sign In")
        .font(.title)
      
      Button("Sign in with Google") {
        Task {
          do {
            let provider = GoogleProviderSwift(clientID: Auth.auth().app?.options.clientID ?? "")
            let outcome = try await authService.signIn(provider)
            
            // Handle MFA if required
            if case .mfaRequired = outcome {
              navigationPath.append(.mfaResolution)
            }
          } catch {
            errorMessage = error.localizedDescription
          }
        }
      }
      .buttonStyle(.borderedProminent)
      
      Button("Phone Sign In") {
        navigationPath.append(.phoneVerification)
      }
      .buttonStyle(.bordered)
    }
    .padding()
  }

  var customPhoneVerificationView: some View {
    Text("Custom Phone Verification View")
    // Implement your custom phone auth UI here
  }

  var customMFAView: some View {
    Text("Custom MFA Resolution View")
    // Implement your custom MFA UI here
  }

  var authenticatedView: some View {
    VStack(spacing: 20) {
      Text("Welcome!")
      Text("Email: \(authService.currentUser?.email ?? "N/A")")
      
      Button("Sign Out") {
        Task {
          try? await authService.signOut()
        }
      }
      .buttonStyle(.borderedProminent)
    }
  }
}

Özel görünümlerle ilgili önemli noktalar

Özel görünümler oluştururken AuthPickerView tarafından otomatik olarak işlenen birkaç şeyi kendiniz yapmanız gerekir:

  1. Hesap çakışmaları: AuthServiceError.accountConflict kullanarak kendi çakışma çözme stratejinizi uygulayın.
  2. MFA İşleme: SignInOutcome için .mfaRequired'yi kontrol edin ve MFA çözümünü manuel olarak gerçekleştirin.
  3. Anonim Kullanıcı Yükseltmeleri: shouldAutoUpgradeAnonymousUsers etkinse anonim hesapların bağlantısını yönetin
  4. Gezinme Durumu: Farklı kimlik doğrulama ekranları (telefon doğrulama, şifre kurtarma vb.) arasında gezinmeyi yönetin.
  5. Yükleme Durumları: authService.authenticationState gözlemlenerek asenkron kimlik doğrulama işlemleri sırasında yükleme göstergeleri gösterilir.
  6. Yeniden kimlik doğrulama: Hassas işlemler için yeniden kimlik doğrulama hatalarını ele alın (aşağıdaki Özel Görünümlerde Yeniden Kimlik Doğrulama bölümüne bakın).

Özel görünümlerde yeniden kimlik doğrulama

Özel görünümler oluştururken belirli hataları yakalayıp kendi akışınızı uygulayarak yeniden kimlik doğrulama işlemini gerçekleştirin. Hassas işlemler, her biri bağlam bilgisi içeren dört tür yeniden kimlik doğrulama hatası verir.

Uygulama kalıpları

OAuth Sağlayıcıları (Google, Apple, Facebook, Twitter vb.):

Hatayı yakalayın ve OAuth akışını otomatik olarak işleyen reauthenticate(context:) işlevini çağırın:

do {
  try await authService.deleteUser()
} catch let error as AuthServiceError {
  if case .oauthReauthenticationRequired(let context) = error {
    try await authService.reauthenticate(context: context)
    try await authService.deleteUser() // Retry operation
  }
}

E-posta/Şifre:

Hatayı yakalayın, şifre isteyin, kimlik bilgisi oluşturun ve reauthenticate(with:) işlevini çağırın:

do {
  try await authService.updatePassword(to: newPassword)
} catch let error as AuthServiceError {
  if case .emailReauthenticationRequired(let context) = error {
    // Show your password prompt UI
    let password = await promptUserForPassword()
    let credential = EmailAuthProvider.credential(
      withEmail: context.email,
      password: password
    )
    try await authService.reauthenticate(with: credential)
    try await authService.updatePassword(to: newPassword) // Retry
  }
}

Telefon:

Hatayı yakalayın, telefonu doğrulayın, kimlik bilgisi oluşturun ve reauthenticate(with:)'yı arayın:

do {
  try await authService.deleteUser()
} catch let error as AuthServiceError {
  if case .phoneReauthenticationRequired(let context) = error {
    // Send verification code
    let verificationId = try await authService.verifyPhoneNumber(
      phoneNumber: context.phoneNumber
    )
    // Show your SMS code input UI
    let code = await promptUserForSMSCode()
    let credential = PhoneAuthProvider.provider().credential(
      withVerificationID: verificationId,
      verificationCode: code
    )
    try await authService.reauthenticate(with: credential)
    try await authService.deleteUser() // Retry
  }
}

E-posta bağlantısı:

Hatayı yakalayın, doğrulama e-postası gönderin ve gelen URL'yi işleyin:

do {
  try await authService.updatePassword(to: newPassword)
} catch let error as AuthServiceError {
  if case .emailLinkReauthenticationRequired(let context) = error {
    // Send verification email
    try await authService.sendEmailSignInLink(
      email: context.email,
      isReauth: true
    )
    // Show your "Check your email" UI
    await showCheckEmailUI()
    // When user taps the link, it opens your app with a URL
    // Handle it in your URL handler:
    // try await authService.handleSignInLink(url: url)
    // The handleSignInLink method automatically completes reauthentication
    try await authService.updatePassword(to: newPassword) // Retry
  }
}

Tüm yeniden kimlik doğrulama bağlamı nesneleri, kullanıcıya yönelik metin için bir .displayMessage özelliği içerir.

Özel OAuth sağlayıcıları

Yerleşik olanların dışındaki hizmetler için özel OAuth sağlayıcıları oluşturabilirsiniz:

⚠️ Önemli: OIDC (OpenID Connect) sağlayıcılarının kullanılabilmesi için Firebase projenizin Kimlik Doğrulama ayarlarında yapılandırılması gerekir. Firebase konsolunda Kimlik doğrulama → Oturum açma yöntemi'ne gidin ve OIDC sağlayıcınızı gerekli kimlik bilgileriyle (istemci kimliği, istemci gizli anahtarı, yayıncı URL'si) ekleyin. Ayrıca, Firebase tarafından sağlanan OAuth yönlendirme URI'sini sağlayıcınızın geliştirici konsoluna kaydetmeniz gerekir. Ayrıntılı kurulum talimatları için Firebase OIDC belgelerine bakın.

import FirebaseAuthSwiftUI
import FirebaseOAuthSwiftUI
import SwiftUI

struct ContentView: View {
  let authService: AuthService

  init() {
    let configuration = AuthConfiguration()
    
    authService = AuthService(configuration: configuration)
      .withOAuthSignIn(
        OAuthProviderSwift(
          providerId: "oidc.line",  // LINE OIDC provider
          scopes: ["profile", "openid", "email"],  // LINE requires these scopes
          displayName: "Sign in with LINE",
          buttonIcon: Image("line-logo"),
          buttonBackgroundColor: .green,
          buttonForegroundColor: .white
        )
      )
      .withOAuthSignIn(
        OAuthProviderSwift(
          providerId: "oidc.custom-provider",
          scopes: ["profile", "openid"],
          displayName: "Sign in with Custom",
          buttonIcon: Image(systemName: "person.circle"),
          buttonBackgroundColor: .purple,
          buttonForegroundColor: .white
        )
      )
  }

  var body: some View {
    AuthPickerView {
      Text("App Content")
    }
    .environment(authService)
  }
}