1. לפני שמתחילים
בשיעור הזה תלמדו איך לפתח אפליקציית iOS שמטמיעה את התכונה 'כניסה באמצעות חשבון Google' ופועלת בסימולטור. אנחנו מספקים הטמעות שמשתמשות גם ב-SwiftUI וגם ב-UIKit.
SwiftUI הוא ה-framework המודרני של Apple לממשק משתמש, שמשמש לפיתוח אפליקציות חדשות. היא מאפשרת ליצור ממשקי משתמש לכל הפלטפורמות של אפל מבסיס קוד משותף יחיד. נדרשת גרסה מינימלית של iOS 13.
UIKit היא ה-framework המקורי והבסיסי של Apple לממשקי משתמש ב-iOS. הוא מספק תאימות לאחור לגרסאות ישנות יותר של iOS. לכן, זו בחירה טובה לאפליקציות ותיקות שצריכות לתמוך במגוון מכשירים ישנים.
אתם יכולים לבחור את המסגרת שהכי מתאימה לצרכים שלכם.
דרישות מוקדמות
מה תלמדו
- איך יוצרים פרויקט ב-Google Cloud
- איך יוצרים לקוחות OAuth ב-Google Cloud Console
- איך מטמיעים את התכונה 'כניסה באמצעות חשבון Google' באפליקציית iOS
- איך להתאים אישית את הכפתור לכניסה באמצעות חשבון Google
- איך מפענחים אסימון מזהה
- איך מפעילים את App Check באפליקציית iOS
הדרישות
- גרסה עדכנית של Xcode
- מחשב עם macOS שעומד בדרישות המערכת של גרסת Xcode שהתקנתם
ה-codelab הזה נוצר באמצעות Xcode 16.3 עם סימולטור iOS 18.3. מומלץ להשתמש בגרסה העדכנית של Xcode לפיתוח.
2. יצירת פרויקט חדש ב-Xcode
- פותחים את Xcode ובוחרים באפשרות Create a new Xcode project (יצירת פרויקט Xcode חדש).
- בוחרים בכרטיסייה iOS, בוחרים בתבנית אפליקציה ולוחצים על הבא.

- באפשרויות הפרויקט:
- מזינים את שם המוצר.
- אפשר גם לבחור צוות.
- מזינים את מזהה הארגון.
- רושמים או זוכרים את מזהה החבילה שנוצר. תצטרכו אותו בהמשך.
- בקטע ממשק, בוחרים באחת מהאפשרויות הבאות:
- SwiftUI לאפליקציה שמבוססת על SwiftUI.
- סטוריבורד לאפליקציה שמבוססת על UIKit.
- בוחרים באפשרות Swift בשדה שפה.
- לוחצים על הבא ובוחרים מיקום לשמירת הפרויקט.

3. יצירת לקוח OAuth
כדי לאפשר לאפליקציה שלכם לתקשר עם שירותי האימות של Google, אתם צריכים ליצור מזהה לקוח OAuth. לשם כך נדרש פרויקט ב-Google Cloud. בהמשך מפורטים השלבים ליצירת פרויקט ומזהה לקוח OAuth.
בוחרים פרויקט קיים או יוצרים פרויקט חדש ב-Google Cloud.
- נכנסים אל Google Cloud Console ובוחרים פרויקט או יוצרים פרויקט. אם בוחרים פרויקט קיים, המסוף יפנה אתכם אוטומטית לשלב הבא שנדרש.

- מזינים שם לפרויקט החדש ב-Google Cloud.
- בוחרים באפשרות יצירה.

הגדרת מסך ההסכמה
אם כבר הגדרתם מסך בקשת הסכמה לפרויקט שנבחר, לא תתבקשו להגדיר אותו עכשיו. במקרה כזה, אפשר לדלג על הקטע הזה ולעבור אל יצירת לקוח OAuth 2.0.
- בוחרים באפשרות הגדרת מסך בקשת ההסכמה.

