iOS অ্যাপে "Google দিয়ে সাইন ইন করুন" যোগ করুন

১. শুরু করার আগে

এই কোডল্যাবটি আপনাকে এমন একটি iOS অ্যাপ্লিকেশন তৈরি করতে সাহায্য করবে, যা ‘সাইন ইন উইথ গুগল’ সুবিধাটি বাস্তবায়ন করে এবং সিমুলেটরে চলে। SwiftUI এবং UIKit উভয় ব্যবহার করে এর বাস্তবায়ন দেখানো হয়েছে।

SwiftUI হলো নতুন অ্যাপ তৈরির জন্য অ্যাপলের একটি আধুনিক UI ফ্রেমওয়ার্ক। এটি একটিমাত্র শেয়ার্ড কোডবেস থেকে অ্যাপলের সকল প্ল্যাটফর্মের জন্য ইউজার ইন্টারফেস তৈরি করতে সক্ষম করে। এর জন্য ন্যূনতম iOS 13 সংস্করণ প্রয়োজন।

UIKit হলো iOS-এর জন্য অ্যাপলের মূল এবং ভিত্তিগত UI ফ্রেমওয়ার্ক। এটি iOS-এর পুরোনো সংস্করণগুলোর জন্য ব্যাকওয়ার্ড কম্প্যাটিবিলিটি প্রদান করে। এই কারণে, প্রতিষ্ঠিত অ্যাপগুলোর জন্য এটি একটি ভালো পছন্দ, যেগুলোকে বিভিন্ন পুরোনো ডিভাইস সাপোর্ট করার প্রয়োজন হয়।

আপনি এমন একটি ফ্রেমওয়ার্কের পথ অনুসরণ করতে পারেন যা আপনার উন্নয়নের চাহিদার সাথে সবচেয়ে ভালোভাবে সামঞ্জস্যপূর্ণ।

পূর্বশর্ত

  • সুইফট সম্পর্কে প্রাথমিক জ্ঞান
  • SwiftUI বা UIKit সম্পর্কে প্রাথমিক জ্ঞান

আপনি যা শিখবেন

  • কীভাবে একটি গুগল ক্লাউড প্রজেক্ট তৈরি করবেন
  • গুগল ক্লাউড কনসোলে কীভাবে OAuth ক্লায়েন্ট তৈরি করবেন
  • আপনার iOS অ্যাপে কীভাবে গুগল দিয়ে সাইন ইন চালু করবেন
  • কীভাবে গুগল দিয়ে সাইন ইন বাটনটি কাস্টমাইজ করবেন
  • একটি আইডি টোকেন কীভাবে ডিকোড করবেন
  • আপনার iOS অ্যাপের জন্য অ্যাপ চেক কীভাবে চালু করবেন

আপনার যা যা লাগবে

  • Xcode- এর একটি বর্তমান সংস্করণ
  • ম্যাকওএস চালিত এমন একটি কম্পিউটার যা আপনার ইনস্টল করা এক্সকোড সংস্করণের জন্য সিস্টেমের প্রয়োজনীয়তা পূরণ করে।

এই কোডল্যাবটি Xcode 16.3 এবং iOS 18.3 সিমুলেটর ব্যবহার করে তৈরি করা হয়েছে। ডেভেলপমেন্টের জন্য আপনার Xcode-এর সর্বশেষ সংস্করণ ব্যবহার করা উচিত।

২. একটি নতুন Xcode প্রজেক্ট তৈরি করুন

  1. Xcode খুলুন এবং 'Create a new Xcode project' নির্বাচন করুন।
  2. iOS ট্যাবটি বেছে নিন, অ্যাপ টেমপ্লেটটি নির্বাচন করুন এবং Next-এ ক্লিক করুন।

এক্সকোড প্রজেক্ট তৈরির টেমপ্লেট পৃষ্ঠা

  1. প্রকল্পের বিকল্পগুলিতে:
    • আপনার পণ্যের নাম লিখুন।
    • ঐচ্ছিকভাবে আপনার দল নির্বাচন করুন।
    • আপনার প্রতিষ্ঠানের শনাক্তকারী নম্বরটি প্রবেশ করান।
    • তৈরি হওয়া বান্ডেল আইডেন্টিফায়ারটি লিখে রাখুন। পরবর্তীতে আপনার এটি প্রয়োজন হবে।
    • ইন্টারফেসের জন্য, নিম্নলিখিতগুলির মধ্যে যেকোনো একটি বেছে নিন:
      • SwiftUI-ভিত্তিক অ্যাপের জন্য SwiftUI
      • UIKit-ভিত্তিক অ্যাপের জন্য স্টোরিবোর্ড
    • ভাষা হিসেবে সুইফট বেছে নিন।
    • পরবর্তী ধাপে যান এবং আপনার প্রজেক্টটি সংরক্ষণ করার জন্য একটি স্থান বেছে নিন।

Xcode প্রজেক্ট অপশন পেজ

৩. একটি OAuth ক্লায়েন্ট তৈরি করুন

