Günümüz mobil ve web uygulamalarının temel taşlarından biri, güvenli ve etkili kimlik doğrulama sistemleridir. Kullanıcıların uygulama içindeki verilerine erişebilmesi, bu sistemler sayesinde güvence altına alınır. Firebase Authentication, bu süreci kolaylaştıran güçlü bir araç olarak öne çıkıyor. Peki, Swift ile Firebase Authentication‘ı nasıl kullanabiliriz?
Proje Oluşturmak
Firebase Authentication yöntemlerini tam anlamıyla simüle edebilmek için yandaki SwiftUI projesini hazırladık. Burada kayıt olma, giriş yapma (anonim, Google, email ve şifre), şifre sıfırlama gibi yöntemleri kullanıp ana ekrana geçiş yapmaya çalışacağız. Ana ekranda ise giriş yapmış kullanıcıya ait id bilgisini ekranda yazdırarak Firebase Console üzerinden kontrolünü gerçekleştireceğiz. Ayrıca “Delete Account” butonu ile hesap silmeyi, “Sign Out” butonu ile uygulamadan çıkış yapmayı göreceğiz.
Firebase Projesi Oluşturmak
Yeni bir Firebase projesi oluşturmak oldukça basit. İlk olarak Firebase Console adresine gidip “Create a Project” butonuna basıyoruz.
Burada ilk olarak bizden projeye bir isim vermemiz isteniyor. Kendi istediğiniz bir ismi verip “Continue” diyebilirsiniz.
Son adımda bize proje için Google Analytics‘in kullanılıp kullanılmayacağını soruyor. Biz bir test projesi oluşturduğumuz için devre dışı bıraktık. Fakat siz projeniz için özel analizler almak istiyorsanız kullanmanızı tavsiye ederiz.
Seçiminizi yapıp “Create Project” dedikten sonra projenin hazırlanması için bir süre beklemeliyiz. Proje hazır olduktan sonra artık sıra geldi Firebase projemizi ana projemize entegre etmeye.
Swift Projesi ile Firebase Projesi Entegrasyonu
Bu aşamada aslında bir önceki aşama kadar kolay. Fakat burada yapacağımız işlem sayısı biraz daha fazla. Firebase projesi oluştuktan sonra aşağıdaki ekran ile karşılaşıyoruz. Burada yapmamız gereken ilk işlem “iOS” butonuna tıklamak.
Tam bu noktada Firebase’i Swift projemize bağlamak için gereken 5 adım bulunuyor. İlk olarak uygulamamızı kayıt etmek için Bundle Identifier‘a ihtiyacımız var. Bunun için Xcode üzerinde uygulama hedefine tıklıyor, ardından “Genel” sekmesine gidiyoruz. Aldığımız Bundle Identifier‘ı Firebase’e ekliyoruz. Burada “App Nickname” ve “App Store ID” opsiyonel olarak sunulmuş. Biz iki seçeneği de boş bırakarak uygulamayı kayıt ediyoruz.
Ardından bağlantı için gerekli bilgilerin yer aldığı GoogleService-Info.plist dosyasını resimde gösterildiği gibi uygulama hedefimize ekliyoruz. Burada dikkat etmemiz gereken nokta dosya adını değiştirmemek ve kopyalama sırasında “Copy items if needed” seçeneğinin işaretli olması.
Şimdi sıra Firebase SDK‘ini kurmakta. Swift Package Manager ile kuracağımız bu SDK içerisinde birçok ürün bulunuyor. Biz burada ;
- FirebaseAuth
- FirebaseFirestore
- FirebaseStorage
paketlerini uygulama hedefimize ekleyip kullanacağız. Fakat siz gereksinimlerinize göre eklemeler yapabilirsiniz.
Bir sonraki adımda Firebase’i uygulamada başlatmak için gerekli kodları eklemekte. Uygulamamızı SwiftUI ile oluşturduk. Bu yüzden biz SwiftUI için gereken kodları kullanacağız. Fakat siz UIKit ile oluşturduysanız buna uygun seçenek ile devam etmelisiniz. Ayrıca ekleme bittikten sonra “Command + B” ile Build almak ekleme sırasında bir hata olup olmadığı anlamamıza yardımcı olabilir.
Son adımda ise “Continue to console” butonuna basarak entegrasyonu tamamlayabiliriz.
Firebase Authentication’ı Aktifleştirmek
Projemizi başarıyla Firebase’e bağladıktan sonra şimdi sıra Authentication’ı kullanmakta. Bunun için Firebase Console üzerinden bu özelliği aktifleştirmemiz gerekiyor.
İlk olarak Firebase Console‘un sol panelinde bulunan “Build” sekmesine basıyoruz. Ardından Authentication’ı seçiyoruz. Daha sonra açılan sayfada “Get started” butonuna basarak ilerliyoruz.
Şimdi ise kullanılacak giriş yöntemlerini belirlememiz gerekiyor. Biz uygulamamızda;
- Email/Password
- Anonymous
giriş yöntemlerini kullanacağız. Fakat şu an sadece “Email/Password” ve “Anonymous” yöntemlerini aktifleştiriyoruz. “Google” ile girişe en son bakacağız.
Firebase ile Anonymous Giriş
Öncelikle giriş ekranımız için SignInViewViewModel sınıfını oluşturduk. Ardından Swift Concurrency konusuna uygun bir şekilde async-await ve Task kullanarak anonim giriş fonksiyonunu ekledik. Ayrıca işlemin sürdüğü ve tamamlandığının anlaşılması için signInCompleted ve isProcessing Published değişkenlerini ekledik. Bu sayede işlem devam ederken kullanıcıya ProgressView() işlem tamamlandığında fullScreenCover ile ana ekrana geçiş sağlanmış olacak.
import Foundation
import FirebaseAuth
@MainActor
class SignInViewViewModel : ObservableObject {
@Published var signInCompleted : Bool = false
@Published var isProcessing : Bool = false
func signInAnonymously() {
isProcessing = true
Task {
do {
try await Auth.auth().signInAnonymously()
isProcessing = false
signInCompleted = true
}catch {
isProcessing = false
signInCompleted = false
print("Misafir olarak girişte hata : \(error)")
}
}
}
}
Şimdi bir test yapalım ve giriş yapabiliyor muyuz bir bakalım.
Ana ekrana ulaşmayı başardık. Fakat giriş yapan kullanıcı bilgisini nasıl alacağız? Şimdi gelin ona bakalım.
Giriş Yapan Kullanıcı Bilgisini Almak
Bunun için önce HomeViewViewModel sınıfını oluşturduk. Ardından getCurrentAuthenticatedUser() fonksiyonunun içerisinde Firebase tarafından bize verilen currentUser’ı kullanarak User? değerine erişiyoruz. Ardından HomeView’da onAppear metodunun içerisinde bu fonksiyonu çağırarak ekran açıldığında kullanıcı sorgusu yapıyoruz. Fakat dikkat etmeliyizki bu değer opsiyonel. Yani bu değerin nil olabilme ihtimalini dikkate alarak işlem yapmalıyız. Bu yüzden HomeView’da bu değer nil ise “User Not Found”, değilse kullanıcı kimlik numarası yazacak. Şimdi gelin bir test yapalım.
import Foundation
import FirebaseAuth
@MainActor
class HomeViewViewModel : ObservableObject {
@Published var currentUser : User?
func getCurrentAuthenticatedUser () {
let user = Auth.auth().currentUser
currentUser = user
}
}
Uygulamadan Çıkış Yapmak
Ana ekrana eriştik. Giriş yapan kullanıcı bilgisini de aldık. Fakat kullanıcı uygulamadan çıkış yapmak istediğinde ne yapmamız gerekiyor? Bunun için signOut() metodunu kullanıyoruz. Şimdi gelin bunu HomeViewViewModel sınıfımıza ekleyip test edelim.
import Foundation
import FirebaseAuth
@MainActor
class HomeViewViewModel : ObservableObject {
@Published var currentUser : User?
@Published var isCompleted : Bool = false
@Published var isProcessing : Bool = false
func getCurrentAuthenticatedUser () {
let user = Auth.auth().currentUser
currentUser = user
}
func signOut () {
isProcessing = true
do {
try Auth.auth().signOut()
isProcessing = false
isCompleted = true
}catch {
isProcessing = false
isCompleted = false
print("Kullanıcı çıkış yapamadı : \(error)")
}
}
}
Email ve Şifre ile Kayıt Olmak
Anonim giriş oldukça pratik ve hızlı bir geçiş sunsa da, uygulamadan çıkış yapıldığında tekrar giriş mümkün değil. Çünkü anonim giriş ile yapılan her yeni girişte yeni bir kullanıcı oluşturulur. Eğer kullanıcıya özel veri saklamak istiyorsanız bu giriş yöntemi pek size göre olmayabilir. Bu yüzden günümüz uygulamalarında sıkça gördüğümüz email ve şifre ile kayıt olup giriş yapmayı görelim. Bunun için öncelikle SignUpViewViewModel sınıfımızı oluşturduk. TextField için userEmail, SecureField için ise userPassword Published değişkenlerini oluşturduk. Kullanıcı kaydı için Firebase tarafından sağlanan createUser() metodunu kullandık. Yalnız burada dikkat edilmesi gereken en önemli nokta, kayıt işlemi başarılı olduğunda uygulamaya girişte yapılıyor. Fakat email doğrulaması yapmak istiyorsanız bu durumu engellemek için işlem tamamlandıktan sonra signOut() metodunu kullanmakta fayda var.
import Foundation
import FirebaseAuth
@MainActor
class SignUpViewViewModel : ObservableObject {
@Published var userEmail : String = ""
@Published var userPassword : String = ""
@Published var isCompleted : Bool = false
@Published var isProcessing : Bool = false
func createNewUser() {
isProcessing = true
Task {
do {
try await Auth.auth().createUser(withEmail: userEmail, password: userPassword)
try Auth.auth().signOut()
isProcessing = false
isCompleted = true
}catch {
isProcessing = false
isCompleted = false
print("Kullanıcı kaydı başarısız : \(error)")
}
}
}
}
Şimdi sıra kayıt işlemini test etmekte.
Email ve Şifre ile Giriş Yapmak
Burada da aslında işlem oldukça basit. createUser() metodunda olduğu gibi yine email ve şifre alan signIn() metodunu kullanarak giriş yapabiliyoruz. Burada bize verilen giriş sonucundan giriş yapan kullanıcının email adresini doğrulayıp doğrulamadığını öğrenebiliyoruz. Eğer doğrulamamışsa sendEmailVerification() ile mail adresine doğrulama maili gönderilebilir. Tabi bunu yapmadan önce signOut() ile çıkış yapmayı unutmamalıyız.
import Foundation
import FirebaseAuth
@MainActor
class SignInViewViewModel : ObservableObject {
@Published var userEmail : String = ""
@Published var userPassword : String = ""
@Published var emailVerifyingErrorOccurred : Bool = false
@Published var signInCompleted : Bool = false
@Published var isProcessing : Bool = false
func signInAnonymously() {
isProcessing = true
Task {
do {
try await Auth.auth().signInAnonymously()
isProcessing = false
signInCompleted = true
}catch {
isProcessing = false
signInCompleted = false
print("Misafir olarak girişte hata : \(error)")
}
}
}
func signInWithEmailAndPassword () {
isProcessing = true
Task {
do {
let authResult = try await Auth.auth().signIn(withEmail: userEmail, password: userPassword)
isProcessing = false
if !authResult.user.isEmailVerified {
try Auth.auth().signOut()
try await authResult.user.sendEmailVerification()
signInCompleted = false
emailVerifyingErrorOccurred = true
}else {
signInCompleted = true
}
}catch {
isProcessing = false
signInCompleted = false
print("Email ve şifre ile girişte hata : \(error)")
}
}
}
}
Kullanıcı email adresini doğrulatarak giriş sağladık. Peki kullanıcımız şifresini unutursa? Şimdi gelin şifre nasıl sıfırlanır ona bakalım.
Şifre Sıfırlamak
Burada şifresinin sıfırlanmasını istediğimiz email adresini sendPasswordReset() metoduna vererek mail gönderilmesini sağlayabiliyoruz.
import Foundation
import FirebaseAuth
@MainActor
class SignInViewViewModel : ObservableObject {
@Published var userEmail : String = ""
@Published var userPassword : String = ""
@Published var emailVerifyingErrorOccurred : Bool = false
@Published var signInCompleted : Bool = false
@Published var isProcessing : Bool = false
func signInAnonymously() {
isProcessing = true
Task {
do {
try await Auth.auth().signInAnonymously()
isProcessing = false
signInCompleted = true
}catch {
isProcessing = false
signInCompleted = false
print("Misafir olarak girişte hata : \(error)")
}
}
}
func signInWithEmailAndPassword () {
isProcessing = true
Task {
do {
let authResult = try await Auth.auth().signIn(withEmail: userEmail, password: userPassword)
isProcessing = false
if !authResult.user.isEmailVerified {
try Auth.auth().signOut()
try await authResult.user.sendEmailVerification()
signInCompleted = false
emailVerifyingErrorOccurred = true
}else {
signInCompleted = true
}
}catch {
isProcessing = false
signInCompleted = false
print("Email ve şifre ile girişte hata : \(error)")
}
}
}
func sendResetPasswordEmail() {
isProcessing = true
Task {
do {
try await Auth.auth().sendPasswordReset(withEmail: userEmail)
isProcessing = false
}catch {
isProcessing = false
print("Şifre sıfırlama maili gönderilemedi : \(error)")
}
}
}
}
Şifremizi sıfırlayıp başarıyla tekrar giriş yapabildik. Fakat çoğu kullanıcı email adresi doğrulama, şifre sıfırlama gibi durumlarla karşılaşmamak için genelde diğer sağlayıcılar ile giriş yaparlar. Şimdi gelin bunlardan en önemlisi, yani Google ile nasıl giriş yapabileceğimizi görelim.
Google ile Giriş SDK’ini Yüklemek
Google ile giriş kurulumu için öncelikle aşağıdaki adreste bulunan GoogleSignIn-iOS SDK‘ini yüklemeliyiz.
https://github.com/google/GoogleSignIn-iOS
Aslında Firebase SDK‘ini yüklerken izlediğimiz yolu tekrar izleyeceğiz.
Google ile Girişi Aktifleştirmek
Google ile girişi aktifleştirmek için aslında bir önceki yöntemlerde izlediğimiz yolu izleyeceğiz. Fakat buradaki tek fark bu giriş yöntemi ile oluşan yeni GoogleService-Info.plist dosyasını yeniden projeye kopyalamak. Gelin bunu nasıl yapacağımıza yakından bakalım.
Yeni Bir URL Scheme Eklemek
Google ile girişin 3.adımı ise yeni bir URL Scheme eklemek olacak. Bunun için önce proje dosyamıza tıklıyoruz. Ardından “Targets” altında projemizin seçili olduğunu gördükten sonra “Info” menüsüne gidiyoruz. Bu menünün altında yer alan “URL Types” menüsünü açıp “+” işaretine basıyoruz. Ardından “URL Scheme” alanına Firebase’den indirip projemize kopyaladığımız GoogleService-Info.plist dosyasının içerisinde bulunan “REVERSED_CLIENT_ID” kodunu buraya kopyalıyoruz. Sonrasında işlem tamam!
Info.plist Dosyasına GIDClientID Eklemek
Yeni bir “URLScheme” oluşturduktan sonra kurulum aşamasında artık sona geldik. Bu adımda ise GoogleService-Info.plist dosyamızda bulunan “CLIENT_ID” kodunu “Info.plist” içerisinde oluşturacağımız “GIDClientID” anahtarına vermek. Şimdi nasıl yapılacağına yakından bakalım.
Google ile Giriş Yapmak
Uzunca bir kurulumun ardından gelelim giriş için gerekli kodlara. Google ile giriş butonuna basıldığında giriş sayfasının açılabilmesi için öncelikle kök görünümü buluyoruz. Ardından Google tarafından sağlanan signIn() metodunu kullanarak giriş sonucunu alıyoruz. Bu sonuçla dönen “user” parametresinden bir “id token” ve “accessToken” oluşturup credential() metoduna veriyoruz. Ardından oluşan credential’ı Firebase tarafından verilen signIn() metodu ile kullanarak girişi tamamlıyoruz. Şimdi uygulamalı olarak görelim.
import Foundation
import FirebaseAuth
import GoogleSignIn
import GoogleSignInSwift
@MainActor
class SignInViewViewModel : ObservableObject {
@Published var userEmail : String = ""
@Published var userPassword : String = ""
@Published var emailVerifyingErrorOccurred : Bool = false
@Published var signInCompleted : Bool = false
@Published var isProcessing : Bool = false
func signInAnonymously() {
isProcessing = true
Task {
do {
try await Auth.auth().signInAnonymously()
isProcessing = false
signInCompleted = true
}catch {
isProcessing = false
signInCompleted = false
print("Misafir olarak girişte hata : \(error)")
}
}
}
func signInWithEmailAndPassword () {
isProcessing = true
Task {
do {
let authResult = try await Auth.auth().signIn(withEmail: userEmail, password: userPassword)
isProcessing = false
if !authResult.user.isEmailVerified {
try Auth.auth().signOut()
try await authResult.user.sendEmailVerification()
signInCompleted = false
emailVerifyingErrorOccurred = true
}else {
signInCompleted = true
}
}catch {
isProcessing = false
signInCompleted = false
print("Email ve şifre ile girişte hata : \(error)")
}
}
}
func sendResetPasswordEmail() {
isProcessing = true
Task {
do {
try await Auth.auth().sendPasswordReset(withEmail: userEmail)
isProcessing = false
}catch {
isProcessing = false
print("Şifre sıfırlama maili gönderilemedi : \(error)")
}
}
}
func signInWithGoogle() {
isProcessing = true
Task {
do {
guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let root = windowScene.windows.first?.rootViewController else {
print("Google kimlik doğrulama sırasında kök görünüm bulunamadı.")
return
}
let authResult = try await GIDSignIn.sharedInstance.signIn(withPresenting: root)
let user = authResult.user
guard let idToken = user.idToken?.tokenString else {
print("Google kimlik doğrulama id token alınamadı.")
return
}
let accessToken = user.accessToken.tokenString
let credential = GoogleAuthProvider.credential(withIDToken: idToken, accessToken: accessToken)
try await Auth.auth().signIn(with: credential)
isProcessing = false
signInCompleted = true
}catch {
isProcessing = false
signInCompleted = false
print("Google ile giriş sağlanamadı : \(error)")
}
}
}
}
Kullanıcı Hesabını Silmek
Örnek projemizde sık kullanılan birkaç giriş yöntemini inceledik. Peki kullanıcı hesabını silmek isterse? Bunun için öncelikle giriş yapmış kullanıcı bilgisini almamız gerekiyor. Aldıktan sonra delete() metodunu çalıştırmamız yeterli olacak.
import Foundation
import FirebaseAuth
@MainActor
class HomeViewViewModel : ObservableObject {
@Published var currentUser : User?
@Published var isCompleted : Bool = false
@Published var isProcessing : Bool = false
func getCurrentAuthenticatedUser () {
let user = Auth.auth().currentUser
currentUser = user
}
func signOut () {
isProcessing = true
do {
try Auth.auth().signOut()
isProcessing = false
isCompleted = true
}catch {
isProcessing = false
isCompleted = false
print("Kullanıcı çıkış yapamadı : \(error)")
}
}
func deleteUserAccount () {
isProcessing = true
Task {
do {
guard let user = currentUser else {return}
try await user.delete()
isProcessing = false
isCompleted = true
}catch {
isProcessing = false
isCompleted = false
print("Kullanıcı hesabı silme başarısız oldu : \(error)")
}
}
}
}
Sonuç olarak, Firebase Authentication, Swift projelerinde kimlik doğrulama işlemlerini hızlı ve güvenli bir şekilde entegre etmek için güçlü bir çözüm sunar. İster anonim giriş, ister e-posta ve şifre ile giriş, ister Google gibi üçüncü parti kimlik sağlayıcıları kullanın, Firebase sayesinde kullanıcı doğrulama süreçlerini kolayca yönetebilirsiniz. Bu yazıda ele aldığımız yöntemlerle uygulamanızın kullanıcı deneyimini bir üst seviyeye taşıyabilir ve güvenlik açısından sağlam bir temel oluşturabilirsiniz.