1. Avant de commencer
Cet atelier de programmation vous explique comment créer une application iOS qui implémente S'identifier avec Google et s'exécute dans un simulateur. Des implémentations utilisant à la fois SwiftUI et UIKit sont fournies.
SwiftUI est le framework d'UI moderne d'Apple pour le développement de nouvelles applications. Il permet de créer des interfaces utilisateur pour toutes les plates-formes Apple à partir d'un seul codebase partagé. Elle nécessite au minimum iOS 13.
UIKit est le framework d'interface utilisateur d'origine et fondamental d'Apple pour iOS. Elle assure la rétrocompatibilité avec les anciennes versions d'iOS. Cela en fait un bon choix pour les applications établies qui doivent être compatibles avec une variété d'anciens appareils.
Vous pouvez suivre le chemin d'accès du framework qui correspond le mieux à vos besoins de développement.
Prérequis
Points abordés
- Créer un projet Google Cloud
- Créer des clients OAuth dans la console Google Cloud
- Implémenter Se connecter avec Google pour votre application iOS
- Personnaliser le bouton "Se connecter avec Google"
- Décoder un jeton d'identité
- Activer App Check pour votre application iOS
Prérequis
- Une version actuelle de Xcode
- Un ordinateur exécutant macOS et répondant à la configuration système requise pour la version d'Xcode que vous avez installée
Cet atelier de programmation a été créé à l'aide de Xcode 16.3 avec le simulateur iOS 18.3. Vous devez utiliser la dernière version de Xcode pour le développement.
2. Créer un projet Xcode
- Ouvrez Xcode et sélectionnez Create a new Xcode project (Créer un projet Xcode).
- Sélectionnez l'onglet iOS, puis le modèle App (Application), et cliquez sur Next (Suivant).

- Dans les options du projet :
- Saisissez le nom de votre produit.
- (Facultatif) Sélectionnez votre équipe.
- Saisissez votre identifiant d'organisation.
- Notez l'identifiant du bundle généré. Vous en aurez besoin ultérieurement.
- Pour Interface, choisissez l'une des options suivantes :
- SwiftUI pour une application basée sur SwiftUI.
- Storyboard pour une application basée sur UIKit.
- Choisissez Swift pour la langue.
- Cliquez sur Suivant, puis choisissez un emplacement pour enregistrer votre projet.

3. Créer un client OAuth
Pour permettre à votre application de communiquer avec les services d'authentification de Google, vous devez créer un ID client OAuth. Pour cela, vous avez besoin d'un projet Google Cloud. Les étapes suivantes vous guideront dans la création d'un projet et d'un ID client OAuth.
Sélectionner ou créer un projet Google Cloud
- Accédez à la console Google Cloud, puis sélectionnez ou créez un projet. Si vous sélectionnez un projet préexistant, la console vous redirigera automatiquement vers la prochaine étape requise.

- Saisissez un nom pour votre nouveau projet Google Cloud.
- Sélectionnez Créer.

Configurer votre écran de consentement
Si vous avez déjà configuré un écran de consentement pour le projet sélectionné, vous ne serez pas invité à le faire maintenant. Dans ce cas, vous pouvez ignorer cette section et passer à Créer un client OAuth 2.0.
- Sélectionnez Configurer l'écran d'autorisation.

- Sélectionnez Premiers pas sur la page "Branding".

- Sur la page de configuration du projet, remplissez les champs suivants :
- Informations sur l'application : saisissez le nom et l'adresse e-mail d'assistance utilisateur de votre application. Cette adresse e-mail d'assistance sera affichée publiquement pour que les utilisateurs puissent vous contacter en cas de question sur leur consentement.
- Audience : sélectionnez Externe.
- Coordonnées : saisissez une adresse e-mail pour que Google puisse vous contacter au sujet de votre projet.
- Consultez le Règlement sur les données utilisateur dans les services d'API Google.
- Cliquez sur Créer.

- Sélectionnez la page Clients dans le menu de navigation.
- Cliquez sur Créer un client.