আপনার অ্যাপকে গুগলের অথেনটিকেশন সার্ভিসের সাথে যোগাযোগ করার অনুমতি দিতে, আপনাকে একটি OAuth ক্লায়েন্ট আইডি তৈরি করতে হবে। এর জন্য একটি গুগল ক্লাউড প্রজেক্ট প্রয়োজন। নিম্নলিখিত ধাপগুলো আপনাকে একটি প্রজেক্ট এবং একটি OAuth ক্লায়েন্ট আইডি তৈরির প্রক্রিয়াটি ধাপে ধাপে দেখিয়ে দেবে।

একটি গুগল ক্লাউড প্রজেক্ট নির্বাচন করুন বা তৈরি করুন

  1. গুগল ক্লাউড কনসোলে যান এবং একটি প্রজেক্ট নির্বাচন করুন বা তৈরি করুন। আপনি যদি আগে থেকে বিদ্যমান কোনো প্রজেক্ট নির্বাচন করেন, তাহলে কনসোলটি স্বয়ংক্রিয়ভাবে আপনাকে পরবর্তী প্রয়োজনীয় ধাপে নিয়ে যাবে।

গুগল ক্লাউড কনসোল প্রজেক্ট সিলেক্টর পৃষ্ঠা

  1. আপনার নতুন গুগল ক্লাউড প্রজেক্টের জন্য একটি নাম দিন।
  2. তৈরি করুন নির্বাচন করুন।

গুগল ক্লাউড কনসোল প্রজেক্ট সিলেক্টর পৃষ্ঠা

আপনি যদি নির্বাচিত প্রজেক্টের জন্য ইতিমধ্যেই একটি কনসেন্ট স্ক্রিন কনফিগার করে থাকেন, তাহলে আপনাকে এখন এটি কনফিগার করার জন্য অনুরোধ করা হবে না। সেক্ষেত্রে, আপনি এই অংশটি এড়িয়ে যেতে পারেন এবং 'Create an OAuth 2.0 client' অংশে চলে যেতে পারেন।

  1. সম্মতি স্ক্রিন কনফিগার করুন নির্বাচন করুন।

গুগল ক্লাউড কনসোলে সম্মতি স্ক্রিন কনফিগার করার প্রয়োজনীয়তা সহ OAuth ক্লায়েন্ট পৃষ্ঠা তৈরি করুন।

  1. ব্র্যান্ডিং পেজে ' Get started' নির্বাচন করুন।

গুগল ক্লাউড কনসোল ব্র্যান্ডিং শুরু করার পৃষ্ঠা

  1. প্রজেক্ট কনফিগারেশন পেজে নিম্নলিখিত ফিল্ডগুলি পূরণ করুন:
    • অ্যাপের তথ্য : আপনার অ্যাপের জন্য একটি নাম এবং একটি ব্যবহারকারী সহায়তা ইমেল দিন। এই সহায়তা ইমেলটি সর্বজনীনভাবে প্রদর্শিত হবে, যাতে ব্যবহারকারীরা তাদের সম্মতি সংক্রান্ত প্রশ্ন নিয়ে আপনার সাথে যোগাযোগ করতে পারেন।
    • দর্শক : বাহ্যিক নির্বাচন করুন।
    • যোগাযোগের তথ্য : আপনার প্রকল্প সম্পর্কে গুগল যাতে আপনার সাথে যোগাযোগ করতে পারে, তার জন্য একটি ইমেল ঠিকানা লিখুন।
    • গুগল এপিআই পরিষেবা: ব্যবহারকারীর ডেটা নীতি পর্যালোচনা করুন।
    • তৈরি করুন- এ ক্লিক করুন।

গুগল ক্লাউড কনসোল ক্লায়েন্ট ব্র্যান্ডিং কনফিগারেশন পৃষ্ঠা

  1. ন্যাভিগেশন মেনু থেকে ক্লায়েন্ট পৃষ্ঠাটি নির্বাচন করুন।
  2. ক্লায়েন্ট তৈরি করুন -এ ক্লিক করুন।

গুগল ক্লাউড প্রজেক্ট ক্লায়েন্ট পেজ

একটি OAuth 2.0 ক্লায়েন্ট তৈরি করুন

  1. অ্যাপ্লিকেশনের ধরন হিসেবে iOS নির্বাচন করুন।
  2. আপনার ক্লায়েন্টের জন্য একটি নাম লিখুন।
  3. শেষ ধাপে তৈরি করা বান্ডেল আইডেন্টিফায়ারটি প্রবেশ করান।
  4. Apple কর্তৃক আপনার টিমকে বরাদ্দ করা টিম আইডিটি প্রবেশ করান। এই ধাপটি আপাতত ঐচ্ছিক, কিন্তু এই কোডল্যাবের পরবর্তী অংশে অ্যাপ চেক (App Check) চালু করার জন্য একটি টিম আইডি প্রয়োজন হবে।
  5. তৈরি করুন নির্বাচন করুন।

OAuth ক্লায়েন্টের বিবরণ ইনপুট পৃষ্ঠা

  1. ডায়ালগ উইন্ডো থেকে ক্লায়েন্ট আইডিটি কপি করুন, পরবর্তীতে আপনার এটি প্রয়োজন হবে।
  2. পরবর্তীতে ব্যবহারের জন্য plist ফাইলটি ডাউনলোড করুন।

