kvendrik / google-oauth-example-ios

Google oAuth iOS example with multi-account support

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Google oAuth Example iOS

Example of oAuth authentication with multi-account support on iOS using GoogleSignIn and GTMAppAuth.

Why both libraries?

Reason we're using both libraries is because GoogleSignIn is Google's new preferred way of doing oAuth on iOS but it doesn't support multiple accounts to be logged in at the same time. To make that work we use a few methods from GTMAppAuth to save and load authorization objects to and from the keychain.

Setup

  1. Create an oAuth client in Google's API Console
  2. Open google-oauth-example.xcworkspace in xCode (note that this project only supports iOS v15+ and therefor xCode v13+)
  3. Add the reversed client ID to your URL Types
  4. Go to GoogleAuth.swift and replace YOUR_OAUTH_CLIENT_ID with your newly created client ID
  5. Run the project in a simulator of your choice

How it works

  1. Load all saved authorizations from your keychain
GoogleAuth.shared.loadSavedAuthorizations() {
    print("loaded authorizations")
}
  1. For new sign ins use GoogleAuth.shared.signIn(_:)
GoogleAuth.shared.signIn() {
    success in
    print(success ? "signed in" : "sign in failed")
}
  1. Handle incoming URLs for when Google redirects back to your app after login
extension SceneDelegate {
    func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
        guard let url = URLContexts.first?.url else { return }
        GoogleAuth.shared.handleUrl(url)
    }
}
  1. Observe GoogleAuth.shared for changes in the logged in accounts
struct AccountsList: View {
    @ObservedObject var googleAuth = GoogleAuth.shared
    
    var body: some View {
        ForEach(googleAuth.profiles, id: \.self.email) {
            profile in
            Text(profile.email)
        }
    }
}
  1. Log out accounts using their profile sub
GoogleAuth.shared.logOut(profile.sub)
  1. Use GoogleApi.shared.fetch(url:authorization:dataStructure:_:) for your own API requests
guard let profileSub = GoogleAuth.shared.profiles.first?.sub else { return }
guard let authorization = GoogleAuth.shared.authorizations[profileSub] else { return }
guard let url = URL(string: "https://www.googleapis.com/oauth2/v3/userinfo") else { return }

GoogleApi.shared.fetch(
    url: url,
    authorization: authorization,
    dataStructure: GoogleProfile.self
) {
    profile, error in
    
    guard error == nil else { return }
    guard let profile = profile else { return }

    print(profile)
}

About

Google oAuth iOS example with multi-account support


Languages

Language:Swift 97.1%Language:Ruby 2.9%