- בדף המיתוג, בוחרים באפשרות תחילת העבודה.

- בדף הגדרות הפרויקט ממלאים את השדות הבאים:
- פרטי האפליקציה: מזינים שם וכתובת אימייל לתמיכה באפליקציה. כתובת האימייל הזו תוצג באופן ציבורי כדי שמשתמשים יוכלו לפנות אליכם עם שאלות לגבי ההסכמה שלהם.
- קהל: בוחרים באפשרות חיצוני.
- פרטים ליצירת קשר: מזינים כתובת אימייל שאליה Google יכולה לשלוח לכם הודעות לגבי הפרויקט.
- קוראים את המדיניות של Google בנושא נתוני משתמשים בשירותי API.
- לוחצים על יצירה.

- בתפריט הניווט, בוחרים בדף לקוחות.
- לוחצים על Create Client.

יצירת לקוח OAuth 2.0
- ב-Application type בוחרים באפשרות iOS.
- מזינים שם ללקוח.
- מזינים את מזהה החבילה שנוצר בשלב הקודם.
- מזינים את מזהה הצוות שהוקצה לצוות על ידי Apple. השלב הזה הוא אופציונלי כרגע, אבל נדרש מזהה צוות כדי להפעיל את App Check בהמשך ה-codelab הזה.
- בוחרים באפשרות יצירה.

- מעתיקים את מזהה הלקוח מתיבת הדו-שיח. תצטרכו אותו בהמשך.
- מורידים את קובץ ה-plist כדי להשתמש בו בהמשך.

4. הגדרת פרויקט Xcode
השלב הבא הוא להגדיר את פרויקט Xcode כך שיפעל עם Sign in with Google SDK. התהליך הזה כולל הוספה של ה-SDK לפרויקט כתלות והגדרה של הגדרות הפרויקט עם מזהה לקוח ייחודי. המזהה הזה מאפשר ל-SDK לתקשר באופן מאובטח עם שירות האימות של Google במהלך תהליך הכניסה.
התקנת יחסי התלות של 'כניסה באמצעות חשבון Google'
- פותחים את פרויקט Xcode.
- עוברים אל File > Add Package Dependencies (קובץ > הוספת תלות בחבילה).
- בסרגל החיפוש, מזינים את כתובת ה-URL של מאגר הכניסה באמצעות Google: https://github.com/google/GoogleSignIn-iOS

- בוחרים באפשרות הוספת חבילה.
- בוחרים את יעד האפליקציה הראשי לחבילה GoogleSignIn.
- אם אתם משתמשים ב-SwiftUI, בוחרים את יעד האפליקציה הראשי לחבילה GoogleSignInSwift. אם אתם מתכננים להשתמש ב-UIKit, אל תבחרו יעד לחבילה הזו.
- בוחרים באפשרות הוספת חבילה.

הגדרת פרטי הכניסה של האפליקציה
- בחלונית הניווט בפרויקט, לוחצים על שורש הפרויקט.
- באזור העריכה הראשי, בוחרים את יעד האפליקציה הראשי מהרשימה TARGETS.
- לוחצים על הכרטיסייה מידע בחלק העליון של אזור העריכה.
- מעבירים את העכבר מעל השורה האחרונה בקטע Custom iOS Target Properties (מאפייני טירגוט מותאמים אישית ל-iOS) ולוחצים על הלחצן + שמופיע.

- בעמודה Key (מפתח), מקלידים GIDClientID.
- בעמודה Value (ערך), מדביקים את מזהה הלקוח שהעתקתם מ-Google Cloud Console.

- פותחים את קובץ ה-plist שהורדתם ממסוף Google Cloud.
- מעתיקים את הערך של Reversed Client ID.

- מרחיבים את הקטע סוגי כתובות URL בתחתית הכרטיסייה מידע.
- לוחצים על הלחצן +.
- מזינים את מזהה הלקוח ההפוך בתיבה סכמות כתובות URL.