OAuth ক্লায়েন্ট আইডি তৈরি ডায়ালগ

৪. আপনার Xcode প্রজেক্ট কনফিগার করুন

পরবর্তী ধাপ হলো ‘সাইন ইন উইথ গুগল এসডিকে’-এর সাথে কাজ করার জন্য আপনার এক্সকোড প্রজেক্ট সেট আপ করা। এই প্রক্রিয়ার জন্য এসডিকে-টিকে আপনার প্রজেক্টে একটি ডিপেন্ডেন্সি হিসেবে যুক্ত করতে হবে এবং একটি অনন্য ক্লায়েন্ট আইডি দিয়ে আপনার প্রজেক্ট সেটিংস কনফিগার করতে হবে। এই আইডিটি সাইন-ইন প্রক্রিয়ার সময় এসডিকে-কে গুগলের অথেনটিকেশন সার্ভিসের সাথে নিরাপদে যোগাযোগ করতে সাহায্য করে।

গুগল দিয়ে সাইন ইন করার নির্ভরতাগুলি ইনস্টল করুন

  1. আপনার Xcode প্রজেক্টটি খুলুন।
  2. ফাইল > প্যাকেজ নির্ভরতা যোগ করুন -এ যান।
  3. সার্চ বারে, 'Sign in with Google' রিপোজিটরির URL-টি লিখুন: https://github.com/google/GoogleSignIn-iOS

সুইফট প্যাকেজ ম্যানেজারে 'সাইন ইন উইথ গুগল' নির্ভরতা খুঁজুন

  1. প্যাকেজ যোগ করুন নির্বাচন করুন।
  2. GoogleSignIn প্যাকেজের জন্য মূল অ্যাপ্লিকেশন টার্গেট নির্বাচন করুন।
  3. আপনি যদি SwiftUI ব্যবহার করেন, তাহলে GoogleSignInSwift প্যাকেজের জন্য মূল অ্যাপ্লিকেশন টার্গেটটি নির্বাচন করুন। আপনি যদি UIKit ব্যবহার করার পরিকল্পনা করেন, তাহলে এই প্যাকেজের জন্য কোনো টার্গেট নির্বাচন করবেন না।
  4. প্যাকেজ যোগ করুন নির্বাচন করুন।

আপনার প্রজেক্টে 'গুগল দিয়ে সাইন ইন' ডিপেন্ডেন্সি যোগ করুন।

আপনার অ্যাপের ক্রেডেনশিয়াল কনফিগার করুন।

  1. প্রজেক্ট নেভিগেটরে, আপনার প্রজেক্টের রুটে ক্লিক করুন।
  2. মূল এডিটর অংশে, টার্গেটস (TARGETS) তালিকা থেকে আপনার মূল অ্যাপ্লিকেশন টার্গেটটি নির্বাচন করুন।
  3. এডিটর এলাকার শীর্ষে থাকা তথ্য ট্যাবটি নির্বাচন করুন।
  4. কাস্টম আইওএস টার্গেট প্রোপার্টিজ সেকশনের শেষ সারির উপর মাউস রাখুন এবং প্রদর্শিত + বোতামটিতে ক্লিক করুন।

iOS টার্গেট প্রোপার্টিতে একটি নতুন টার্গেট কী যোগ করুন

  1. Key কলামে GIDClientID টাইপ করুন।
  2. 'Value' কলামে, গুগল ক্লাউড কনসোল থেকে কপি করা ক্লায়েন্ট আইডিটি পেস্ট করুন।

মূল অ্যাপ টার্গেটে GIDClientID যোগ করুন

  1. গুগল ক্লাউড কনসোল থেকে ডাউনলোড করা plist ফাইলটি খুলুন।
  2. রিভার্সড ক্লায়েন্ট আইডি- এর মানটি কপি করুন।

গুগল ক্লাউড কনসোল প্লিস্ট ফাইল

  1. Info ট্যাবের একেবারে নিচে থাকা URL Types অংশটি প্রসারিত করুন।
  2. + বোতামটি নির্বাচন করুন।
  3. URL Schemes বক্সে রিভার্সড ক্লায়েন্ট আইডিটি প্রবেশ করান।

মূল অ্যাপ্লিকেশন টার্গেটে URLSchemes কী যোগ করুন

এখন আমরা আমাদের অ্যাপে সাইন-ইন বাটন যোগ করার জন্য প্রস্তুত!

৫. সাইন-ইন বাটন যোগ করুন

Xcode প্রজেক্টটি কনফিগার করা হয়ে গেলে, এবার অ্যাপটিতে ‘Sign in with Google’ বাটনটি যোগ করার পালা!

এই ধাপের মূল লজিকটি হলো GIDSignIn.sharedInstance.signIn কে কল করা। এই মেথডটি অথেনটিকেশন প্রক্রিয়া শুরু করে এবং ব্যবহারকারীর কাছে 'সাইন ইন উইথ গুগল' ফ্লোটি উপস্থাপন করার জন্য 'সাইন ইন উইথ গুগল' SDK-এর কাছে নিয়ন্ত্রণ হস্তান্তর করে।