Créer un client OAuth 2.0
- Sélectionnez iOS comme type d'application.
- Saisissez un nom pour votre client.
- Saisissez l'identifiant du bundle créé à la dernière étape.
- Saisissez l'ID d'équipe attribué à votre équipe par Apple. Cette étape est facultative pour le moment, mais un ID d'équipe est requis pour activer App Check plus tard dans cet atelier de programmation.
- Sélectionnez Créer.

- Copiez l'ID client dans la boîte de dialogue. Vous en aurez besoin plus tard.
- Téléchargez le fichier plist pour le consulter ultérieurement.

4. Configurer votre projet Xcode
L'étape suivante consiste à configurer votre projet Xcode pour qu'il fonctionne avec le SDK Se connecter avec Google. Ce processus consiste à ajouter le SDK à votre projet en tant que dépendance et à configurer les paramètres de votre projet avec un ID client unique. Cet ID permet au SDK de communiquer de manière sécurisée avec le service d'authentification de Google lors du processus de connexion.
Installer les dépendances de Se connecter avec Google
- Ouvrez votre projet Xcode.
- Accédez à File > Add Package Dependencies (Fichier > Ajouter des dépendances de package).
- Dans la barre de recherche, saisissez l'URL du dépôt "Se connecter avec Google" : https://github.com/google/GoogleSignIn-iOS.

- Sélectionnez Ajouter un package.
- Sélectionnez la principale application cible pour le package GoogleSignIn.
- Si vous utilisez SwiftUI, sélectionnez la cible d'application principale pour le package GoogleSignInSwift. Si vous prévoyez d'utiliser UIKit, ne sélectionnez pas de cible pour ce package.
- Sélectionnez Ajouter un package.

Configurer les identifiants de votre application
- Dans le navigateur de projet, cliquez sur la racine de votre projet.
- Dans la zone principale de l'éditeur, sélectionnez la cible principale de votre application dans la liste CIBLES.
- Sélectionnez l'onglet Infos en haut de la zone de l'éditeur.
- Pointez sur la dernière ligne de la section Custom iOS Target Properties (Propriétés cibles iOS personnalisées), puis cliquez sur le bouton + qui s'affiche.

- Dans la colonne Clé, saisissez GIDClientID.
- Dans la colonne Valeur, collez l'ID client que vous avez copié depuis la console Google Cloud.

- Ouvrez le fichier plist que vous avez téléchargé depuis la console Google Cloud.
- Copiez la valeur de ID client inversé.

- Développez Types d'URL en bas de l'onglet Infos.
- Sélectionnez le bouton +.
- Saisissez l'ID client inversé dans la zone Schémas d'URL.

Nous sommes maintenant prêts à ajouter le bouton de connexion à notre application.
5. Ajouter le bouton de connexion
Maintenant que le projet Xcode est configuré, il est temps d'ajouter le bouton "Se connecter avec Google" à l'application.
La logique principale de cette étape est l'appel à GIDSignIn.sharedInstance.signIn. Cette méthode lance le processus d'authentification, en laissant le contrôle au SDK Se connecter avec Google pour présenter le flux Se connecter avec Google à l'utilisateur.
SwiftUI
- Recherchez le fichier ContentView.swift dans le navigateur de projet Xcode.
- Remplacez le contenu de ce fichier par le texte suivant :
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
- Recherchez le fichier ViewController.swift dans le navigateur de projet Xcode.
- Remplacez le contenu de ce fichier par le texte suivant :
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 ?? "")")
}
}
}

Afficher le bouton de connexion
Lancez votre application dans le simulateur. Le bouton "Se connecter avec Google" s'affiche, mais il ne fonctionne pas encore correctement. C'est normal, car vous devez encore implémenter le code pour gérer la redirection vers votre application une fois que l'utilisateur s'est authentifié.
6. Personnaliser le bouton de connexion
Vous pouvez personnaliser le bouton par défaut "S'identifier avec Google" pour mieux l'adapter au thème de votre application. Le SDK S'identifier avec Google vous permet de modifier le jeu de couleurs et le style du bouton.
SwiftUI
Le bouton par défaut est ajouté à la page avec cette ligne de code :
GoogleSignInButton(action: handleSignInButton)
Le GoogleSignInButton est personnalisé en transmettant des paramètres à son initialiseur. Le code suivant permet d'afficher le bouton de connexion en mode sombre.
- Ouvrez ContentView.swift.
- Mettez à jour l'initialiseur pour que
GoogleSignInButtoncontienne les valeurs suivantes :
GoogleSignInButton(
scheme: .dark, // Options: .light, .dark, .auto
style: .standard, // Options: .standard, .wide, .icon
state: .normal, // Options: .normal, .disabled
action: handleSignInButton
).padding()

