-
Notifications
You must be signed in to change notification settings - Fork 490
Expand file tree
/
Copy pathFacebookProviderAuthUI.swift
More file actions
120 lines (108 loc) · 3.63 KB
/
FacebookProviderAuthUI.swift
File metadata and controls
120 lines (108 loc) · 3.63 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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import AppTrackingTransparency
import FacebookCore
import FacebookLogin
import FirebaseAuth
import FirebaseAuthSwiftUI
import SwiftUI
let kFacebookEmailScope = "email"
let kFacebookProfileScope = "public_profile"
let kDefaultFacebookScopes = [kFacebookEmailScope, kFacebookProfileScope]
public enum FacebookLoginType {
case classic
case limitedLogin
}
public enum FacebookProviderError: Error {
case signInCancelled(String)
case configurationInvalid(String)
case accessToken(String)
case authenticationToken(String)
}
public class FacebookProviderAuthUI: FacebookProviderAuthUIProtocol {
let scopes: [String]
let shortName = "Facebook"
let providerId = "facebook.com"
private let loginManager = LoginManager()
private var rawNonce: String
private var shaNonce: String
public init(scopes: [String]? = nil) {
self.scopes = scopes ?? kDefaultFacebookScopes
rawNonce = CommonUtils.randomNonce()
shaNonce = CommonUtils.sha256Hash(of: rawNonce)
}
@MainActor public var authButton: SignInWithFacebookButton {
return SignInWithFacebookButton()
}
@MainActor public func signInWithFacebook(isLimitedLogin: Bool) async throws -> AuthCredential {
let trackingStatus = ATTrackingManager.trackingAuthorizationStatus
let tracking: LoginTracking = trackingStatus != .authorized ? .limited :
(isLimitedLogin ? .limited : .enabled)
guard let configuration: LoginConfiguration = {
if tracking == .limited {
return LoginConfiguration(
permissions: scopes,
tracking: tracking,
nonce: shaNonce
)
} else {
return LoginConfiguration(
permissions: scopes,
tracking: tracking
)
}
}() else {
throw FacebookProviderError
.configurationInvalid("Failed to create Facebook login configuration")
}
let result = try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<
Void,
Error
>) in
loginManager.logIn(
configuration: configuration
) { result in
switch result {
case .cancelled:
continuation
.resume(throwing: FacebookProviderError.signInCancelled("User cancelled sign-in"))
// showCanceledAlert = true
case let .failed(error):
continuation.resume(throwing: error)
// errorMessage = authService.string.localizedErrorMessage(for: error)
case .success:
continuation.resume()
}
}
}
if isLimitedLogin {
return try limitedLogin()
} else {
return try classicLogin()
}
}
private func classicLogin() throws -> AuthCredential {
if let token = AccessToken.current,
!token.isExpired {
let credential = FacebookAuthProvider
.credential(withAccessToken: token.tokenString)
return credential
} else {
throw FacebookProviderError
.accessToken(
"Access token has expired or not available. Please sign-in with Facebook before attempting to create a Facebook provider credential"
)
}
}
private func limitedLogin() throws -> AuthCredential {
if let idToken = AuthenticationToken.current {
let credential = OAuthProvider.credential(withProviderID: providerId,
idToken: idToken.tokenString,
rawNonce: rawNonce)
return credential
} else {
throw FacebookProviderError
.authenticationToken(
"Authentication is not available. Please sign-in with Facebook before attempting to create a Facebook provider credential"
)
}
}
}