SwiftUI

  1. এক্সকোড প্রজেক্ট নেভিগেটরে ContentView.swift ফাইলটি খুঁজুন।
  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()
}

iOS সিমুলেটরে SwiftUI ফ্রেমওয়ার্কের 'Sign in with Google' বাটন

UIKit

  1. এক্সকোড প্রজেক্ট নেভিগেটরে ViewController.swift ফাইলটি খুঁজুন।
  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 ?? "")")
    }
  }
}

iOS সিমুলেটরে UIKit ফ্রেমওয়ার্কের 'Sign in with Google' বাটন

সাইন-ইন বোতামটি দেখুন

সিমুলেটরে আপনার অ্যাপটি চালু করুন। আপনি ‘Sign in with Google’ বাটনটি দেখতে পাবেন, কিন্তু এটি এখনই ঠিকমতো কাজ করবে না। এটি স্বাভাবিক, কারণ ব্যবহারকারী প্রমাণীকরণের পর তাকে আপনার অ্যাপে ফিরিয়ে আনার জন্য প্রয়োজনীয় কোডটি আপনাকে এখনও যুক্ত করতে হবে।

৬. সাইন-ইন বাটনটি কাস্টমাইজ করুন

আপনার অ্যাপের থিমের সাথে আরও ভালোভাবে মানিয়ে নেওয়ার জন্য আপনি ডিফল্ট 'সাইন-ইন উইথ গুগল' বাটনটি কাস্টমাইজ করতে পারেন। 'সাইন-ইন উইথ গুগল' এসডিকে আপনাকে বাটনটির কালার স্কিম এবং স্টাইল পরিবর্তন করার সুযোগ দেয়।

SwiftUI

এই কোড লাইনটির মাধ্যমে পেজে ডিফল্ট বাটনটি যোগ করা হয়:

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 ফ্রেমওয়ার্ক রেফারেন্স দেখুন।

UIKit

ডিফল্ট বাটনটি এই কোড লাইনগুলো দিয়ে তৈরি করা হয়:

// 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. viewDidLoad ফাংশনে, ভিউতে সাইন-ইন বাটন যোগ করার ঠিক আগে নিম্নলিখিত কোড লাইনগুলো যোগ করুন:
// Set the width and color of the sign-in button
signInButton.style = .standard  // Options: .standard, .wide, .iconOnly
signInButton.colorScheme = .dark  // Options: .dark, .light

iOS সিমুলেটরে UIKit ফ্রেমওয়ার্কের ডার্ক মোড এবং গুগল দিয়ে সাইন ইন করার বাটন।

কাস্টমাইজেশন সম্পর্কে আরও তথ্যের জন্য GoogleSignIn ফ্রেমওয়ার্ক রেফারেন্স দেখুন।

৭. প্রমাণীকরণ পুনঃনির্দেশ URL পরিচালনা করুন

সাইন-ইন বাটনটি যুক্ত করার পর, পরবর্তী ধাপ হলো ব্যবহারকারীর প্রমাণীকরণের পরে যে রিডাইরেক্ট হয়, তা পরিচালনা করা। প্রমাণীকরণের পরে, গুগল একটি অস্থায়ী অনুমোদন কোডসহ একটি ইউআরএল ফেরত দেয়। সাইন-ইন প্রক্রিয়াটি সম্পূর্ণ করতে, একটি হ্যান্ডলার এই ইউআরএলটি গ্রহণ করে এবং একটি স্বাক্ষরিত আইডি টোকেন (JWT)-এর বিনিময়ের জন্য এটিকে 'সাইন ইন উইথ গুগল এসডিকে'-তে পাঠিয়ে দেয়।

SwiftUI

  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)
        }
    }
  }
}

UIKit

  1. AppDelegate.swift খুলুন।
  2. ফাইলের শীর্ষে নিম্নলিখিত ইম্পোর্টটি যোগ করুন:
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.
  }
}

সাইন-ইন প্রবাহ পরীক্ষা করুন

আপনি এখন সম্পূর্ণ সাইন-ইন প্রক্রিয়াটি পরীক্ষা করতে পারেন!

আপনার অ্যাপটি চালু করুন এবং সাইন-ইন বোতামে ট্যাপ করুন। আপনার প্রমাণীকরণের পর, গুগল একটি সম্মতি স্ক্রিন দেখাবে যেখানে আপনি অ্যাপটিকে আপনার তথ্য অ্যাক্সেস করার অনুমতি দিতে পারবেন। আপনি অনুমোদন করলেই সাইন-ইন প্রক্রিয়াটি চূড়ান্ত হবে এবং আপনাকে অ্যাপে ফিরিয়ে আনা হবে।