עכשיו אפשר להתחיל להוסיף את לחצן הכניסה לאפליקציה.
5. הוספת לחצן הכניסה
אחרי שמגדירים את פרויקט Xcode, אפשר להתחיל להוסיף את הלחצן 'כניסה באמצעות חשבון Google' לאפליקציה.
הלוגיקה המרכזית של השלב הזה היא הקריאה ל-GIDSignIn.sharedInstance.signIn. השיטה הזו מתחילה את תהליך האימות ומעבירה את השליטה ל-SDK של 'כניסה באמצעות חשבון Google' כדי להציג למשתמש את תהליך הכניסה באמצעות חשבון Google.
SwiftUI
- מחפשים את הקובץ ContentView.swift בחלונית הניווט בפרויקט ב-Xcode.
- מחליפים את התוכן של הקובץ הזה בטקסט הבא:
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()
}

UIKit
- מחפשים את הקובץ ViewController.swift בחלונית הניווט בפרויקט ב-Xcode.
- מחליפים את התוכן של הקובץ הזה בטקסט הבא:
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 ?? "")")
}
}
}

הצגת לחצן הכניסה
מפעילים את האפליקציה בסימולטור. יוצג לכם הלחצן 'כניסה באמצעות חשבון Google', אבל הוא עדיין לא יפעל כמו שצריך. זה צפוי, כי עדיין צריך להטמיע את הקוד כדי לטפל בהפניה חזרה לאפליקציה אחרי שהמשתמש מבצע אימות.
6. התאמה אישית של לחצן הכניסה
אתם יכולים להתאים אישית את לחצן ברירת המחדל של הכניסה באמצעות חשבון Google כדי שיתאים יותר לעיצוב האפליקציה שלכם. ערכת ה-SDK של 'כניסה באמצעות חשבון Google' מאפשרת לשנות את ערכת הצבעים והסגנון של הלחצן.
SwiftUI
לחצן ברירת המחדל מתווסף לדף באמצעות שורת הקוד הבאה:
GoogleSignInButton(action: handleSignInButton)
התג GoogleSignInButton מותאם אישית על ידי העברת פרמטרים לפונקציית האתחול שלו. הקוד הבא יגרום לכפתור הכניסה להופיע במצב כהה.
- פותחים את ContentView.swift.
- מעדכנים את הפונקציה לאתחול של
GoogleSignInButtonכך שתכיל את הערכים הבאים:
GoogleSignInButton(
scheme: .dark, // Options: .light, .dark, .auto
style: .standard, // Options: .standard, .wide, .icon
state: .normal, // Options: .normal, .disabled
action: handleSignInButton
).padding()

מידע נוסף על אפשרויות ההתאמה האישית זמין במאמר GoogleSignInSwift Framework Reference
UIKit
כברירת מחדל, הכפתור נוצר עם שורות הקוד הבאות:
// Create an instance of the Sign in with Google button
let signInButton = GIDSignInButton()
// Add the button to your view
view.addSubview(signInButton)
הלחצן GIDSignInButton מותאם אישית על ידי הגדרת מאפיינים במופע של הלחצן. הקוד הבא יגרום לכפתור הכניסה להופיע במצב כהה.
- פותחים את ViewController.swift.
- מוסיפים את שורות הקוד הבאות ממש לפני שמוסיפים את לחצן הכניסה לתצוגה בפונקציה
viewDidLoad:
// Set the width and color of the sign-in button
signInButton.style = .standard // Options: .standard, .wide, .iconOnly
signInButton.colorScheme = .dark // Options: .dark, .light

