افزودن ورود با گوگل به اپلیکیشن iOS

۱. قبل از شروع

این آزمایشگاه کد شما را در ساخت یک برنامه iOS که ورود با گوگل را پیاده‌سازی می‌کند و در یک شبیه‌ساز اجرا می‌شود، راهنمایی می‌کند. پیاده‌سازی‌ها با استفاده از SwiftUI و UIKit ارائه شده‌اند.

SwiftUI چارچوب رابط کاربری مدرن اپل برای توسعه برنامه‌های جدید است. این چارچوب امکان ساخت رابط‌های کاربری برای همه پلتفرم‌های اپل را از یک کدبیس مشترک فراهم می‌کند. این چارچوب به حداقل نسخه iOS 13 نیاز دارد.

UIKit چارچوب رابط کاربری اصلی و بنیادی اپل برای iOS است. این چارچوب با نسخه‌های قدیمی‌تر iOS سازگاری دارد. این امر آن را به انتخابی خوب برای برنامه‌های جاافتاده‌ای تبدیل می‌کند که نیاز به پشتیبانی از انواع دستگاه‌های قدیمی‌تر دارند.

شما می‌توانید مسیر چارچوبی را دنبال کنید که به بهترین وجه با نیازهای توسعه شما همسو باشد.

پیش‌نیازها

آنچه یاد خواهید گرفت

  • نحوه ایجاد یک پروژه گوگل کلود
  • نحوه ایجاد کلاینت‌های OAuth در کنسول ابری گوگل
  • نحوه پیاده‌سازی ورود با گوگل برای برنامه iOS شما
  • نحوه شخصی‌سازی دکمه ورود با گوگل
  • نحوه رمزگشایی یک توکن شناسایی
  • نحوه فعال کردن App Check برای برنامه iOS شما

آنچه نیاز دارید

  • نسخه فعلی Xcode
  • رایانه‌ای که سیستم عامل macOS را اجرا می‌کند و الزامات سیستم را برای نسخه Xcode که نصب کرده‌اید، برآورده می‌کند.

این آزمایشگاه کد با استفاده از Xcode 16.3 و شبیه‌ساز iOS 18.3 ایجاد شده است. برای توسعه باید از آخرین نسخه Xcode استفاده کنید.

۲. یک پروژه جدید Xcode ایجاد کنید

  1. Xcode را باز کنید و گزینه Create a new Xcode project را انتخاب کنید.
  2. تب iOS را انتخاب کنید، قالب برنامه را انتخاب کنید و روی Next کلیک کنید.

صفحه الگوی نسخه برداری پروژه Xcode

  1. در گزینه‌های پروژه:
    • نام محصول خود را وارد کنید.
    • در صورت تمایل تیم خود را انتخاب کنید.
    • شناسه سازمان خود را وارد کنید.
    • شناسه بسته تولید شده را یادداشت کنید. بعداً به آن نیاز خواهید داشت.
    • برای رابط کاربری ، یکی از موارد زیر را انتخاب کنید:
      • SwiftUI برای یک برنامه مبتنی بر SwiftUI.
      • استوری‌بورد برای یک برنامه مبتنی بر UIKit.
    • برای زبان، Swift را انتخاب کنید.
    • روی Next کلیک کنید و مکانی را برای ذخیره پروژه خود انتخاب کنید.

صفحه گزینه‌های پروژه Xcode

۳. یک کلاینت OAuth ایجاد کنید

برای اینکه برنامه شما بتواند با سرویس‌های احراز هویت گوگل ارتباط برقرار کند، باید یک شناسه کلاینت OAuth ایجاد کنید. این کار به یک پروژه Google Cloud نیاز دارد. مراحل زیر شما را در فرآیند ایجاد یک پروژه و یک شناسه کلاینت OAuth راهنمایی می‌کند.

یک پروژه Google Cloud انتخاب یا ایجاد کنید

  1. به کنسول گوگل کلود بروید و یک پروژه را انتخاب یا ایجاد کنید. اگر یک پروژه از قبل موجود را انتخاب می‌کنید، کنسول به طور خودکار شما را به مرحله بعدی مورد نیاز هدایت می‌کند.

صفحه انتخاب پروژه کنسول ابری گوگل

  1. نامی برای پروژه جدید Google Cloud خود وارد کنید.
  2. ایجاد را انتخاب کنید.

صفحه انتخاب پروژه کنسول ابری گوگل

اگر قبلاً صفحه رضایت‌نامه را برای پروژه انتخاب‌شده پیکربندی کرده‌اید، اکنون از شما خواسته نمی‌شود که آن را پیکربندی کنید. در این صورت، می‌توانید از این بخش صرف‌نظر کنید و به بخش ایجاد یک کلاینت OAuth 2.0 بروید.

  1. صفحه پیکربندی رضایت را انتخاب کنید.

کنسول ابری گوگل، صفحه کلاینت OAuth را با پیکربندی صفحه رضایت‌نامه ایجاد می‌کند.

  1. در صفحه برندسازی، گزینه شروع به کار (Get Started) را انتخاب کنید.

صفحه شروع به کار با برند کنسول ابری گوگل

  1. در صفحه پیکربندی پروژه، فیلدهای زیر را پر کنید:
    • اطلاعات برنامه : یک نام و یک ایمیل پشتیبانی کاربر برای برنامه خود وارد کنید. این ایمیل پشتیبانی به صورت عمومی نمایش داده می‌شود تا کاربران بتوانند در مورد رضایت خود با شما تماس بگیرند.
    • مخاطب : خارجی را انتخاب کنید.
    • اطلاعات تماس : یک آدرس ایمیل وارد کنید تا گوگل بتواند در مورد پروژه شما با شما تماس بگیرد.
    • سیاست‌های مربوط به داده‌های کاربر در سرویس‌های API گوگل را مرور کنید.
    • روی ایجاد کلیک کنید.

صفحه پیکربندی برندسازی کلاینت کنسول ابری گوگل

  1. صفحه مشتریان را در منوی ناوبری انتخاب کنید.
  2. روی ایجاد کلاینت کلیک کنید.

صفحه مشتریان پروژه Google CLoud

یک کلاینت OAuth 2.0 ایجاد کنید

  1. برای نوع برنامه، iOS را انتخاب کنید.
  2. یک نام برای کلاینت خود وارد کنید.
  3. شناسه بسته ایجاد شده در مرحله قبل را وارد کنید.
  4. شناسه تیم اختصاص داده شده به تیم شما توسط اپل را وارد کنید. این مرحله فعلاً اختیاری است، اما برای فعال کردن App Check در ادامه این codelab، شناسه تیم لازم است.
  5. ایجاد را انتخاب کنید.

صفحه ورود اطلاعات کلاینت OAuth

  1. شناسه کلاینت را از پنجره محاوره‌ای کپی کنید، بعداً به آن نیاز خواهید داشت.
  2. فایل plist را دانلود کنید تا بعداً به آن مراجعه کنید.

پنجره ایجاد شناسه کلاینت OAuth

۴. پروژه Xcode خود را پیکربندی کنید

