Published on

Firebase authentication: apple orqali tizimga kirish (sign in with apple)

Authors

Nega "Sign in with Apple" majburiy?

Apple'ning qat'iy qoidalariga ko'ra, agar sizning iOS ilovangizda uchinchi tomon avtorizatsiya usullari (masalan, Google bilan kirish, Facebook bilan kirish yoki hatto oddiy Email/Parol bilan kirish) mavjud bo'lsa, siz Sign in with Apple usulini qo'shishga majbursiz. Agar qo'shmasangiz, ilovangiz App Store'ga qabul qilinmaydi va rad etiladi (reject). Ammo buning yaxshi tarafi shundaki, iPhone foydalanuvchilarining qariyb 99.9% ida iCloud akkaunti bor va ular bir marta bosish (va FaceID) orqali juda oson ro'yxatdan o'ta oladilar.

Eslatma: "Sign in with Apple"ni to'liq ishlatish uchun sizda Pullik Apple Developer Account ($99/yil) bo'lishi kerak. Aks holda bu kodlarni yozganingiz bilan oxirida xatolik yuz beradi.

1-qadam: Sozlamalar (Firebase va Xcode)

Firebase:

  1. Firebase Konsolidan Authentication bo'limiga o'ting.
  2. Add new provider tugmasi orqali Apple ni yoqing va saqlang.

Xcode:

  1. Xcode'da loyiha fayliga bosing va Target -> Signing & Capabilities bo'limiga o'ting.
  2. Yuqori chap burchakdagi + Capability tugmasini bosing va qidiruvga "Apple" deb yozing.
  3. Sign In with Apple imkoniyatini loyihaga qo'shing. (Bu sizning Apple Developer hisobingiz bilan bog'langan bo'lishi shart, aks holda bu capability ro'yxatda chiqmaydi).

2-qadam: Apple tugmasining dizayn qoidalari

Apple Sign-In tugmasini xohlagan rang yoki shaklda yasashga ruxsat bermaydi. Uning dizayni, yozuvi va logotipi aniq standartlarga mos kelishi kerak. Xususan:

  • Qora fonga oq yozuv va oq olma, yoki Oq fonga qora yozuv va qora olma bo'lishi mumkin.
  • Boshqacha rang (masalan, qizil, ko'k) ishlatish taqiqlanadi.

Afsuski, Firebase va SwiftUI bilan to'g'ridan-to'g'ri integratsiya qilinadigan tayyor "Sign in with Apple" tugmasi yo'q. Shuning uchun biz UIKit'dagi rasmiy ASAuthorizationAppleIDButton tugmasini SwiftUI'ga o'girib ishlatamiz:

import SwiftUI
import AuthenticationServices

struct SignInWithAppleButtonViewRepresentable: UIViewRepresentable {
    let type: ASAuthorizationAppleIDButton.ButtonType
    let style: ASAuthorizationAppleIDButton.Style

    func makeUIView(context: Context) -> ASAuthorizationAppleIDButton {
        return ASAuthorizationAppleIDButton(type: type, style: style)
    }

    func updateUIView(_ uiView: ASAuthorizationAppleIDButton, context: Context) {}
}

View'da undan foydalanish:

SignInWithAppleButtonViewRepresentable(type: .signIn, style: .black)
    .allowsHitTesting(false) // Ichki bosilishlarni o'chirib qo'yamiz
    .overlay {
        // Ustidan oddiy shaffof SwiftUI tugmasini qo'yamiz
        Button {
            Task {
                do {
                    try await viewModel.signInApple()
                } catch {
                    print(error)
                }
            }
        } label: {
            Color.clear
        }
    }
    .frame(height: 55)

3-qadam: Kriptografiya va Nonce yaratish

Google'dan farqli o'laroq, Apple avtorizatsiyasi CryptoKit yordamida maxsus xavfsizlik kalitlarini (Nonce) talab qiladi. Buni bajarish uchun alohida SignInAppleHelper klassini yaratamiz.

Ushbu klass juda katta bo'lib, o'z ichida:

  1. Tasodifiy 32 belgili Nonce yaratish.
  2. Uning SHA256 xeshini (hash) hisoblash.
  3. ASAuthorizationController orqali Apple'ning rasmiy oynasini ochishni o'z ichiga oladi.

TIP

Bu murakkab kriptografik kodlarni boshidan yozib o'tirmaslik uchun, men uni tayyor GitHub Gist sahifamga yuklab qo'yganman. Siz shunchaki o'sha yerdagi kodni nusxalab loyihangizga qo'shib qo'ysangiz bo'ladi.

4-qadam: Delegate va Firebase'ga bog'lash

Foydalanuvchi FaceID orqali tasdiqlangach, Apple bizga idToken va uning ma'lumotlarini (Ismi va Email) qaytaradi. Lekin Apple'ning SDK'si async/await o'rniga eskicha Delegate usulida ishlaydi. Bu muammoni chetlab o'tish uchun biz Swift'ning ajoyib imkoniyati — withCheckedThrowingContinuation dan foydalanamiz. Bu eski completion handler'larni zamonaviy async/await ga aylantirib beradi.

Qaytgan javobni qabul qilgach, xuddi Google'dagi kabi Firebase'ga kiritamiz:

// AuthenticationManager.swift ichida
func signInWithApple(tokens: SignInWithAppleResult) async throws -> AuthDataResultModel {
    // 1. Apple javobidan Firebase tushunadigan Credential yasaymiz
    let credential = OAuthProvider.credential(
        withProviderID: "apple.com",
        idToken: tokens.token,
        rawNonce: tokens.nonce
    )

    // 2. Firebase tizimiga kiritamiz
    let authDataResult = try await Auth.auth().signIn(with: credential)
    return AuthDataResultModel(user: authDataResult.user)
}

Eslatma: Sign In with Apple orqali foydalanuvchining ismi va emaili faqatgina birinchi marta ro'yxatdan o'tayotgan paytdagina beriladi. Agar dasturingizda ularni ma'lumotlar bazasida (Firestore) saqlamoqchi bo'lsangiz, albatta birinchi ro'yxatdan o'tgan zahotiyoq ushlab qolib, bazaga yozib qo'yish kerak bo'ladi.

Xulosa

Sign in with Apple boshqa barcha provayderlarga qaraganda eng ko'p qoidalar va uzoq kod yozishni talab qiladi (kriptografiya, UI qat'iy qoidalari, delegate'lar, Apple Developer account). Lekin bir marta SignInAppleHelper ni to'g'ri yozib olsangiz, qolgan hamma loyihalaringizda shu kodni tayyor shablon sifatida ishlataverasiz!

Keyingi darsda biz eng qiziq va qulay usul — Anonymous Authentication (Yashirincha / Hisobsiz kirish) imkoniyatini ko'rib chiqamiz. Bu foydalanuvchini hech qanday ma'lumot so'ramasdan darhol ilovaga kiritish uchun ishlatiladi.

Buy mea coffee