Pour en savoir plus sur les options de personnalisation, consultez la documentation de référence du framework GoogleSignInSwift.
UIKit
Le bouton par défaut est créé avec ces lignes de code :
// Create an instance of the Sign in with Google button
let signInButton = GIDSignInButton()
// Add the button to your view
view.addSubview(signInButton)
Le GIDSignInButton est personnalisé en définissant des propriétés sur l'instance du bouton. Le code suivant permet d'afficher le bouton de connexion en mode sombre.
- Ouvrez ViewController.swift.
- Ajoutez les lignes de code suivantes juste avant d'ajouter le bouton de connexion à la vue dans la fonction
viewDidLoad:
// Set the width and color of the sign-in button
signInButton.style = .standard // Options: .standard, .wide, .iconOnly
signInButton.colorScheme = .dark // Options: .dark, .light

Pour en savoir plus sur la personnalisation, consultez la documentation de référence du framework GoogleSignIn.
7. Gérer l'URL de redirection de l'authentification
Une fois le bouton de connexion ajouté, l'étape suivante consiste à gérer la redirection qui se produit après l'authentification d'un utilisateur. Après l'authentification, Google renvoie une URL avec un code d'autorisation temporaire. Pour finaliser le processus de connexion, un gestionnaire intercepte cette URL et la transmet au SDK Se connecter avec Google afin qu'elle soit échangée contre un jeton d'identité signé (JWT).
SwiftUI
- Ouvrez le fichier contenant votre struct
App. Le nom de ce fichier est basé sur votre projet. Il se présente donc sous la forme YourProjectNameApp.swift. - Remplacez le contenu de ce fichier par le texte suivant :
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
- Ouvrez AppDelegate.swift.
- Ajoutez l'importation suivante en haut du fichier :
import GoogleSignIn
- Ajoutez la fonction de gestionnaire d'authentification suivante dans la classe
AppDelegate. Il est conseillé de la placer juste après l'accolade fermante de la méthodeapplication(_: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
}
Une fois ces modifications effectuées, votre fichier AppDelegate.swift devrait se présenter comme suit :
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.
}
}
Tester le flux de connexion
Vous pouvez maintenant tester le flux de connexion complet.
Exécutez votre application et appuyez sur le bouton de connexion. Une fois que vous vous êtes authentifié, Google affiche un écran de consentement sur lequel vous pouvez autoriser l'application à accéder à vos informations. Une fois que vous avez approuvé la connexion, elle est finalisée et vous êtes redirigé vers l'application.
Une fois le flux de connexion terminé, le SDK Se connecter avec Google stocke de manière sécurisée les identifiants de l'utilisateur dans le trousseau de clés de l'appareil. Ces identifiants peuvent être utilisés ultérieurement pour permettre à un utilisateur de rester connecté lors des prochains lancements de l'application.
8. Ajouter un bouton de déconnexion
Maintenant que la connexion fonctionne, l'étape suivante consiste à ajouter un bouton de déconnexion et à mettre à jour l'UI pour refléter l'état de connexion actuel de l'utilisateur. Lorsqu'une connexion réussit, le SDK fournit un objet GIDGoogleUser. Cet objet contient une propriété profile avec des informations de base telles que le nom et l'adresse e-mail de l'utilisateur, que vous utiliserez pour personnaliser l'UI.
SwiftUI
- Ouvrez votre fichier ContentView.swift.
- Ajoutez une variable d'état en haut de votre struct
ContentView. Cette variable contiendra les informations de l'utilisateur après sa connexion. Comme il s'agit d'une variable@State, SwiftUI mettra automatiquement à jour votre UI chaque fois que sa valeur changera :
struct ContentView: View {
@State private var user: GIDGoogleUser?
}
- Remplacez le
bodyactuel de votre structContentViewpar leVStacksuivant. Cela permet de vérifier si la variable d'étatusercontient un utilisateur. Si c'est le cas, un message de bienvenue et un bouton de déconnexion s'affichent. Si ce n'est pas le cas, le bouton "Se connecter avec Google" d'origine s'affiche :
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()
}
}
}
- Mettez à jour le bloc d'achèvement
handleSignInButtonpour attribuersignInResult.userà votre nouvelle variableuser. Voici ce qui déclenche le passage de l'UI à la vue connectée :
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 ?? "")")
}
}
- Ajoutez une fonction
signOuten bas de votre structureContentView, qui sera appelée par votre bouton de déconnexion :
func signOut() {
GIDSignIn.sharedInstance.signOut()
// After signing out, set the `user` state variable to `nil`.
self.user = nil
}
Lancez l'application et connectez-vous. L'interface utilisateur devrait changer une fois l'authentification réussie.