מידע נוסף על התאמה אישית זמין בחומר העזר בנושא GoogleSignIn Framework
7. טיפול בכתובת ה-URL להפניה אוטומטית לאימות
אחרי שמוסיפים את לחצן הכניסה, השלב הבא הוא לטפל בהפניה האוטומטית שמתרחשת אחרי שהמשתמש מבצע אימות. אחרי האימות, Google מחזירה כתובת URL עם קוד הרשאה זמני. כדי להשלים את תהליך הכניסה, רכיב handler מיירט את כתובת ה-URL הזו ומעביר אותה ל-SDK של הכניסה באמצעות חשבון Google כדי להחליף אותה באסימון מזהה חתום (JWT).
SwiftUI
- פותחים את הקובץ שמכיל את מבנה הנתונים
App. שם הקובץ נקבע לפי שם הפרויקט, ולכן הוא ייראה בערך כך: YourProjectNameApp.swift. - מחליפים את התוכן של הקובץ הזה בטקסט הבא:
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)
}
}
}
}
UIKit
- פותחים את AppDelegate.swift.
- מוסיפים את שורת הייבוא הבאה לחלק העליון של הקובץ:
import GoogleSignIn
- מוסיפים את פונקציית הטיפול באימות הבאה בתוך המחלקה
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 של'כניסה באמצעות חשבון Google' מאחסנת בצורה מאובטחת את פרטי הכניסה של המשתמש ב-Keychain של המכשיר. אפשר להשתמש בפרטי הכניסה האלה בהמשך כדי לאפשר למשתמש להישאר מחובר בהפעלות הבאות של האפליקציה.
8. הוספת כפתור יציאה
עכשיו, אחרי שהכניסה לחשבון פועלת, השלב הבא הוא להוסיף לחצן ליציאה מהחשבון ולעדכן את ממשק המשתמש כך שישקף את מצב הכניסה הנוכחי של המשתמש. כשמתבצעת כניסה בהצלחה, ה-SDK מספק אובייקט GIDGoogleUser. האובייקט הזה מכיל מאפיין profile עם מידע בסיסי כמו שם המשתמש וכתובת האימייל שלו, שבו תשתמשו כדי להתאים אישית את ממשק המשתמש.
SwiftUI
- פותחים את הקובץ ContentView.swift.
- מוסיפים משתנה מצב בחלק העליון של מבנה הנתונים
ContentView. המשתנה הזה יכיל את פרטי המשתמש אחרי שהוא ייכנס לחשבון. מכיוון שזהו משתנה@State, SwiftUI יעדכן אוטומטית את ממשק המשתמש בכל פעם שהערך שלו ישתנה:
struct ContentView: View {
@State private var user: GIDGoogleUser?
}
- מחליפים את
bodyהנוכחי של מבנהContentViewב-VStackהבא. הפעולה הזו תבדוק אם משתנה המצבuserמכיל משתמש. אם כן, תופיע הודעת פתיחה ולחצן יציאה. אם לא, יוצג הכפתור המקורי 'כניסה באמצעות חשבון Google':
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()
}
}
}
- מעדכנים את בלוק ההשלמה
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 ?? "")")
}
}
- מוסיפים פונקציה חדשה
signOutלתחתית של מבנה הנתוניםContentViewכדי שהיא תופעל על ידי לחצן היציאה:
func signOut() {
GIDSignIn.sharedInstance.signOut()
// After signing out, set the `user` state variable to `nil`.
self.user = nil
}
מפעילים את האפליקציה ונכנסים לחשבון. אחרי אימות מוצלח, ממשק המשתמש אמור להשתנות.