যখন সাইন-ইন প্রক্রিয়াটি সফলভাবে সম্পন্ন হয়, তখন ‘সাইন ইন উইথ গুগল এসডিকে’ ব্যবহারকারীর ক্রেডেনশিয়ালগুলো ডিভাইসের কীচেইনে নিরাপদে সংরক্ষণ করে। পরবর্তীতে অ্যাপটি চালু করার সময় ব্যবহারকারীকে সাইন-ইন করা অবস্থায় রাখার জন্য এই ক্রেডেনশিয়ালগুলো ব্যবহার করা যেতে পারে।

৮. একটি সাইন-আউট বাটন যোগ করুন

এখন যেহেতু সাইন-ইন কাজ করছে, পরবর্তী ধাপ হলো একটি সাইন-আউট বাটন যোগ করা এবং ব্যবহারকারীর বর্তমান সাইন-ইন অবস্থা অনুযায়ী UI আপডেট করা। সাইন-ইন সফল হলে, SDK একটি GIDGoogleUser অবজেক্ট প্রদান করে। এই অবজেক্টটিতে একটি profile প্রপার্টি থাকে, যেখানে ব্যবহারকারীর নাম এবং ইমেলের মতো মৌলিক তথ্য থাকে, যা আপনি UI ব্যক্তিগতকরণ করতে ব্যবহার করবেন।

SwiftUI

  1. আপনার ContentView.swift ফাইলটি খুলুন।
  2. আপনার ContentView struct-এর শুরুতে একটি স্টেট ভ্যারিয়েবল যোগ করুন। ব্যবহারকারী সাইন ইন করার পর এই ভ্যারিয়েবলটি তার তথ্য ধারণ করবে। যেহেতু এটি একটি @State ভ্যারিয়েবল, তাই এর মান পরিবর্তন হলেই SwiftUI স্বয়ংক্রিয়ভাবে আপনার UI আপডেট করে দেবে।
struct ContentView: View {
  @State private var user: GIDGoogleUser?
}
  1. আপনার ContentView struct-এর বর্তমান body নিম্নলিখিত VStack দিয়ে প্রতিস্থাপন করুন। এটি পরীক্ষা করবে যে user স্টেট ভেরিয়েবলটিতে কোনো ব্যবহারকারী আছে কিনা। যদি থাকে, তবে এটি একটি স্বাগত বার্তা এবং একটি সাইন-আউট বাটন দেখাবে। আর যদি না থাকে, তবে এটি আসল 'Sign in with 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()
    }
  }
}
  1. handleSignInButton কমপ্লিশন ব্লকটি আপডেট করে signInResult.user কে আপনার নতুন user ভেরিয়েবলে অ্যাসাইন করুন। এটিই UI-কে সাইন-ইন করা ভিউতে পরিবর্তন করতে ট্রিগার করে:
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. আপনার সাইন-আউট বাটন দ্বারা কল করার জন্য, আপনার ContentView struct-এর শেষে একটি নতুন signOut ফাংশন যোগ করুন:
func signOut() {
  GIDSignIn.sharedInstance.signOut()
  // After signing out, set the `user` state variable to `nil`.
  self.user = nil
}

অ্যাপটি চালু করুন এবং সাইন ইন করুন। সফলভাবে প্রমাণীকরণের পর আপনি ইউজার ইন্টারফেসে (UI) পরিবর্তন দেখতে পাবেন!

iOS সিমুলেটরে SwiftUI ফ্রেমওয়ার্কের সাইন-ইন করা অবস্থা

এই পরিবর্তনগুলো করার পর, আপনার 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

  1. ViewController.swift খুলুন।
  2. ViewController এর একদম উপরে, যেখানে আপনি signInButton ডিক্লেয়ার করেছেন তার ঠিক নিচে, একটি সাইন-আউট বাটন এবং একটি ওয়েলকাম লেবেল যোগ করুন:
let signOutButton = UIButton(type: .system)
let welcomeLabel = UILabel()
  1. ViewController এর শেষে নিম্নলিখিত ফাংশনটি যোগ করুন। এই ফাংশনটি ব্যবহারকারীর সাইন-ইন স্ট্যাটাসের উপর ভিত্তি করে তাকে ভিন্ন ভিন্ন UI দেখাবে:
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. সফল সাইন-ইন হলে UpdateUI মেথডটি কল করার জন্য signInButtonTapped ফাংশনটি আপডেট করুন:
@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. অবশেষে, সাইন-আউট প্রক্রিয়াটি পরিচালনা করার জন্য ViewController এ একটি signOutButtonTapped ফাংশন যোগ করুন:
@objc func signOutButtonTapped() {
  GIDSignIn.sharedInstance.signOut()
  // Update the UI for the signed-out state.
  updateUI(for: nil)
}

অ্যাপটি চালু করুন এবং সাইন ইন করুন। সফলভাবে প্রমাণীকরণের পর আপনি ইউজার ইন্টারফেসে (UI) পরিবর্তন দেখতে পাবেন!

iOS সিমুলেটরে UIKit ফ্রেমওয়ার্কের সাইন-ইন করা অবস্থা

এই পরিবর্তনগুলো করার পর, আপনার 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-এ সংরক্ষিত ক্রেডেনশিয়াল ব্যবহার করে ব্যবহারকারীকে নীরবে পুনরায় সাইন-ইন করানো হয়, যা নিশ্চিত করে যে তাদের প্রতিবার সাইন-ইন প্রক্রিয়াটি সম্পূর্ণ করতে হবে না।