Une fois ces modifications effectuées, votre fichier ContentView.swift doit se présenter comme suit :
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
- Ouvrez ViewController.swift.
- En haut de
ViewController, juste en dessous de l'endroit où vous avez déclarésignInButton, ajoutez un bouton de déconnexion et un libellé d'accueil :
let signOutButton = UIButton(type: .system)
let welcomeLabel = UILabel()
- Ajoutez la fonction suivante au bas de
ViewController. Cette fonction affichera une interface utilisateur différente en fonction de l'état de connexion de l'utilisateur :
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
}
}
- En bas de la fonction
viewDidLoad, ajoutez le code suivant pour ajouter le libellé d'accueil et le bouton de déconnexion à la vue :
// --- 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)
- Mettez à jour la fonction
signInButtonTappedpour appeler la méthodeUpdateUIen cas de connexion réussie :
@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)
}
}
}
- Enfin, ajoutez une fonction
signOutButtonTappedàViewControllerpour gérer le processus de déconnexion :
@objc func signOutButtonTapped() {
GIDSignIn.sharedInstance.signOut()
// Update the UI for the signed-out state.
updateUI(for: nil)
}
Lancez l'application et connectez-vous. L'interface utilisateur devrait changer une fois l'authentification réussie.

Une fois ces modifications effectuées, votre fichier ViewController.swift doit se présenter comme suit :
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. Restaurer l'état de connexion d'un utilisateur
Pour améliorer l'expérience des utilisateurs qui reviennent, l'étape suivante consiste à restaurer leur état de connexion au lancement de l'application. L'appel de restorePreviousSignIn utilise les identifiants enregistrés dans le trousseau pour reconnecter silencieusement l'utilisateur, ce qui lui évite de devoir effectuer la procédure de connexion à chaque fois.
SwiftUI
- Ouvrez ContentView.swift.
- Ajoutez le code suivant directement après
VStackdans la variablebody:
.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 ?? "")")
}
}
}
Votre fichier ContentView.swift devrait se présenter comme suit :
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
- Ouvrez ViewController.swift.
- Ajoutez l'appel
restorePreviousSignInsuivant à la fin de la méthodeviewDidLoad:
// 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)
}
}
}
Votre fichier ViewController.swift devrait se présenter comme suit :
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)
}
}
Tester la connexion silencieuse
Une fois connecté, quittez complètement l'application et relancez-la. Vous devriez voir que vous êtes maintenant connecté automatiquement, sans avoir besoin d'appuyer sur le bouton.
10. Comprendre le jeton d'identité
Bien que l'objet GIDGoogleUser soit pratique pour personnaliser l'UI à l'aide du nom et de l'adresse e-mail de l'utilisateur, le jeton d'identité est la donnée la plus importante renvoyée par le SDK.
Cet atelier de programmation utilise un outil en ligne pour inspecter le contenu du jeton JWT. Dans une application de production, vous devez envoyer ce jeton d'identité à votre serveur backend. Votre serveur doit vérifier l'intégrité du jeton d'identification et utiliser le JWT pour effectuer une action plus significative, comme créer un compte sur votre plate-forme backend ou établir une nouvelle session pour l'utilisateur.
Accéder au jeton JWT et le décoder
- Lancez votre application.
- Ouvrez la console Xcode. Un jeton d'identité doit s'afficher. Elle doit ressembler à ceci :
eyJhbGciOiJSUzI1Ni ... Hecz6Wm4Q. - Copiez le jeton d'identité et utilisez un outil en ligne tel que jwt.io pour décoder le jeton JWT.
Le jeton JWT décodé se présente comme suit :
{
"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
}
Champs de jetons notables
Le jeton d'identité décodé contient des champs ayant des objectifs différents. Certaines sont faciles à comprendre, comme le nom et l'adresse e-mail, tandis que d'autres sont utilisées par votre serveur backend pour la validation.
Le champ suivant est particulièrement important à comprendre :
- sub : le champ
subest un identifiant unique et permanent pour le compte Google de l'utilisateur. Un utilisateur peut modifier son adresse e-mail principale ou son nom, mais son IDsubne changera jamais. Le champsubest donc la valeur idéale à utiliser comme clé primaire pour vos comptes utilisateur de backend.
Obtenir des informations sur l'utilisateur à partir du jeton d'identité fournit plus d'informations sur la signification de tous les champs du jeton.
11. Sécuriser votre application avec App Check
Nous vous recommandons vivement d'activer App Check pour vous assurer que seule votre application peut accéder aux points de terminaison OAuth 2.0 de Google au nom de votre projet. App Check fonctionne en vérifiant que les requêtes envoyées à vos services de backend proviennent bien de votre application authentique sur un appareil réel et non modifié.
Cette section explique comment intégrer App Check à votre application et le configurer pour le débogage dans un simulateur et pour une version de production exécutée sur un appareil réel.
Configuration de la console
L'intégration d'App Check à votre application nécessite une configuration unique dans les consoles Google Cloud et Firebase. Pour ce faire, vous devez activer App Check pour votre client OAuth iOS dans la console Google Cloud, créer une clé API à utiliser avec le fournisseur de débogage App Check et associer votre projet Google Cloud à Firebase.
Activer App Check dans la console Google Cloud
- Accédez à la liste des clients associés à votre projet Google Cloud.
- Sélectionnez l'ID client OAuth 2.0 que vous avez créé pour votre application iOS.
- Activez App Check sous Identité Google pour iOS.