مرحله بعدی، تنظیم پروژه Xcode شما برای کار با ابزار ورود با Google SDK است. این فرآیند شامل اضافه کردن SDK به پروژه شما به عنوان یک وابستگی و پیکربندی تنظیمات پروژه با یک شناسه کلاینت منحصر به فرد است. این شناسه به SDK اجازه می‌دهد تا در طول فرآیند ورود به سیستم، به طور ایمن با سرویس احراز هویت گوگل ارتباط برقرار کند.

وابستگی‌های ورود با گوگل را نصب کنید

  1. پروژه Xcode خود را باز کنید.
  2. به مسیر File > Add Package Dependencies بروید.
  3. در نوار جستجو، آدرس URL مخزن ورود با گوگل را وارد کنید: https://github.com/google/GoogleSignIn-iOS

وابستگی ورود با گوگل را در Swift Package Manager پیدا کنید

  1. افزودن بسته را انتخاب کنید.
  2. هدف اصلی برنامه را برای بسته GoogleSignIn انتخاب کنید.
  3. اگر از SwiftUI استفاده می‌کنید، هدف اصلی برنامه را برای بسته GoogleSignInSwift انتخاب کنید. اگر قصد استفاده از UIKit را دارید، هدفی برای این بسته انتخاب نکنید.
  4. افزودن بسته را انتخاب کنید.

وابستگی ورود با گوگل را به پروژه خود اضافه کنید

اعتبارنامه‌های برنامه خود را پیکربندی کنید

  1. در پنجره‌ی ناوبری پروژه، روی ریشه‌ی پروژه‌ی خود کلیک کنید.
  2. در قسمت ویرایشگر اصلی، هدف اصلی برنامه خود را از لیست TARGETS انتخاب کنید.
  3. برگه اطلاعات را در بالای قسمت ویرایشگر انتخاب کنید.
  4. ماوس را روی آخرین ردیف در بخش «ویژگی‌های سفارشی هدف iOS» نگه دارید و روی دکمه‌ی + که ظاهر می‌شود کلیک کنید.

یک کلید هدف جدید به ویژگی‌های هدف iOS اضافه کنید

  1. در ستون Key ، عبارت GIDClientID را تایپ کنید.
  2. در ستون Value ، شناسه کلاینتی که از کنسول گوگل کلود کپی کرده‌اید را جایگذاری کنید.

GIDClientID را به هدف اصلی برنامه اضافه کنید

  1. فایل plist که از کنسول ابری گوگل دانلود کرده‌اید را باز کنید.
  2. مقدار Reversed Client ID را کپی کنید.

فایل لیست کنسول ابری گوگل

  1. انواع URL را در پایین برگه اطلاعات باز کنید.
  2. دکمه + را انتخاب کنید.
  3. شناسه کلاینت معکوس شده را در کادر طرح‌های URL وارد کنید.

کلید URLSchemes را به هدف اصلی برنامه اضافه کنید

حالا آماده‌ایم تا دکمه ورود به برنامه‌مان را اضافه کنیم!

۵. دکمه ورود را اضافه کنید

با پیکربندی پروژه Xcode، وقت آن رسیده است که دکمه ورود با گوگل را به برنامه اضافه کنیم!

منطق اصلی این مرحله فراخوانی GIDSignIn.sharedInstance.signIn است. این متد فرآیند احراز هویت را آغاز می‌کند و کنترل را به Sign in with Google SDK می‌دهد تا جریان Sign in with Google را به کاربر ارائه دهد.

سویفت‌یو‌آی

  1. فایل ContentView.swift را در Xcode Project Navigator پیدا کنید.
  2. محتوای این فایل را با متن زیر جایگزین کنید:
import GoogleSignIn
import GoogleSignInSwift
import SwiftUI

struct ContentView: View {
  var body: some View {
    VStack {
      GoogleSignInButton(action: handleSignInButton).padding()
    }
  }

  func handleSignInButton() {
    // Find the current window scene.
    guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene else {
      print("There is no active window scene")
      return
    }

    // Get the root view controller from the window scene.
    guard
      let rootViewController = windowScene.windows.first(where: { $0.isKeyWindow })?
        .rootViewController
    else {
      print("There is no key window or root view controller")
      return
    }

    // Start the sign-in process.
    GIDSignIn.sharedInstance.signIn(
      withPresenting: rootViewController
    ) { signInResult, error in
      guard let result = signInResult else {
        // Inspect error
        print("Error signing in: \(error?.localizedDescription ?? "No error description")")
        return
      }
      // If sign in succeeded, display the app's main content View.
      print("ID Token: \(result.user.idToken?.tokenString ?? "")")
    }
  }
}

#Preview {
  ContentView()
}

دکمه ورود با گوگل در فریم‌ورک SwiftUI در شبیه‌ساز iOS

رابط کاربری

  1. فایل ViewController.swift را در Xcode Project Navigator پیدا کنید.
  2. محتوای این فایل را با متن زیر جایگزین کنید:
import GoogleSignIn
import UIKit

class ViewController: UIViewController {

  // Create an instance of the Sign in with Google button
  let signInButton = GIDSignInButton()

  override func viewDidLoad() {
    super.viewDidLoad()

    // Add the sign-in button to your view
    view.addSubview(signInButton)

    // Position the button using constraints
    signInButton.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
      signInButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
      signInButton.centerYAnchor.constraint(equalTo: view.centerYAnchor),
    ])

    // Add a target to the button to call a method when it's pressed
    signInButton.addTarget(self, action: #selector(signInButtonTapped), for: .touchUpInside)
  }

  // This method is called when the sign-in button is pressed.
  @objc func signInButtonTapped() {
    // Start the sign-in process.
    GIDSignIn.sharedInstance.signIn(withPresenting: self) { signInResult, error in
      guard let result = signInResult else {
        // Inspect error
        print("Error signing in: \(error?.localizedDescription ?? "No error description")")
        return
      }

      // If sign in succeeded, print the ID token.
      print("ID Token: \(result.user.idToken?.tokenString ?? "")")
    }
  }
}

دکمه ورود با گوگل در فریم‌ورک UIKit در شبیه‌ساز iOS

دکمه ورود را مشاهده کنید

برنامه خود را در شبیه‌ساز اجرا کنید. دکمه ورود با گوگل را خواهید دید، اما هنوز به درستی کار نمی‌کند. این مورد قابل پیش‌بینی است، زیرا هنوز باید کدی را پیاده‌سازی کنید که پس از احراز هویت کاربر، ریدایرکت مجدد به برنامه شما را مدیریت کند.

۶. دکمه ورود را سفارشی کنید

شما می‌توانید دکمه پیش‌فرض ورود با گوگل را برای تطبیق بهتر با قالب برنامه خود سفارشی کنید. کیت توسعه نرم‌افزاری ورود با گوگل به شما امکان می‌دهد طرح رنگ و سبک دکمه را تغییر دهید.

سویفت‌یو‌آی

دکمه پیش‌فرض با این خط کد به صفحه اضافه می‌شود:

GoogleSignInButton(action: handleSignInButton)

دکمه GoogleSignInButton با ارسال پارامترها به مقداردهنده اولیه‌اش سفارشی‌سازی می‌شود. کد زیر باعث می‌شود دکمه ورود در حالت تاریک نمایش داده شود.

  1. فایل ContentView.swift را باز کنید.
  2. مقداردهی اولیه‌ی GoogleSignInButton را به‌روزرسانی کنید تا شامل مقادیر زیر باشد:
GoogleSignInButton(
  scheme: .dark,  // Options: .light, .dark, .auto
  style: .standard,  // Options: .standard, .wide, .icon
  state: .normal,  // Options: .normal, .disabled
  action: handleSignInButton
).padding()

حالت تاریک چارچوب SwiftUI دکمه ورود با گوگل در شبیه‌ساز iOS

برای اطلاعات بیشتر در مورد گزینه‌های سفارشی‌سازی، به مرجع چارچوب GoogleSignInSwift مراجعه کنید.

رابط کاربری

دکمه پیش‌فرض با این خطوط کد ایجاد می‌شود:

// Create an instance of the Sign in with Google button
let signInButton = GIDSignInButton()

// Add the button to your view
view.addSubview(signInButton)

دکمه‌ی GIDSignInButton با تنظیم ویژگی‌های نمونه‌ی دکمه، سفارشی‌سازی می‌شود. کد زیر باعث می‌شود دکمه‌ی ورود به سیستم در حالت تاریک نمایش داده شود.

  1. فایل ViewController.swift را باز کنید.
  2. خطوط کد زیر را بلافاصله قبل از اضافه کردن دکمه ورود به view در تابع viewDidLoad اضافه کنید:
// Set the width and color of the sign-in button
signInButton.style = .standard  // Options: .standard, .wide, .iconOnly
signInButton.colorScheme = .dark  // Options: .dark, .light

حالت تاریک چارچوب UIKit دکمه ورود با گوگل در شبیه‌ساز iOS

برای اطلاعات بیشتر در مورد سفارشی‌سازی، به مرجع چارچوب GoogleSignIn مراجعه کنید.

۷. مدیریت URL تغییر مسیر احراز هویت

با اضافه شدن دکمه ورود، مرحله بعدی مدیریت تغییر مسیری است که پس از احراز هویت کاربر رخ می‌دهد. پس از احراز هویت، گوگل یک URL با کد مجوز موقت برمی‌گرداند. برای تکمیل فرآیند ورود، یک کنترل‌کننده این URL را رهگیری کرده و آن را به Sign in with Google SDK ارسال می‌کند تا با یک توکن شناسه امضا شده (JWT) مبادله شود.

سویفت‌یو‌آی

  1. فایلی که شامل App struct شماست را باز کنید. این فایل بر اساس پروژه شما نامگذاری شده است، بنابراین نام آن چیزی شبیه به YourProjectNameApp.swift خواهد بود.
  2. محتوای این فایل را با متن زیر جایگزین کنید:
import GoogleSignIn
import SwiftUI

@main
struct iOS_Sign_in_with_Google_App: App {
  var body: some Scene {
    WindowGroup {
      ContentView()

        .onOpenURL { url in
          GIDSignIn.sharedInstance.handle(url)
        }
    }
  }
}

رابط کاربری

  1. فایل AppDelegate.swift را باز کنید.
  2. دستور import زیر را به بالای فایل اضافه کنید:
import GoogleSignIn
  1. تابع مدیریت احراز هویت زیر را درون کلاس AppDelegate اضافه کنید. یک جای مناسب برای قرار دادن آن، مستقیماً بعد از آکولاد بسته‌ی متد application(_:didFinishLaunchingWithOptions:) است:
func application(
  _ app: UIApplication,
  open url: URL,
  options: [UIApplication.OpenURLOptionsKey: Any] = [:]
) -> Bool {
  var handled: Bool

  handled = GIDSignIn.sharedInstance.handle(url)
  if handled {
    return true
  }
  // If not handled by this app, return false.
  return false
}

پس از اعمال این تغییرات، فایل AppDelegate.swift شما باید به شکل زیر باشد:

import GoogleSignIn
import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

  func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    // Override point for customization after application launch.
    return true
  }

  func application(
    _ app: UIApplication,
    open url: URL,
    options: [UIApplication.OpenURLOptionsKey: Any] = [:]
  ) -> Bool {
    var handled: Bool

    handled = GIDSignIn.sharedInstance.handle(url)
    if handled {
      return true
    }
    // If not handled by this app, return false.
    return false
  }

  // MARK: UISceneSession Lifecycle

  func application(
    _ application: UIApplication,
    configurationForConnecting connectingSceneSession: UISceneSession,
    options: UIScene.ConnectionOptions
  ) -> UISceneConfiguration {
    // Called when a new scene session is being created.
    // Use this method to select a configuration to create the new scene with.
    return UISceneConfiguration(
      name: "Default Configuration",
      sessionRole: connectingSceneSession.role
    )
  }

  func application(
    _ application: UIApplication,
    didDiscardSceneSessions sceneSessions: Set<UISceneSession>
  ) {
    // Called when the user discards a scene session.
    // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
    // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
  }
}

جریان ورود به سیستم را آزمایش کنید

اکنون می‌توانید کل جریان ورود به سیستم را آزمایش کنید!

برنامه خود را اجرا کنید و روی دکمه ورود به سیستم ضربه بزنید. پس از تأیید اعتبار، گوگل یک صفحه رضایت‌نامه ارائه می‌دهد که در آن می‌توانید به برنامه اجازه دسترسی به اطلاعات خود را بدهید. پس از تأیید، ورود به سیستم نهایی می‌شود و به برنامه بازگردانده می‌شوید.

وقتی فرآیند ورود به سیستم با موفقیت انجام شود، «ورود با Google SDK» به طور ایمن اطلاعات کاربری کاربر را در Keychain دستگاه ذخیره می‌کند. این اطلاعات کاربری می‌توانند بعداً برای فعال ماندن کاربر در هنگام اجرای برنامه‌های بعدی استفاده شوند.

۸. دکمه خروج را اضافه کنید

حالا که ورود به سیستم کار می‌کند، مرحله بعدی اضافه کردن یک دکمه خروج و به‌روزرسانی رابط کاربری برای نمایش وضعیت ورود فعلی کاربر است. وقتی ورود موفقیت‌آمیز باشد، SDK یک شیء GIDGoogleUser ارائه می‌دهد. این شیء شامل یک ویژگی profile با اطلاعات اولیه مانند نام و ایمیل کاربر است که برای شخصی‌سازی رابط کاربری از آن استفاده خواهید کرد.

سویفت‌یو‌آی

  1. فایل ContentView.swift خود را باز کنید.
  2. یک متغیر state در بالای ساختار ContentView خود اضافه کنید. این متغیر اطلاعات کاربر را پس از ورود به سیستم نگه می‌دارد. از آنجایی که این یک متغیر @State است، SwiftUI به طور خودکار رابط کاربری شما را هر زمان که مقدار آن تغییر کند، به‌روزرسانی می‌کند:
struct ContentView: View {
  @State private var user: GIDGoogleUser?
}
  1. body فعلی ساختار ContentView خود را با VStack زیر جایگزین کنید. این بررسی می‌کند که آیا متغیر وضعیت user شامل یک کاربر است یا خیر. اگر چنین باشد، یک پیام خوشامدگویی و یک دکمه خروج نمایش داده می‌شود. اگر چنین نباشد، دکمه ورود با گوگل اصلی نمایش داده می‌شود:
var body: some View {
  VStack {
    // Check if the user is signed in.
    if let user = user {
      // If signed in, show a welcome message and the sign-out button.
      Text("Hello, \(user.profile?.givenName ?? "User")!")
        .font(.title)
        .padding()

      Button("Sign Out", action: signOut)
        .buttonStyle(.borderedProminent)

    } else {
      // If not signed in, show the "Sign in with Google" button.
      GoogleSignInButton(
        scheme: .dark,  // Options: .light, .dark, .auto
        style: .standard,  // Options: .standard, .wide, .icon
        state: .normal,  // Options: .normal, .disabled
        action: handleSignInButton
      ).padding()
    }
  }
}
  1. بلوک تکمیل handleSignInButton به‌روزرسانی کنید تا signInResult.user را به متغیر user جدید شما اختصاص دهد. این همان چیزی است که باعث می‌شود رابط کاربری به نمای وارد شده تغییر کند:
func handleSignInButton() {
  // Find the current window scene.
  guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene else {
    print("There is no active window scene")
    return
  }

  // Get the root view controller from the window scene.
  guard
    let rootViewController = windowScene.windows.first(where: { $0.isKeyWindow })?
      .rootViewController
  else {
    print("There is no key window or root view controller")
    return
  }

  // Start the sign-in process.
  GIDSignIn.sharedInstance.signIn(
    withPresenting: rootViewController
  ) { signInResult, error in
    guard let result = signInResult else {
      // Inspect error
      print("Error signing in: \(error?.localizedDescription ?? "No error description")")
      return
    }

    DispatchQueue.main.async {
      self.user = result.user
    }

    // If sign in succeeded, display the app's main content View.
    print("ID Token: \(result.user.idToken?.tokenString ?? "")")
  }
}
  1. یک تابع signOut جدید به پایین ساختار ContentView خود اضافه کنید تا توسط دکمه خروج شما فراخوانی شود:
func signOut() {
  GIDSignIn.sharedInstance.signOut()
  // After signing out, set the `user` state variable to `nil`.
  self.user = nil
}

برنامه را اجرا کنید و وارد سیستم شوید. پس از احراز هویت موفق، باید تغییر رابط کاربری را ببینید!

وضعیت ورود به سیستم چارچوب SwiftUI در شبیه‌ساز iOS

پس از اعمال این تغییرات، فایل ContentView.swift شما باید به شکل زیر باشد:

import GoogleSignIn
import GoogleSignInSwift
import SwiftUI

struct ContentView: View {

  @State private var user: GIDGoogleUser?

  var body: some View {
    VStack {
      // Check if the user is signed in.
      if let user = user {
        // If signed in, show a welcome message and the sign-out button.
        Text("Hello, \(user.profile?.givenName ?? "User")!")
          .font(.title)
          .padding()

        Button("Sign Out", action: signOut)
          .buttonStyle(.borderedProminent)

      } else {
        // If not signed in, show the "Sign in with Google" button.
        GoogleSignInButton(
          scheme: .dark,  // Options: .light, .dark, .auto
          style: .standard,  // Options: .standard, .wide, .icon
          state: .normal,  // Options: .normal, .disabled
          action: handleSignInButton
        ).padding()
      }
    }
  }

  func handleSignInButton() {
    // Find the current window scene.
    guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene else {
      print("There is no active window scene")
      return
    }

    // Get the root view controller from the window scene.
    guard
      let rootViewController = windowScene.windows.first(where: { $0.isKeyWindow })?
        .rootViewController
    else {
      print("There is no key window or root view controller")
      return
    }

    // Start the sign-in process.
    GIDSignIn.sharedInstance.signIn(
      withPresenting: rootViewController
    ) { signInResult, error in
      guard let result = signInResult else {
        // Inspect error
        print("Error signing in: \(error?.localizedDescription ?? "No error description")")
        return
      }

      DispatchQueue.main.async {
        self.user = result.user
      }

      // If sign in succeeded, display the app's main content View.
      print("ID Token: \(result.user.idToken?.tokenString ?? "")")
    }
  }

  func signOut() {
    GIDSignIn.sharedInstance.signOut()
    // After signing out, set the `user` state variable to `nil`.
    self.user = nil
  }
}

#Preview {
  ContentView()
}

رابط کاربری

  1. فایل ViewController.swift را باز کنید.
  2. در بالای ViewController ، درست زیر جایی که signInButton تعریف کرده‌اید، یک دکمه‌ی خروج و یک برچسب خوشامدگویی اضافه کنید:
let signOutButton = UIButton(type: .system)
let welcomeLabel = UILabel()
  1. تابع زیر را به پایین ViewController اضافه کنید. این تابع بر اساس وضعیت ورود کاربر، رابط کاربری متفاوتی را به او نشان می‌دهد:
private func updateUI(for user: GIDGoogleUser?) {
  if let user = user {
    // User is signed in.
    signInButton.isHidden = true
    signOutButton.isHidden = false
    welcomeLabel.isHidden = false
    welcomeLabel.text = "Hello, \(user.profile?.givenName ?? "User")!"
  } else {
    // User is signed out.
    signInButton.isHidden = false
    signOutButton.isHidden = true
    welcomeLabel.isHidden = true
  }
}
  1. در پایین تابع viewDidLoad ، کد زیر را برای افزودن برچسب خوشامدگویی و دکمه خروج به نما اضافه کنید:
// --- Set up the Welcome Label ---
welcomeLabel.translatesAutoresizingMaskIntoConstraints = false
welcomeLabel.textAlignment = .center
welcomeLabel.font = .systemFont(ofSize: 24, weight: .bold)
view.addSubview(welcomeLabel)

NSLayoutConstraint.activate([
  welcomeLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
  welcomeLabel.bottomAnchor.constraint(equalTo: signInButton.topAnchor, constant: -20),
])

// --- Set up the Sign-Out Button ---
signOutButton.translatesAutoresizingMaskIntoConstraints = false
signOutButton.setTitle("Sign Out", for: .normal)
view.addSubview(signOutButton)

NSLayoutConstraint.activate([
  signOutButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
  signOutButton.topAnchor.constraint(equalTo: signInButton.bottomAnchor, constant: 20),
])