SwiftUI

  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()
}

UIKit

  1. ViewController.swift খুলুন।
  2. viewDidLoad মেথডের শেষে নিম্নলিখিত restorePreviousSignIn কলটি যোগ করুন:
// 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)
  }
}

সাইলেন্ট সাইন-ইন পরীক্ষা করুন

সাইন ইন করার পর, অ্যাপটি সম্পূর্ণভাবে বন্ধ করে আবার চালু করুন। আপনি দেখবেন যে, বাটনটি ট্যাপ না করেই আপনি এখন স্বয়ংক্রিয়ভাবে সাইন ইন হয়ে গেছেন।

১০. আইডি টোকেনটি বুঝুন।

যদিও ব্যবহারকারীর নাম এবং ইমেল ব্যবহার করে UI ব্যক্তিগতকরণের জন্য GIDGoogleUser অবজেক্টটি সুবিধাজনক, SDK থেকে ফেরত আসা সবচেয়ে গুরুত্বপূর্ণ ডেটা হলো আইডি টোকেন।

এই কোডল্যাবটি JWT-এর বিষয়বস্তু পরীক্ষা করার জন্য একটি অনলাইন টুল ব্যবহার করে। একটি প্রোডাকশন অ্যাপে, আপনার এই আইডি টোকেনটি আপনার ব্যাকএন্ড সার্ভারে পাঠানো উচিত। আপনার সার্ভারকে অবশ্যই আইডি টোকেনটির অখণ্ডতা যাচাই করতে হবে এবং JWT ব্যবহার করে আরও অর্থবহ কিছু করতে হবে, যেমন আপনার ব্যাকএন্ড প্ল্যাটফর্মে একটি নতুন অ্যাকাউন্ট তৈরি করা বা ব্যবহারকারীর জন্য একটি নতুন সেশন স্থাপন করা।

JWT টোকেন অ্যাক্সেস এবং ডিকোড করুন

  1. আপনার অ্যাপটি চালু করুন।
  2. Xcode কনসোলটি খুলুন। আপনি একটি প্রিন্ট করা আইডি টোকেন দেখতে পাবেন। এটি দেখতে eyJhbGciOiJSUzI1Ni ... Hecz6Wm4Q মতো হবে।
  3. আইডি টোকেনটি কপি করুন এবং JWT ডিকোড করার জন্য jwt.io-এর মতো কোনো অনলাইন টুল ব্যবহার করুন।

ডিকোড করা 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 আইডি কখনও পরিবর্তন হবে না। এই কারণে আপনার ব্যাকএন্ড ব্যবহারকারী অ্যাকাউন্টগুলোর জন্য প্রাইমারি কী হিসেবে sub ফিল্ডটি একটি আদর্শ ভ্যালু।

আইডি টোকেন থেকে ব্যবহারকারীর তথ্য সংগ্রহ করলে টোকেনের সমস্ত ফিল্ডের অর্থ সম্পর্কে আরও বিস্তারিত জানা যায়।

১১. অ্যাপ চেক দিয়ে আপনার অ্যাপ সুরক্ষিত করুন

আপনার প্রোজেক্টের পক্ষ থেকে শুধুমাত্র আপনার অ্যাপই যেন গুগলের OAuth 2.0 এন্ডপয়েন্টগুলো অ্যাক্সেস করতে পারে, তা নিশ্চিত করার জন্য অ্যাপ চেক (App Check) চালু করার জন্য জোরালোভাবে সুপারিশ করা হচ্ছে। অ্যাপ চেক এই বিষয়টি যাচাই করার মাধ্যমে কাজ করে যে, আপনার ব্যাকএন্ড সার্ভিসগুলোতে পাঠানো অনুরোধগুলো একটি আসল এবং অপরিবর্তিত ডিভাইসে থাকা আপনার প্রকৃত অ্যাপ থেকেই আসছে।

এই বিভাগে দেখানো হয়েছে কীভাবে আপনার অ্যাপে অ্যাপ চেক (App Check) একীভূত করতে হয় এবং সিমুলেটরে ডিবাগিং ও আসল ডিভাইসে প্রোডাকশন বিল্ড চালানোর জন্য এটিকে কনফিগার করতে হয়।

কনসোল সেটআপ

আপনার অ্যাপ্লিকেশনে অ্যাপ চেক যুক্ত করার জন্য গুগল ক্লাউড এবং ফায়ারবেস কনসোলে একবার সেটআপ করতে হবে। এর জন্য গুগল ক্লাউড কনসোলে আপনার iOS OAuth ক্লায়েন্টের জন্য অ্যাপ চেক সক্রিয় করতে হবে, অ্যাপ চেক ডিবাগ প্রোভাইডারের জন্য একটি এপিআই কী তৈরি করতে হবে এবং আপনার গুগল ক্লাউড প্রজেক্টকে ফায়ারবেসের সাথে লিঙ্ক করতে হবে।