- Cliquez sur Enregistrer.
Créer une clé API
- Accédez à la page Bibliothèque d'API de votre projet Google Cloud.
- Saisissez API Firebase App Check dans la barre de recherche.

- Sélectionnez et activez l'API Firebase App Check.
- Accédez à API et services, puis sélectionnez Identifiants dans le menu de navigation.
- Sélectionnez Créer des identifiants en haut de la page.

- Attribuez un nom à cette clé API.
- Sélectionnez "Applications iOS" sous Restrictions liées aux applications.
- Ajoutez l'identifiant du bundle de votre application en tant qu'application approuvée.
- Sélectionnez Restreindre la clé sous Restrictions relatives aux API.
- Sélectionnez API Firebase App Check dans le menu déroulant.
- Sélectionnez Créer.

- Copiez la clé API créée. Vous en aurez besoin dans l'une des prochaines étapes.
Ajouter Firebase à votre projet Google Cloud
- Accédez à la console Firebase.
- Sélectionnez Commencer par configurer un projet Firebase.
- Sélectionnez Ajouter Firebase à un projet Google Cloud.

- Sélectionnez un projet Google Cloud dans le menu déroulant et poursuivez la procédure d'inscription.
- Sélectionnez Ajouter Firebase.
- Une fois votre projet Firebase prêt, sélectionnez Continuer pour l'ouvrir.
Intégration du code côté client
Maintenant que le projet Google Cloud est configuré pour App Check, il est temps d'écrire le code côté client pour l'activer. Le fournisseur utilisé pour l'attestation est différent dans les environnements de production et de débogage. Une application de production sur un appareil réel utilise le service App Attest intégré d'Apple pour prouver son authenticité. Toutefois, comme le simulateur iOS ne peut pas fournir ce type d'attestation, l'environnement de débogage nécessite un fournisseur de débogage spécial auquel est transmise une clé API.
Le code suivant gère les deux scénarios en utilisant une directive de compilation pour sélectionner automatiquement le bon fournisseur au moment de la compilation.
SwiftUI
- Ouvrez le fichier d'application principal.
- Définissez la classe
AppDelegatesuivante après les importations et avant l'attribut@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
}
}
- Remplacez
"YOUR_API_KEY"dans le code fourni par la clé API que vous avez copiée depuis la console Google Cloud. - Ajoutez la ligne suivante dans votre struct
App, juste avant la variablebody. Cela enregistre votre classe AppDelegate auprès du cycle de vie de l'application, ce qui lui permet de répondre au lancement de l'application et à d'autres événements système :
@UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
Votre fichier d'application principal devrait se présenter comme suit :
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
- Ouvrez AppDelegate.swift.
- Mettez à jour la méthode
application(_:didFinishLaunchingWithOptions:)pour qu'elle contienne l'initialisation d'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
}
- Remplacez
"YOUR_API_KEY"dans le code fourni par la clé API que vous avez copiée depuis la console Google Cloud.
Votre fichier AppDelegate.swift devrait se présenter comme suit :
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.
}
}
Tester App Check sur le simulateur
- Dans la barre de menu Xcode, accédez à Product > Scheme > Edit Scheme (Produit > Schéma > Modifier le schéma).
- Sélectionnez Exécuter dans le menu de navigation.
- Sélectionnez l'onglet Arguments.
- Dans la section Arguments Passed on Launch (Arguments transmis au lancement), sélectionnez + et ajoutez -FIRDebugEnabled. Cet argument de lancement active la journalisation de débogage Firebase.
- Cliquez sur Fermer.

