11import FacebookCore
22import FacebookLogin
3+ import FirebaseAuth
34import FirebaseAuthSwiftUI
45import SwiftUI
56
67@MainActor
78public struct FacebookButtonView {
89 @Environment ( AuthService . self) private var authService
910 @State private var errorMessage = " "
10- @State private var limitedLogin : Bool = true
11- @State private var nonce : String ? = FacebookUtils . randomNonce ( )
11+ @State private var limitedLogin : Bool = false
12+ @State private var rawNonce : String
13+ @State private var shaNonce : String
14+
15+ public init ( ) {
16+ let nonce = FacebookUtils . randomNonce ( )
17+ _rawNonce = State ( initialValue: nonce)
18+ _shaNonce = State ( initialValue: FacebookUtils . sha256Hash ( of: nonce) )
19+ }
1220
13- public init ( ) { }
21+ private func classicLogin( ) async {
22+ do {
23+ if let token = AccessToken . current,
24+ !token. isExpired {
25+ let credential = FacebookAuthProvider
26+ . credential ( withAccessToken: token. tokenString)
27+ try await authService. signIn ( with: credential)
28+ } else {
29+ throw NSError (
30+ domain: " FacebookSwiftErrorDomain " ,
31+ code: 1 ,
32+ userInfo: [
33+ NSLocalizedDescriptionKey: " Access token has expired or not available. Please sign-in with Facebook before attempting to create a Facebook provider credential " ,
34+ ]
35+ )
36+ }
37+ } catch {
38+ errorMessage = authService. string. localizedErrorMessage (
39+ for: error
40+ )
41+ }
42+ }
1443
15- private func signInWithFacebook( ) async {
16- if let token = AccessToken . current,
17- !token. isExpired {
18- // AuthenticationToken.current.
19- // no need to login with Facebook, create credential and sign in here
44+ private func limitedLogin( ) async {
45+ do {
46+ if let idToken = AuthenticationToken . current {
47+ let credential = OAuthProvider . credential ( withProviderID: kFacebookProviderId,
48+ idToken: idToken. tokenString,
49+ rawNonce: rawNonce)
50+ try await authService. signIn ( with: credential)
51+ } else {
52+ throw NSError (
53+ domain: " FacebookSwiftErrorDomain " ,
54+ code: 2 ,
55+ userInfo: [
56+ NSLocalizedDescriptionKey: " Authentication is not available. Please sign-in with Facebook before attempting to create a Facebook provider credential " ,
57+ ]
58+ )
59+ }
60+ } catch {
61+ errorMessage = authService. string. localizedErrorMessage (
62+ for: error
63+ )
2064 }
2165 }
2266}
@@ -25,13 +69,17 @@ extension FacebookButtonView: View {
2569 public var body : some View {
2670 FacebookLoginButtonView (
2771 isLimitedLogin: $limitedLogin,
28- nonce: $nonce ,
72+ nonce: $shaNonce ,
2973 onLoginResult: { error in
3074 Task {
3175 if let error = error {
3276 errorMessage = authService. string. localizedErrorMessage ( for: error)
3377 } else {
34- await signInWithFacebook ( )
78+ if limitedLogin {
79+ await limitedLogin ( )
80+ } else {
81+ await classicLogin ( )
82+ }
3583 }
3684 }
3785 }
@@ -44,8 +92,8 @@ struct FacebookLoginButtonView: UIViewRepresentable {
4492 typealias UIViewType = FBLoginButton
4593
4694 @Binding var isLimitedLogin : Bool
47- @Binding var nonce : String ?
48- var onLoginResult : ( ( Error ? ) -> Void ) ?
95+ @Binding var nonce : String
96+ var onLoginResult : ( Error ? ) -> Void
4997
5098 class Coordinator : NSObject , @preconcurrency LoginButtonDelegate {
5199 var parent : FacebookLoginButtonView
@@ -56,11 +104,9 @@ struct FacebookLoginButtonView: UIViewRepresentable {
56104
57105 @MainActor func loginButtonWillLogin( _ loginButton: FBLoginButton ) -> Bool {
58106 loginButton. loginTracking = parent. isLimitedLogin ? . limited : . enabled
59- loginButton. permissions = [ " public_profile " , " email " ]
107+ // loginButton.permissions = ["public_profile", "email"]
60108
61- if let nonce = parent. nonce, !nonce. isEmpty {
62- loginButton. nonce = nonce
63- }
109+ loginButton. nonce = parent. nonce
64110
65111 return true
66112 }
@@ -69,20 +115,20 @@ struct FacebookLoginButtonView: UIViewRepresentable {
69115 didCompleteWith result: LoginManagerLoginResult ? ,
70116 error: Error ? ) {
71117 if let error = error {
72- parent. onLoginResult ? ( error)
118+ parent. onLoginResult ( error)
73119 return
74120 }
75121
76122 guard let result = result, !result. isCancelled else {
77- parent. onLoginResult ? ( NSError (
123+ parent. onLoginResult ( NSError (
78124 domain: " FacebookLogin " ,
79125 code: 1 ,
80126 userInfo: [ NSLocalizedDescriptionKey: " Login was cancelled. " ]
81127 ) )
82128 return
83129 }
84130
85- parent. onLoginResult ? ( nil )
131+ parent. onLoginResult ( nil )
86132 }
87133
88134 func loginButtonDidLogOut( _: FBLoginButton ) {
0 commit comments