গুগল ক্লাউড কনসোলে অ্যাপ চেক সক্ষম করুন

  1. আপনার গুগল ক্লাউড প্রজেক্টের সাথে যুক্ত ক্লায়েন্টদের তালিকায় যান।
  2. আপনার iOS অ্যাপের জন্য তৈরি করা OAuth 2.0 ক্লায়েন্ট আইডিটি নির্বাচন করুন।
  3. iOS-এর জন্য Google Identity-এর নিচে অ্যাপ চেক চালু করুন

অ্যাপ চেক টগল সহ OAuth ক্লায়েন্ট সম্পাদনা পৃষ্ঠা

  1. সংরক্ষণ করুন- এ ক্লিক করুন।

একটি এপিআই কী তৈরি করুন

  1. আপনার গুগল ক্লাউড প্রজেক্টের এপিআই লাইব্রেরি পৃষ্ঠায় যান।
  2. সার্চ বারে Firebase App Check API লিখুন।

গুগল ক্লাউড কনসোল এপিআই লাইব্রেরি পৃষ্ঠা

  1. Firebase App Check API-টি নির্বাচন করে সক্রিয় করুন।
  2. APIs & Services- এ যান এবং নেভিগেশন মেনু থেকে Credentials নির্বাচন করুন।
  3. পৃষ্ঠার শীর্ষে থাকা 'ক্রেডেনশিয়াল তৈরি করুন' নির্বাচন করুন।

গুগল ক্লাউড কনসোল এপিআই ক্রেডেনশিয়াল পৃষ্ঠা

  1. এই API Key-টির একটি নাম নির্ধারণ করুন।
  2. অ্যাপ্লিকেশন বিধিনিষেধের অধীনে iOS অ্যাপ নির্বাচন করুন।
  3. আপনার অ্যাপের বান্ডেল আইডেন্টিফায়ারটিকে একটি অনুমোদিত অ্যাপ্লিকেশন হিসেবে যুক্ত করুন।
  4. API বিধিনিষেধের অধীনে রেস্ট্রিক্ট কী নির্বাচন করুন।
  5. ড্রপ-ডাউন মেনু থেকে ফায়ারবেস অ্যাপ চেক এপিআই (Firebase App Check API) নির্বাচন করুন।
  6. তৈরি করুন নির্বাচন করুন।

গুগল ক্লাউড কনসোল এপিআই কী তৈরির পৃষ্ঠা

  1. তৈরি হওয়া API কী-টি কপি করে রাখুন। পরবর্তী ধাপে আপনার এটি প্রয়োজন হবে।

আপনার গুগল ক্লাউড প্রকল্পে ফায়ারবেস যুক্ত করুন

  1. ফায়ারবেস কনসোলে যান।
  2. একটি Firebase প্রজেক্ট সেট আপ করে শুরু করুন নির্বাচন করুন
  3. গুগল ক্লাউড প্রকল্পে ফায়ারবেস যোগ করুন নির্বাচন করুন।

একটি বিদ্যমান গুগল ক্লাউড প্রকল্পে ফায়ারবেস যুক্ত করুন

  1. ড্রপ-ডাউন থেকে একটি গুগল ক্লাউড প্রজেক্ট বেছে নিন এবং সাইন-আপ প্রক্রিয়াটি সম্পন্ন করুন।
  2. ফায়ারবেস যোগ করুন নির্বাচন করুন।
  3. আপনার Firebase প্রজেক্টটি প্রস্তুত হয়ে গেলে, প্রজেক্টটি খোলার জন্য 'Continue' নির্বাচন করুন।

ক্লায়েন্ট-সাইড কোড ইন্টিগ্রেশন

অ্যাপ চেকের জন্য গুগল ক্লাউড প্রজেক্টটি কনফিগার করা হয়ে গেলে, এটি চালু করার জন্য ক্লায়েন্ট-সাইড কোড লেখার সময় এসেছে। প্রোডাকশন এবং ডিবাগ এনভায়রনমেন্টে অ্যাটেস্টেশনের জন্য ব্যবহৃত প্রোভাইডার ভিন্ন হয়। একটি আসল ডিভাইসের প্রোডাকশন অ্যাপ তার সত্যতা প্রমাণ করার জন্য অ্যাপলের বিল্ট-ইন অ্যাপ অ্যাটেস্ট সার্ভিস ব্যবহার করে। তবে, যেহেতু আইওএস সিমুলেটর এই ধরনের অ্যাটেস্টেশন প্রদান করতে পারে না, তাই ডিবাগ এনভায়রনমেন্টের জন্য একটি বিশেষ ডিবাগ প্রোভাইডারের প্রয়োজন হয়, যেটিকে একটি এপিআই কী (API key) পাস করা হয়।

নিম্নলিখিত কোডটি একটি কম্পাইলার ডিরেক্টিভ ব্যবহার করে বিল্ড টাইমে স্বয়ংক্রিয়ভাবে সঠিক প্রোভাইডার নির্বাচন করার মাধ্যমে উভয় পরিস্থিতিই সামাল দেয়।

