-
Notifications
You must be signed in to change notification settings - Fork 491
Expand file tree
/
Copy pathGoogleProviderAuthUI.swift
More file actions
70 lines (61 loc) · 2.33 KB
/
GoogleProviderAuthUI.swift
File metadata and controls
70 lines (61 loc) · 2.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
@preconcurrency import FirebaseAuth
import FirebaseAuthSwiftUI
import FirebaseCore
import GoogleSignIn
import GoogleSignInSwift
import SwiftUI
let kGoogleUserInfoEmailScope = "https://www.googleapis.com/auth/userinfo.email"
let kGoogleUserInfoProfileScope = "https://www.googleapis.com/auth/userinfo.profile"
let kDefaultScopes = [kGoogleUserInfoEmailScope, kGoogleUserInfoProfileScope]
public enum GoogleProviderError: Error {
case rootViewControllerNotFound(String)
case authenticationToken(String)
case user(String)
}
public class GoogleProviderAuthUI: @preconcurrency GoogleProviderAuthUIProtocol {
let scopes: [String]
let shortName = "Google"
let providerId = "google.com"
let clientID: String
public init(scopes: [String]? = nil, clientID: String = FirebaseApp.app()!.options.clientID!) {
self.scopes = scopes ?? kDefaultScopes
self.clientID = clientID
}
@MainActor public var authButton: GoogleSignInButton {
return GoogleSignInButton {
Task {
try await self.signInWithGoogle(clientID: self.clientID)
}
}
}
@MainActor public func signInWithGoogle(clientID: String) async throws -> AuthCredential {
guard let presentingViewController = await (UIApplication.shared.connectedScenes
.first as? UIWindowScene)?.windows.first?.rootViewController else {
throw GoogleProviderError
.rootViewControllerNotFound(
"Root View controller is not available to present Google sign-in View."
)
}
let config = GIDConfiguration(clientID: clientID)
GIDSignIn.sharedInstance.configuration = config
return try await withCheckedThrowingContinuation { continuation in
GIDSignIn.sharedInstance.signIn(
withPresenting: presentingViewController
) { result, error in
if let error = error {
continuation.resume(throwing: error)
return
}
guard let user = result?.user,
let idToken = user.idToken?.tokenString else {
continuation
.resume(throwing: GoogleProviderError.user("Failed to retrieve user or idToken."))
return
}
let credential = GoogleAuthProvider.credential(withIDToken: idToken,
accessToken: user.accessToken.tokenString)
continuation.resume(returning: credential)
}
}
}
}