אחרי שמבצעים את השינויים האלה, הקובץ 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()
}
UIKit
- פותחים את ViewController.swift.
- בחלק העליון של
ViewController, ממש מתחת למקום שבו הצהרתם עלsignInButton, מוסיפים לחצן יציאה ותווית ברוכים הבאים:
let signOutButton = UIButton(type: .system)
let welcomeLabel = UILabel()
- מוסיפים את הפונקציה הבאה לתחתית הקובץ
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
}
}
- בתחתית הפונקציה
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)
- מעדכנים את הפונקציה
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)
}
}
}
- לבסוף, מוסיפים פונקציית
signOutButtonTappedל-ViewControllerכדי לטפל בתהליך היציאה מהחשבון:
@objc func signOutButtonTapped() {
GIDSignIn.sharedInstance.signOut()
// Update the UI for the signed-out state.
updateUI(for: nil)
}
מפעילים את האפליקציה ונכנסים לחשבון. אחרי אימות מוצלח, ממשק המשתמש אמור להשתנות.

אחרי שמבצעים את השינויים האלה, הקובץ 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)
}
}
9. שחזור מצב הכניסה של משתמש
כדי לשפר את חוויית השימוש של משתמשים חוזרים, השלב הבא הוא לשחזר את מצב הכניסה שלהם כשהם מפעילים את האפליקציה. התקשרות אל restorePreviousSignIn משתמשת בפרטי הכניסה ששמורים ב-Keychain כדי להכניס את המשתמש שוב לחשבון באופן שקט, וכך המשתמש לא צריך להשלים את תהליך הכניסה בכל פעם.
SwiftUI
- פותחים את הקובץ ContentView.swift.
- מוסיפים את הקוד הבא מיד אחרי
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()
}
UIKit
- פותחים את ViewController.swift.
- מוסיפים את הקריאה
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)
}
}
בדיקת הכניסה השקטה
אחרי שנכנסים לחשבון, סוגרים את האפליקציה לגמרי ומפעילים אותה מחדש. אמור להופיע שאתם מחוברים לחשבון באופן אוטומטי בלי שתצטרכו להקיש על הלחצן.
10. הסבר על אסימון מזהה
אובייקט GIDGoogleUser נוח להתאמה אישית של ממשק המשתמש באמצעות השם וכתובת האימייל של המשתמש, אבל הנתון הכי חשוב שמוחזר מ-SDK הוא אסימון ה-ID.
בשיעור הזה נשתמש בכלי אונליין כדי לבדוק את התוכן של ה-JWT. באפליקציה לייצור, צריך לשלוח את טוקן ה-ID הזה לשרת הקצה העורפי. השרת צריך לאמת את השלמות של טוקן הזהות ולהשתמש ב-JWT כדי לבצע פעולה משמעותית יותר, כמו יצירת חשבון חדש בפלטפורמת ה-Backend או יצירת סשן חדש למשתמש.
גישה לאסימון JWT ופענוח שלו
- מפעילים את האפליקציה.
- פותחים את מסוף Xcode. אסימון המזהה יודפס. היא תיראה בערך כך:
eyJhbGciOiJSUzI1Ni ... Hecz6Wm4Q. - מעתיקים את אסימון הזהות ומשתמשים בכלי אונליין כמו 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
}
שדות טוקן חשובים
אסימון המזהה המפוענח מכיל שדות עם מטרות שונות. חלק מהפרטים קל להבין, כמו שם וכתובת אימייל, אבל אחרים משמשים את שרת הקצה העורפי לאימות.
חשוב במיוחד להבין את השדה הבא:
- sub: השדה
subהוא מזהה ייחודי וקבוע של חשבון Google של המשתמש. משתמש יכול לשנות את כתובת האימייל הראשית או את השם שלו, אבל המזהה שלו ב-subלא ישתנה לעולם. לכן, הערך בשדהsubהוא הערך המושלם לשימוש כמפתח ראשי לחשבונות המשתמשים בבק-אנד.
במאמר קבלת פרטי משתמש מאסימון המזהה יש מידע נוסף על המשמעות של כל השדות באסימון.
11. אבטחת האפליקציה באמצעות App Check
מומלץ מאוד להפעיל את App Check כדי לוודא שרק האפליקציה שלכם יכולה לגשת לנקודות הקצה של OAuth 2.0 של Google בשם הפרויקט שלכם. התכונה App Check פועלת על ידי אימות הבקשות לשירותי ה-Backend, כדי לוודא שהן מגיעות מהאפליקציה האותנטית שלכם במכשיר אמיתי שלא בוצעו בו שינויים.
בקטע הזה מוסבר איך לשלב את App Check באפליקציה ואיך להגדיר אותו לניפוי באגים בסימולטור ולגרסת ייצור שפועלת במכשיר אמיתי.
הגדרת המסוף
כדי לשלב את App Check באפליקציה, צריך לבצע הגדרה חד-פעמית במסוף Google Cloud ובמסוף Firebase. התהליך כולל הפעלה של App Check ללקוח OAuth של iOS ב-Google Cloud Console, יצירה של מפתח API לשימוש עם ספק הניפוי באגים של App Check וקישור של פרויקט Google Cloud ל-Firebase.
הפעלת App Check במסוף Google Cloud
- עוברים לרשימת הלקוחות שמשויכים לפרויקט ב-Google Cloud.
- בוחרים את מזהה הלקוח ב-OAuth 2.0 שיצרתם עבור אפליקציית iOS.
- מעבירים את המתג של App Check למצב מופעל בקטע Google Identity for iOS