signOutButton.addTarget(self, action: #selector(signOutButtonTapped), for: .touchUpInside)

// --- Set Initial UI State ---
updateUI(for: nil)
  1. تابع signInButtonTapped را به‌روزرسانی کنید تا متد UpdateUI را در صورت ورود موفق فراخوانی کند:
@objc func signInButtonTapped() {
  // Start the sign-in process.
  GIDSignIn.sharedInstance.signIn(withPresenting: self) { signInResult, error in
    guard let result = signInResult else {
      // Inspect error
      print("Error signing in: \(error?.localizedDescription ?? "No error description")")
      return
    }

    // If sign in succeeded, print the ID token.
    print("ID Token: \(result.user.idToken?.tokenString ?? "")")

    DispatchQueue.main.async {
      self.updateUI(for: result.user)
    }
  }
}
  1. در نهایت، یک تابع signOutButtonTapped به ViewController اضافه کنید تا فرآیند خروج را مدیریت کند:
@objc func signOutButtonTapped() {
  GIDSignIn.sharedInstance.signOut()
  // Update the UI for the signed-out state.
  updateUI(for: nil)
}

برنامه را اجرا کنید و وارد سیستم شوید. پس از احراز هویت موفق، باید تغییر رابط کاربری را ببینید!

وضعیت ورود به سیستم چارچوب UIKit در شبیه‌ساز iOS

پس از اعمال این تغییرات، فایل ViewController.swift شما باید به شکل زیر باشد:

import GoogleSignIn
import UIKit

class ViewController: UIViewController {

  // Create an instance of the Sign in with Google button
  let signInButton = GIDSignInButton()
  let signOutButton = UIButton(type: .system)
  let welcomeLabel = UILabel()

  override func viewDidLoad() {
    super.viewDidLoad()

    // Set the width and color of the sign-in button
    signInButton.style = .standard  // Options: .standard, .wide, .iconOnly
    signInButton.colorScheme = .dark  // Options: .dark, .light

    // Add the sign-in button to your view
    view.addSubview(signInButton)

    // Position the button using constraints
    signInButton.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
      signInButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
      signInButton.centerYAnchor.constraint(equalTo: view.centerYAnchor),
    ])

    // Add a target to the button to call a method when it's pressed
    signInButton.addTarget(self, action: #selector(signInButtonTapped), for: .touchUpInside)

    // --- Set up the Welcome Label ---
    welcomeLabel.translatesAutoresizingMaskIntoConstraints = false
    welcomeLabel.textAlignment = .center
    welcomeLabel.font = .systemFont(ofSize: 24, weight: .bold)
    view.addSubview(welcomeLabel)

    NSLayoutConstraint.activate([
      welcomeLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
      welcomeLabel.bottomAnchor.constraint(equalTo: signInButton.topAnchor, constant: -20),
    ])

    // --- Set up the Sign-Out Button ---
    signOutButton.translatesAutoresizingMaskIntoConstraints = false
    signOutButton.setTitle("Sign Out", for: .normal)
    view.addSubview(signOutButton)

    NSLayoutConstraint.activate([
      signOutButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
      signOutButton.topAnchor.constraint(equalTo: signInButton.bottomAnchor, constant: 20),
    ])

    signOutButton.addTarget(self, action: #selector(signOutButtonTapped), for: .touchUpInside)

    // --- Set Initial UI State ---
    updateUI(for: nil)
  }

  // This method is called when the sign-in button is pressed.
  @objc func signInButtonTapped() {
    // Start the sign-in process.
    GIDSignIn.sharedInstance.signIn(withPresenting: self) { signInResult, error in
      guard let result = signInResult else {
        // Inspect error
        print("Error signing in: \(error?.localizedDescription ?? "No error description")")
        return
      }

      // If sign in succeeded, print the ID token.
      print("ID Token: \(result.user.idToken?.tokenString ?? "")")

      DispatchQueue.main.async {
        self.updateUI(for: result.user)
      }
    }
  }

  private func updateUI(for user: GIDGoogleUser?) {
    if let user = user {
      // User is signed in.
      signInButton.isHidden = true
      signOutButton.isHidden = false
      welcomeLabel.isHidden = false
      welcomeLabel.text = "Hello, \(user.profile?.givenName ?? "User")!"
    } else {
      // User is signed out.
      signInButton.isHidden = false
      signOutButton.isHidden = true
      welcomeLabel.isHidden = true
    }
  }

  @objc func signOutButtonTapped() {
    GIDSignIn.sharedInstance.signOut()
    // Update the UI for the signed-out state.
    updateUI(for: nil)
  }
}

۹. بازیابی وضعیت ورود کاربر

برای بهبود تجربه کاربران قدیمی، مرحله بعدی بازیابی وضعیت ورود به سیستم آنها در هنگام اجرای برنامه است. فراخوانی restorePreviousSignIn از اعتبارنامه‌های ذخیره شده در Keychain برای ورود مجدد کاربر به صورت بی‌صدا استفاده می‌کند و تضمین می‌کند که آنها مجبور نیستند هر بار روند ورود به سیستم را تکمیل کنند.

سویفت‌یو‌آی

  1. فایل ContentView.swift را باز کنید.
  2. کد زیر را مستقیماً پس از VStack و درون متغیر body اضافه کنید:
.onAppear {
  // On appear, try to restore a previous sign-in.
  GIDSignIn.sharedInstance.restorePreviousSignIn { user, error in
    // This closure is called when the restoration is complete.
    if let user = user {
      // If a user was restored, update the `user` state variable.
      DispatchQueue.main.async {
        self.user = user
      }

      // Print the ID token to the console when restored.
      print("Restored ID Token: \(user.idToken?.tokenString ?? "")")
    }
  }
}

فایل ContentView.swift شما باید به شکل زیر باشد:

import GoogleSignIn
import GoogleSignInSwift
import SwiftUI

struct ContentView: View {

  @State private var user: GIDGoogleUser?

  var body: some View {
    VStack {
      // Check if the user is signed in.
      if let user = user {
        // If signed in, show a welcome message and the sign-out button.
        Text("Hello, \(user.profile?.givenName ?? "User")!")
          .font(.title)
          .padding()

        Button("Sign Out", action: signOut)
          .buttonStyle(.borderedProminent)

      } else {
        // If not signed in, show the "Sign in with Google" button.
        GoogleSignInButton(
          scheme: .dark,  // Options: .light, .dark, .auto
          style: .standard,  // Options: .standard, .wide, .icon
          state: .normal,  // Options: .normal, .disabled
          action: handleSignInButton
        ).padding()
      }
    }

    .onAppear {
      // On appear, try to restore a previous sign-in.
      GIDSignIn.sharedInstance.restorePreviousSignIn { user, error in
        // This closure is called when the restoration is complete.
        if let user = user {
          // If a user was restored, update the `user` state variable.
          DispatchQueue.main.async {
            self.user = user
          }

          // Print the ID token to the console when restored.
          print("Restored ID Token: \(user.idToken?.tokenString ?? "")")
        }
      }
    }
  }

  func handleSignInButton() {
    // Find the current window scene.
    guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene else {
      print("There is no active window scene")
      return
    }

    // Get the root view controller from the window scene.
    guard
      let rootViewController = windowScene.windows.first(where: { $0.isKeyWindow })?
        .rootViewController
    else {
      print("There is no key window or root view controller")
      return
    }

    // Start the sign-in process.
    GIDSignIn.sharedInstance.signIn(
      withPresenting: rootViewController
    ) { signInResult, error in
      guard let result = signInResult else {
        // Inspect error
        print("Error signing in: \(error?.localizedDescription ?? "No error description")")
        return
      }

      DispatchQueue.main.async {
        self.user = result.user
      }

      // If sign in succeeded, display the app's main content View.
      print("ID Token: \(result.user.idToken?.tokenString ?? "")")
    }
  }

  func signOut() {
    GIDSignIn.sharedInstance.signOut()
    // After signing out, set the `user` state variable to `nil`.
    self.user = nil
  }
}

#Preview {
  ContentView()
}

رابط کاربری

  1. فایل ViewController.swift را باز کنید.
  2. فراخوانی restorePreviousSignIn زیر را به انتهای متد viewDidLoad اضافه کنید:
// Attempt to restore a previous sign-in session
GIDSignIn.sharedInstance.restorePreviousSignIn { user, error in
  if let user = user {
    print("Successfully restored sign-in for user: \(user.profile?.givenName ?? "Unknown")")

    // Print the ID token when a session is restored.
    print("Restored ID Token: \(user.idToken?.tokenString ?? "")")

    // On success, update the UI for the signed-in state on the main thread.
    DispatchQueue.main.async {
      self.updateUI(for: user)
    }
  }
}

فایل ViewController.swift شما باید به شکل زیر باشد:

import GoogleSignIn
import UIKit

class ViewController: UIViewController {

  // Create an instance of the Sign in with Google button
  let signInButton = GIDSignInButton()
  let signOutButton = UIButton(type: .system)
  let welcomeLabel = UILabel()

  override func viewDidLoad() {
    super.viewDidLoad()

    // Set the width and color of the sign-in button
    signInButton.style = .standard  // Options: .standard, .wide, .iconOnly
    signInButton.colorScheme = .dark  // Options: .dark, .light

    // Add the sign-in button to your view
    view.addSubview(signInButton)

    // Position the button using constraints
    signInButton.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
      signInButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
      signInButton.centerYAnchor.constraint(equalTo: view.centerYAnchor),
    ])

    // Add a target to the button to call a method when it's pressed
    signInButton.addTarget(self, action: #selector(signInButtonTapped), for: .touchUpInside)

    // --- Set up the Welcome Label ---
    welcomeLabel.translatesAutoresizingMaskIntoConstraints = false
    welcomeLabel.textAlignment = .center
    welcomeLabel.font = .systemFont(ofSize: 24, weight: .bold)
    view.addSubview(welcomeLabel)

    NSLayoutConstraint.activate([
      welcomeLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor),
      welcomeLabel.bottomAnchor.constraint(equalTo: signInButton.topAnchor, constant: -20),
    ])

    // --- Set up the Sign-Out Button ---
    signOutButton.translatesAutoresizingMaskIntoConstraints = false
    signOutButton.setTitle("Sign Out", for: .normal)
    view.addSubview(signOutButton)

    NSLayoutConstraint.activate([
      signOutButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
      signOutButton.topAnchor.constraint(equalTo: signInButton.bottomAnchor, constant: 20),
    ])

    signOutButton.addTarget(self, action: #selector(signOutButtonTapped), for: .touchUpInside)

    // --- Set Initial UI State ---
    updateUI(for: nil)

    // Attempt to restore a previous sign-in session
    GIDSignIn.sharedInstance.restorePreviousSignIn { user, error in
      if let user = user {
        print("Successfully restored sign-in for user: \(user.profile?.givenName ?? "Unknown")")

        // Print the ID token when a session is restored.
        print("Restored ID Token: \(user.idToken?.tokenString ?? "")")

        // On success, update the UI for the signed-in state on the main thread.
        DispatchQueue.main.async {
          self.updateUI(for: user)
        }
      }
    }
  }

  // This method is called when the sign-in button is pressed.
  @objc func signInButtonTapped() {
    // Start the sign-in process.
    GIDSignIn.sharedInstance.signIn(withPresenting: self) { signInResult, error in
      guard let result = signInResult else {
        // Inspect error
        print("Error signing in: \(error?.localizedDescription ?? "No error description")")
        return
      }

      // If sign in succeeded, print the ID token.
      print("ID Token: \(result.user.idToken?.tokenString ?? "")")

      DispatchQueue.main.async {
        self.updateUI(for: result.user)
      }
    }
  }

  private func updateUI(for user: GIDGoogleUser?) {
    if let user = user {
      // User is signed in.
      signInButton.isHidden = true
      signOutButton.isHidden = false
      welcomeLabel.isHidden = false
      welcomeLabel.text = "Hello, \(user.profile?.givenName ?? "User")!"
    } else {
      // User is signed out.
      signInButton.isHidden = false
      signOutButton.isHidden = true
      welcomeLabel.isHidden = true
    }
  }

  @objc func signOutButtonTapped() {
    GIDSignIn.sharedInstance.signOut()
    // Update the UI for the signed-out state.
    updateUI(for: nil)
  }
}

ورود بی‌صدا را آزمایش کنید

پس از ورود به سیستم، برنامه را کاملاً ببندید و دوباره آن را اجرا کنید. باید ببینید که اکنون بدون نیاز به لمس دکمه، به طور خودکار وارد سیستم شده‌اید.

۱۰. توکن شناسه (ID token) را درک کنید

اگرچه شیء GIDGoogleUser برای شخصی‌سازی رابط کاربری با استفاده از نام و ایمیل کاربر مناسب است، اما مهم‌ترین داده‌ای که از SDK برگردانده می‌شود، توکن شناسه است.

این آزمایشگاه کد از یک ابزار آنلاین برای بررسی محتوای JWT استفاده می‌کند. در یک برنامه‌ی کاربردی، باید این توکن شناسه را به سرور backend خود ارسال کنید. سرور شما باید صحت توکن شناسه را تأیید کند و از JWT برای انجام کاری معنادارتر، مانند ایجاد یک حساب کاربری جدید در پلتفرم backend شما یا ایجاد یک session جدید برای کاربر، استفاده کند.

دسترسی و رمزگشایی توکن JWT

  1. برنامه خود را راه اندازی کنید.
  2. کنسول Xcode را باز کنید. باید یک ID Token چاپ شده را ببینید. چیزی شبیه به eyJhbGciOiJSUzI1Ni ... Hecz6Wm4Q خواهد بود.
  3. توکن شناسه را کپی کنید و از یک ابزار آنلاین مانند jwt.io برای رمزگشایی JWT استفاده کنید.

JWT رمزگشایی شده به شکل زیر خواهد بود:

{
  "alg": "RS256",
  "kid": "c8ab71530972bba20b49f78a09c9852c43ff9118",
  "typ": "JWT"
}
{
  "iss": "https://accounts.google.com",
  "azp": "171291171076-rrbkcjrp5jbte92ai9gub115ertscphi.apps.googleusercontent.com",
  "aud": "171291171076-rrbkcjrp5jbte92ai9gub115ertscphi.apps.googleusercontent.com",
  "sub": "10769150350006150715113082367",
  "email": "example@example.com",
  "email_verified": true,
  "at_hash": "JyCYDmHtzhjkb0-qJhKsMg",
  "name": "Kimya",
  "picture": "https://lh3.googleusercontent.com/a/ACg8ocIyy4VoR31t_n0biPVcScBHwZOCRaKVDb_MoaMYep65fyqoAw=s96-c",
  "given_name": "Kimya",
  "iat": 1758645896,
  "exp": 1758649496
}

فیلدهای توکن قابل توجه

توکن شناسه رمزگشایی‌شده شامل فیلدهایی با اهداف مختلف است. در حالی که برخی از آنها مانند نام و ایمیل به راحتی قابل فهم هستند، برخی دیگر توسط سرور backend شما برای تأیید استفاده می‌شوند.