- Lancez votre application sur le simulateur.
- Copiez le jeton de débogage App Check qui s'affiche dans la console Xcode.

- Accédez à votre projet dans la console Firebase.
- Développez la section Build (Compiler) dans le menu de navigation.
- Sélectionnez App Check.
- Sélectionnez l'onglet Applications.
- Pointez sur votre application, puis sélectionnez l'icône du menu à trois points.

- Sélectionnez Gérer les jetons de débogage.
- Sélectionnez Ajouter un jeton de débogage.
- Attribuez un nom à votre jeton de débogage, puis collez le jeton de débogage que vous avez copié précédemment pour la valeur.
- Sélectionnez Enregistrer pour enregistrer votre jeton.

- Revenez au simulateur et connectez-vous.
L'affichage des métriques dans la console peut prendre plusieurs minutes. Une fois que ce sera fait, vous pourrez vérifier que App Check fonctionne en recherchant une augmentation des requêtes Validées à l'un des deux endroits suivants :
- Dans la section "App Check" de la console Firebase, sous l'onglet "API".

- Sur la page de modification de votre client OAuth dans la console Google Cloud.

Après avoir surveillé les métriques App Check de votre application et confirmé que les requêtes légitimes sont validées, vous devez activer l'application App Check. Une fois appliquée, App Check refuse toutes les requêtes non validées, ce qui garantit que seul le trafic provenant de votre application authentique peut accéder aux points de terminaison OAuth 2.0 de Google au nom de votre projet.
12. Ressources supplémentaires
Félicitations !
Vous avez configuré un client OAuth 2.0 iOS, ajouté un bouton "Se connecter avec Google" à une application iOS, appris à personnaliser l'apparence du bouton, décodé un jeton d'identité JWT et activé App Check pour votre application.
Les liens suivants peuvent vous aider à passer à l'étape suivante :
- Premiers pas avec Google Sign-In pour iOS
- Dépôt Google Sign-In pour iOS
- Valider un jeton d'ID Google
- Premiers pas avec App Check pour Google Sign-In sur iOS
- Révoquer les jetons d'accès et déconnecter l'application
- En savoir plus sur les projets Google Cloud
- Méthodes d'authentification Google Identity
- Activer l'application App Check