- לוחצים על שמירה.
יצירה של מפתח API
- עוברים לדף API Library בפרויקט ב-Google Cloud.
- מזינים Firebase App Check API בסרגל החיפוש.

- בוחרים את Firebase App Check API ומפעילים אותו.
- עוברים אל APIs & Services ובוחרים באפשרות Credentials בתפריט הניווט.
- לוחצים על יצירת פרטי כניסה בחלק העליון של הדף.

- נותנים שם למפתח ה-API.
- בקטע Application restrictions, בוחרים באפשרות iOS apps.
- מוסיפים את מזהה החבילה של האפליקציה כאפליקציה מאושרת.
- בקטע API restrictions, לוחצים על Restrict key.
- בתפריט הנפתח, בוחרים באפשרות Firebase App Check API.
- בוחרים באפשרות יצירה.

- מעתיקים את מפתח ה-API שנוצר. תצטרכו אותו בשלב הבא.
הוספת Firebase לפרויקט ב-Google Cloud
- עוברים אל מסוף Firebase.
- בוחרים באפשרות Get started by setting up a Firebase project (מתחילים בהגדרת פרויקט ב-Firebase).
- בוחרים באפשרות הוספת Firebase לפרויקט Google Cloud.

- בוחרים פרויקט ב-Google Cloud מהתפריט הנפתח וממשיכים בתהליך ההרשמה.
- בוחרים באפשרות הוספת Firebase.
- אחרי שהפרויקט ב-Firebase מוכן, לוחצים על המשך כדי לפתוח את הפרויקט.
שילוב קוד בצד הלקוח
אחרי שמגדירים את פרויקט Google Cloud לשימוש ב-App Check, צריך לכתוב את הקוד בצד הלקוח כדי להפעיל אותו. הספק שמשמש לאימות שונה בסביבות ייצור ובסביבות ניפוי באגים. אפליקציה שנמצאת בשלב ההפקה במכשיר אמיתי משתמשת בשירות App Attest המובנה של אפל כדי להוכיח את האותנטיות שלה. עם זאת, מכיוון שסימולטור iOS לא יכול לספק אישור כזה, סביבת הניפוי באגים דורשת ספק ניפוי באגים מיוחד שמועבר אליו מפתח API.
הקוד הבא מטפל בשני התרחישים באמצעות הנחיית קומפילציה לבחירה אוטומטית של הספק הנכון בזמן הבנייה.
SwiftUI
- פותחים את קובץ האפליקציה הראשי.
- מגדירים את המחלקה
AppDelegateאחרי הייבוא ולפני המאפיין@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
}
}
- מחליפים את הערך
"YOUR_API_KEY"בקוד שמופיע למעלה במפתח ה-API שהעתקתם מ-Google Cloud Console. - מוסיפים את השורה הבאה בתוך מבנה הנתונים
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)
}
}
}
}
UIKit
- פותחים את AppDelegate.swift.
- מעדכנים את השיטה
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
}
- מחליפים את הערך
"YOUR_API_KEY"בקוד שמופיע למעלה במפתח ה-API שהעתקתם מ-Google Cloud Console.
קובץ 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.
}
}
בדיקת App Check באמולטור
- בסרגל התפריטים של Xcode, עוברים אל Product (מוצר) > Scheme (סכימה) > Edit Scheme (עריכת הסכימה).
- בתפריט הניווט, בוחרים באפשרות Run (הפעלה).
- בוחרים בכרטיסייה Arguments (ארגומנטים).
- בקטע Arguments Passed on Launch (ארגומנטים שהערך שלהם נקבע בהפעלה), לוחצים על + ומוסיפים את הערך -FIRDebugEnabled. ארגומנט ההפעלה הזה מאפשר רישום ביומן של ניפוי באגים ב-Firebase.
- לוחצים על סגירה.