SwiftUI

  1. মূল অ্যাপ ফাইলটি খুলুন।
  2. import-গুলোর পরে এবং @main অ্যাট্রিবিউটের আগে নিম্নলিখিত AppDelegate ক্লাসটি সংজ্ঞায়িত করুন:
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 Key) বসান।
  2. আপনার App struct-এর ভিতরে, 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

  1. AppDelegate.swift খুলুন।
  2. অ্যাপ চেক ইনিশিয়ালাইজেশন অন্তর্ভুক্ত করার জন্য application(_:didFinishLaunchingWithOptions:) মেথডটি আপডেট করুন:
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 Key) বসান।

আপনার 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. ন্যাভিগেশন মেনু থেকে রান নির্বাচন করুন।
  3. আর্গুমেন্টস ট্যাবটি নির্বাচন করুন।
  4. 'Arguments Passed on Launch' বিভাগে, + নির্বাচন করুন এবং -FIRDebugEnabled যোগ করুন। এই লঞ্চ আর্গুমেন্টটি Firebase ডিবাগ লগিং সক্ষম করে।
  5. বন্ধ নির্বাচন করুন।

এক্সকোড আর্গুমেন্টস এডিটর পৃষ্ঠা

  1. সিমুলেটরে আপনার অ্যাপটি চালু করুন।
  2. এক্সকোড কনসোলে প্রিন্ট হওয়া অ্যাপ চেক ডিবাগ টোকেনটি কপি করুন।

Xcode কনসোলে অ্যাপ ডিবাগ টোকেন চেক করুন

  1. Firebase Console- এ আপনার প্রজেক্টে যান।
  2. ন্যাভিগেশন মেনুতে থাকা বিল্ড সেকশনটি প্রসারিত করুন।
  3. অ্যাপ চেক নির্বাচন করুন।
  4. অ্যাপস ট্যাবটি নির্বাচন করুন।
  5. আপনার অ্যাপের উপর মাউস রাখুন এবং তিন-বিন্দু মেনু আইকনটি নির্বাচন করুন।

ফায়ারবেস অ্যাপ সেটিংস পরীক্ষা করুন

  1. ডিবাগ টোকেন পরিচালনা নির্বাচন করুন।
  2. ডিবাগ টোকেন যোগ করুন নির্বাচন করুন।
  3. আপনার ডিবাগ টোকেনটির একটি নাম দিন এবং ভ্যালু হিসেবে আগে কপি করা ডিবাগ টোকেনটি পেস্ট করুন।
  4. আপনার টোকেনটি নিবন্ধন করতে সেভ নির্বাচন করুন।

ফায়ারবেস অ্যাপ চেক ডিবাগ টোকেন ব্যবস্থাপনা

  1. সিমুলেটরে ফিরে যান এবং সাইন ইন করুন।

কনসোলে মেট্রিকগুলো প্রদর্শিত হতে কয়েক মিনিট সময় লাগতে পারে। সেগুলো প্রদর্শিত হয়ে গেলে, আপনি দুটি জায়গার যেকোনো একটিতে ভেরিফাইড রিকোয়েস্টের সংখ্যা বৃদ্ধি দেখে অ্যাপ চেক ঠিকমতো কাজ করছে কিনা তা নিশ্চিত হতে পারেন:

  • Firebase Console-এর App Check সেকশনের APIs ট্যাবের অধীনে।

ফায়ারবেস অ্যাপ মেট্রিক্স পরীক্ষা করুন

  • গুগল ক্লাউড কনসোলে আপনার OAuth ক্লায়েন্টের সম্পাদনা পৃষ্ঠায়।

গুগল ক্লাউড কনসোল অ্যাপ মেট্রিক্স পরীক্ষা করুন

আপনার অ্যাপের অ্যাপ চেক মেট্রিক্স নিরীক্ষণ করার পর এবং বৈধ অনুরোধগুলি যাচাই করা হচ্ছে তা নিশ্চিত করার পরে, আপনার অ্যাপ চেক এনফোর্সমেন্ট সক্রিয় করা উচিত। একবার সক্রিয় করা হলে, অ্যাপ চেক সমস্ত যাচাইবিহীন অনুরোধ প্রত্যাখ্যান করে, যা নিশ্চিত করে যে শুধুমাত্র আপনার আসল অ্যাপের ট্র্যাফিকই আপনার প্রকল্পের পক্ষ থেকে গুগলের OAuth 2.0 এন্ডপয়েন্টগুলি অ্যাক্সেস করতে পারবে।

১২. অতিরিক্ত সম্পদ

অভিনন্দন!

আপনি একটি OAuth 2.0 iOS ক্লায়েন্ট কনফিগার করেছেন, একটি iOS অ্যাপে ‘Sign in with Google’ বাটন যোগ করেছেন, বাটনটির চেহারা কাস্টমাইজ করার পদ্ধতি শিখেছেন, একটি JWT ID টোকেন ডিকোড করেছেন এবং আপনার অ্যাপের জন্য ‘App Check’ সক্রিয় করেছেন।

এই লিঙ্কগুলো আপনাকে পরবর্তী পদক্ষেপের জন্য সাহায্য করতে পারে:

প্রায়শই জিজ্ঞাসিত প্রশ্নাবলী