درک فیلد زیر به ویژه مهم است:

  • sub : فیلد sub یک شناسه منحصر به فرد و دائمی برای حساب گوگل کاربر است. کاربر می‌تواند ایمیل یا نام اصلی خود را تغییر دهد، اما شناسه sub او هرگز تغییر نخواهد کرد. این باعث می‌شود که فیلد sub مقدار مناسبی برای استفاده به عنوان کلید اصلی برای حساب‌های کاربری backend شما باشد.

دریافت اطلاعات کاربر از توکن شناسه، اطلاعات بیشتری در مورد معنی تمام فیلدهای توکن دارد.

۱۱. برنامه خود را با App Check ایمن کنید

اکیداً توصیه می‌شود که App Check را فعال کنید تا مطمئن شوید که فقط برنامه شما می‌تواند به نقاط انتهایی OAuth 2.0 گوگل از طرف پروژه شما دسترسی داشته باشد. App Check با تأیید اینکه درخواست‌های ارسالی به سرویس‌های backend شما از برنامه معتبر شما در یک دستگاه واقعی و بدون دستکاری سرچشمه می‌گیرند، کار می‌کند.

این بخش نحوه ادغام App Check در برنامه شما و پیکربندی آن برای اشکال‌زدایی در شبیه‌ساز و اجرای نسخه نهایی روی دستگاه واقعی را نشان می‌دهد.

تنظیمات کنسول

ادغام App Check در برنامه شما نیاز به یک تنظیم یکباره در کنسول‌های Google Cloud و Firebase دارد. این شامل فعال کردن App Check برای کلاینت iOS OAuth شما در کنسول Google Cloud، ایجاد یک کلید API برای استفاده با ارائه‌دهنده اشکال‌زدایی App Check و پیوند دادن پروژه Google Cloud شما به Firebase است.

فعال کردن بررسی برنامه در کنسول ابری گوگل

  1. به لیست کلاینت‌های مرتبط با پروژه گوگل کلود خود بروید.
  2. شناسه کلاینت OAuth 2.0 که برای برنامه iOS خود ایجاد کرده‌اید را انتخاب کنید.
  3. گزینه «بررسی برنامه» را در زیر «شناسایی گوگل» برای iOS فعال کنید.

صفحه ویرایش کلاینت OAuth با قابلیت بررسی برنامه

  1. روی ذخیره کلیک کنید.

ایجاد کلید API

  1. به صفحه کتابخانه API برای پروژه Google Cloud خود بروید.
  2. عبارت Firebase App Check API را در نوار جستجو وارد کنید.

صفحه کتابخانه API کنسول ابری گوگل

  1. API بررسی برنامه Firebase را انتخاب و فعال کنید.
  2. به APIها و خدمات بروید و در منوی پیمایش، اعتبارنامه‌ها را انتخاب کنید.
  3. در بالای صفحه، گزینه ایجاد اعتبارنامه (Create credentials) را انتخاب کنید.

صفحه اعتبارنامه‌های API کنسول ابری گوگل

  1. یک نام به این کلید API اختصاص دهید.
  2. برنامه‌های iOS را در قسمت محدودیت‌های برنامه انتخاب کنید.
  3. شناسه بسته نرم‌افزاری برنامه خود را به عنوان یک برنامه تأیید شده اضافه کنید.
  4. در بخش محدودیت‌های API، کلید Restrict را انتخاب کنید.
  5. از منوی کشویی، گزینه Firebase App Check API را انتخاب کنید.
  6. ایجاد را انتخاب کنید.

صفحه ایجاد کلید API کنسول ابری گوگل

  1. کلید API ایجاد شده را کپی کنید. در مراحل بعدی به آن نیاز خواهید داشت.

فایربیس را به پروژه گوگل کلود خود اضافه کنید

  1. به کنسول فایربیس بروید.
  2. با راه‌اندازی یک پروژه Firebase، گزینه «شروع به کار» را انتخاب کنید.
  3. گزینه «افزودن فایربیس به پروژه گوگل کلود» را انتخاب کنید.

اضافه کردن فایربیس به یک پروژه گوگل کلود موجود

  1. یک پروژه Google Cloud را از منوی کشویی انتخاب کنید و مراحل ثبت نام را ادامه دهید.
  2. افزودن فایربیس را انتخاب کنید.
  3. پس از آماده شدن پروژه Firebase، برای باز کردن پروژه، گزینه Continue را انتخاب کنید.

ادغام کد سمت کلاینت

با پیکربندی پروژه Google Cloud برای App Check، زمان آن رسیده است که کد سمت کلاینت را برای فعال‌سازی آن بنویسیم. ارائه‌دهنده مورد استفاده برای تأیید اعتبار در محیط‌های تولید و اشکال‌زدایی متفاوت است. یک برنامه تولید در یک دستگاه واقعی از سرویس App Attest داخلی اپل برای اثبات اعتبار خود استفاده می‌کند. با این حال، از آنجا که شبیه‌ساز iOS نمی‌تواند این نوع تأیید اعتبار را ارائه دهد، محیط اشکال‌زدایی به یک ارائه‌دهنده اشکال‌زدایی ویژه نیاز دارد که یک کلید API به آن منتقل می‌شود.

کد زیر هر دو سناریو را با استفاده از یک دستورالعمل کامپایلر برای انتخاب خودکار ارائه‌دهنده صحیح در زمان ساخت، مدیریت می‌کند.

سویفت‌یو‌آی

  1. فایل اصلی برنامه را باز کنید.
  2. کلاس AppDelegate زیر را بعد از importها و قبل از ویژگی @main تعریف کنید:
class AppDelegate: NSObject, UIApplicationDelegate {
  func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
  ) -> Bool {

    #if targetEnvironment(simulator)
      // Configure for debugging on a simulator.
      // TODO: Replace "YOUR_API_KEY" with the key from your Google Cloud project.
      let apiKey = "YOUR_API_KEY"
      GIDSignIn.sharedInstance.configureDebugProvider(withAPIKey: apiKey) { error in
        if let error {
          print("Error configuring GIDSignIn debug provider: \(error)")
        }
      }
    #else
      // Configure GIDSignIn for App Check on a real device.
      GIDSignIn.sharedInstance.configure { error in
        if let error {
          print("Error configuring GIDSignIn for App Check: \(error)")
        } else {
          print("GIDSignIn configured for App Check.")
        }
      }
    #endif

    return true
  }
}
  1. "YOUR_API_KEY" را در کد ارائه شده با کلید API که از کنسول ابری گوگل کپی کرده‌اید، جایگزین کنید.
  2. خط زیر را داخل ساختار App خود، درست قبل از متغیر body اضافه کنید. این کار کلاس AppDelegate شما را در چرخه حیات برنامه ثبت می‌کند و به آن اجازه می‌دهد به راه‌اندازی برنامه و سایر رویدادهای سیستم پاسخ دهد:
@UIApplicationDelegateAdaptor(AppDelegate.self) var delegate

فایل اصلی برنامه شما باید به شکل زیر باشد:

import GoogleSignIn
import SwiftUI