- מפעילים את האפליקציה בסימולטור.
- מעתיקים את אסימון ניפוי הבאגים של App Check שמוצג במסוף Xcode.

- עוברים לפרויקט במסוף Firebase.
- מרחיבים את הקטע Build (פיתוח) בתפריט הניווט.
- בוחרים באפשרות בדיקת אפליקציות.
- בוחרים בכרטיסייה אפליקציות.
- מעבירים את העכבר מעל האפליקציה ולוחצים על סמל האפשרויות הנוספות (3 נקודות).

- בוחרים באפשרות ניהול אסימוני ניפוי באגים.
- לוחצים על הוספת טוקן לניפוי באגים.
- נותנים שם לטוקן לניפוי באגים ומדביקים את הטוקן לניפוי באגים שהעתקתם קודם לכן כערך.
- לוחצים על שמירה כדי לרשום את האסימון.

- חוזרים לסימולטור ונכנסים לחשבון.
יכול להיות שיעברו כמה דקות עד שהמדדים יופיעו במסוף. אחרי שהם יבצעו את הפעולה, תוכלו לוודא ש-App Check פועל על ידי חיפוש עלייה במספר הבקשות המאומתות באחד משני המקומות הבאים:
- בקטע App Check במסוף Firebase, בכרטיסייה APIs.

- בדף העריכה של לקוח OAuth ב-Google Cloud Console.

אחרי שתעקבו אחרי מדדי App Check של האפליקציה ותוודאו שהבקשות הלגיטימיות מאומתות, כדאי להפעיל את האכיפה של App Check. אחרי שהאכיפה תופעל, App Check ידחה את כל הבקשות שלא אומתו, וכך יבטיח שרק תנועה מהאפליקציה האותנטית שלכם תוכל לגשת לנקודות הקצה של Google OAuth 2.0 בשם הפרויקט שלכם.
12. מקורות מידע נוספים
מעולה!
הגדרתם לקוח iOS OAuth 2.0, הוספתם לחצן 'כניסה באמצעות Google' לאפליקציית iOS, למדתם איך להתאים אישית את המראה של הלחצן, פענחתם אסימון מזהה JWT והפעלתם את App Check באפליקציה.
הקישורים הבאים יכולים לעזור לכם בשלבים הבאים:
- איך מתחילים להשתמש בכניסה באמצעות חשבון Google ל-iOS
- מאגר Google Sign-In for iOS
- אימות של אסימון מזהה של Google
- איך מתחילים להשתמש ב-App Check לכניסה באמצעות חשבון Google ב-iOS
- ביטול טוקנים של גישה וניתוק האפליקציה
- מידע נוסף על פרויקטים ב-Google Cloud
- שיטות אימות של Google Identity
- הפעלת האכיפה של App Check