class AppDelegate: NSObject, UIApplicationDelegate {
  func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
  ) -> Bool {

    #if targetEnvironment(simulator)
      // Configure for debugging on a simulator.
      // TODO: Replace "YOUR_API_KEY" with the key from your Google Cloud project.
      let apiKey = "YOUR_API_KEY"
      GIDSignIn.sharedInstance.configureDebugProvider(withAPIKey: apiKey) { error in
        if let error {
          print("Error configuring GIDSignIn debug provider: \(error)")
        }
      }
    #else
      // Configure GIDSignIn for App Check on a real device.
      GIDSignIn.sharedInstance.configure { error in
        if let error {
          print("Error configuring GIDSignIn for App Check: \(error)")
        } else {
          print("GIDSignIn configured for App Check.")
        }
      }
    #endif

    return true
  }
}

@main
struct iOS_Sign_in_with_Google_App: App {

  @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate

  var body: some Scene {
    WindowGroup {
      ContentView()

        .onOpenURL { url in
          GIDSignIn.sharedInstance.handle(url)
        }
    }
  }
}

رابط کاربری

  1. فایل AppDelegate.swift را باز کنید.
  2. متد application(_:didFinishLaunchingWithOptions:) را به‌روزرسانی کنید تا مقداردهی اولیه App Check را در بر بگیرد:
func application(
  _ application: UIApplication,
  didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {

  #if targetEnvironment(simulator)
    // Configure for debugging on a simulator.
    // TODO: Replace "YOUR_API_KEY" with the key from your Google Cloud project.
    let apiKey = "YOUR_API_KEY"
    GIDSignIn.sharedInstance.configureDebugProvider(withAPIKey: apiKey) { error in
      if let error {
        print("Error configuring GIDSignIn debug provider: \(error)")
      }
    }
  #else
    // Configure GIDSignIn for App Check on a real device.
    GIDSignIn.sharedInstance.configure { error in
      if let error {
        print("Error configuring GIDSignIn for App Check: \(error)")
      }
    }
  #endif

  return true
}
  1. "YOUR_API_KEY" را در کد ارائه شده با کلید API که از کنسول ابری گوگل کپی کرده‌اید، جایگزین کنید.

فایل AppDelegate.swift شما باید به شکل زیر باشد:

import GoogleSignIn
import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

  func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {

    #if targetEnvironment(simulator)
      // Configure for debugging on a simulator.
      // TODO: Replace "YOUR_API_KEY" with the key from your Google Cloud project.
      let apiKey = "YOUR_API_KEY"
      GIDSignIn.sharedInstance.configureDebugProvider(withAPIKey: apiKey) { error in
        if let error {
          print("Error configuring GIDSignIn debug provider: \(error)")
        }
      }
    #else
      // Configure GIDSignIn for App Check on a real device.
      GIDSignIn.sharedInstance.configure { error in
        if let error {
          print("Error configuring GIDSignIn for App Check: \(error)")
        }
      }
    #endif

    return true
  }

  func application(
    _ app: UIApplication,
    open url: URL,
    options: [UIApplication.OpenURLOptionsKey: Any] = [:]
  ) -> Bool {
    var handled: Bool

    handled = GIDSignIn.sharedInstance.handle(url)
    if handled {
      return true
    }
    // If not handled by this app, return false.
    return false
  }

  // MARK: UISceneSession Lifecycle

  func application(
    _ application: UIApplication,
    configurationForConnecting connectingSceneSession: UISceneSession,
    options: UIScene.ConnectionOptions
  ) -> UISceneConfiguration {
    // Called when a new scene session is being created.
    // Use this method to select a configuration to create the new scene with.
    return UISceneConfiguration(
      name: "Default Configuration",
      sessionRole: connectingSceneSession.role
    )
  }

  func application(
    _ application: UIApplication,
    didDiscardSceneSessions sceneSessions: Set<UISceneSession>
  ) {
    // Called when the user discards a scene session.
    // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
    // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
  }
}

برنامه تست را روی شبیه‌ساز بررسی کنید

  1. در نوار منوی Xcode، به مسیر Product > Scheme > Edit Scheme بروید.
  2. در منوی ناوبری، گزینه اجرا (Run) را انتخاب کنید.
  3. برگه آرگومان‌ها را انتخاب کنید.
  4. در بخش Arguments Passed on Launch ، گزینه + را انتخاب کرده و -FIRDebugEnabled را اضافه کنید. این آرگومان راه‌اندازی، ثبت گزارش اشکال‌زدایی Firebase را فعال می‌کند.
  5. بستن را انتخاب کنید.

صفحه ویرایشگر آرگومان‌های Xcode

  1. برنامه خود را روی شبیه‌ساز اجرا کنید.
  2. توکن اشکال‌زدایی App Check را که در کنسول Xcode چاپ شده است، کپی کنید.

توکن اشکال‌زدایی بررسی برنامه در کنسول Xcode

  1. در کنسول فایربیس به پروژه خود بروید.
  2. بخش ساخت (Build) را در منوی ناوبری (navigation menu) گسترش دهید.
  3. بررسی برنامه را انتخاب کنید.
  4. برگه برنامه‌ها را انتخاب کنید.
  5. موس را روی برنامه خود نگه دارید و نماد منوی سه نقطه‌ای را انتخاب کنید.

تنظیمات بررسی برنامه فایربیس

  1. مدیریت توکن‌های اشکال‌زدایی را انتخاب کنید.
  2. افزودن توکن اشکال‌زدایی را انتخاب کنید.
  3. برای توکن اشکال‌زدایی خود یک نام تعیین کنید و توکن اشکال‌زدایی که قبلاً کپی کرده‌اید را به عنوان مقدار آن جایگذاری کنید.
  4. برای ثبت توکن خود، گزینه ذخیره را انتخاب کنید.

مدیریت توکن اشکال‌زدایی بررسی برنامه فایربیس

  1. به شبیه‌ساز برگردید و وارد سیستم شوید.

ممکن است چند دقیقه طول بکشد تا معیارها در کنسول ظاهر شوند. پس از نمایش آنها، می‌توانید با جستجوی افزایش درخواست‌های تأیید شده در یکی از دو مکان زیر، تأیید کنید که App Check کار می‌کند:

  • در بخش بررسی برنامه (App Check) در کنسول فایربیس، زیر تب APIها (رابط‌های برنامه‌نویسی کاربردی).

معیارهای بررسی برنامه Firebase

  • در صفحه ویرایش کلاینت OAuth خود در کنسول Google Cloud.

معیارهای بررسی برنامه کنسول ابری گوگل

پس از نظارت بر معیارهای App Check برنامه خود و تأیید صحت درخواست‌های مشروع، باید App Check enforcement را فعال کنید . پس از اعمال این قابلیت، App Check تمام درخواست‌های تأیید نشده را رد می‌کند و تضمین می‌کند که فقط ترافیک برنامه معتبر شما می‌تواند به نقاط انتهایی OAuth 2.0 گوگل از طرف پروژه شما دسترسی پیدا کند.

۱۲. منابع اضافی

تبریک می‌گویم!

شما یک کلاینت iOS با قابلیت OAuth 2.0 را پیکربندی کرده‌اید، یک دکمه ورود با گوگل به یک برنامه iOS اضافه کرده‌اید، یاد گرفته‌اید که چگونه ظاهر دکمه را سفارشی کنید، یک توکن JWT ID را رمزگشایی کرده‌اید و App Check را برای برنامه خود فعال کرده‌اید.

این لینک‌ها می‌توانند در مراحل بعدی به شما کمک کنند:

سوالات متداول