Skip to content

Commit 859e364

Browse files
Merge pull request #1296 from firebase/refactor-providers
2 parents 29840d4 + a6948d1 commit 859e364

File tree

14 files changed

+74
-116
lines changed

14 files changed

+74
-116
lines changed

FirebaseSwiftUI/FirebaseAppleSwiftUI/Sources/Services/AppleProviderAuthUI.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ extension AuthenticateWithAppleDialog: ASAuthorizationControllerDelegate {
114114

115115
// MARK: - Apple Provider Swift
116116

117-
public class AppleProviderSwift: AuthProviderSwift {
117+
public class AppleProviderSwift: CredentialAuthProviderSwift {
118118
public let scopes: [ASAuthorization.Scope]
119119
let providerId = "apple.com"
120120

@@ -140,15 +140,15 @@ public class AppleProviderSwift: AuthProviderSwift {
140140
}
141141

142142
public class AppleProviderAuthUI: AuthProviderUI {
143-
public var provider: AuthProviderSwift
143+
private let typedProvider: AppleProviderSwift
144+
public var provider: AuthProviderSwift { typedProvider }
145+
public let id: String = "apple.com"
144146

145-
public init(provider: AuthProviderSwift) {
146-
self.provider = provider
147+
public init(provider: AppleProviderSwift) {
148+
typedProvider = provider
147149
}
148150

149-
public let id: String = "apple.com"
150-
151151
@MainActor public func authButton() -> AnyView {
152-
AnyView(SignInWithAppleButton(provider: provider))
152+
AnyView(SignInWithAppleButton(provider: typedProvider))
153153
}
154154
}

FirebaseSwiftUI/FirebaseAppleSwiftUI/Sources/Views/SignInWithAppleButton.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ import SwiftUI
2020
@MainActor
2121
public struct SignInWithAppleButton {
2222
@Environment(AuthService.self) private var authService
23-
let provider: AuthProviderSwift
24-
public init(provider: AuthProviderSwift) {
23+
let provider: AppleProviderSwift
24+
public init(provider: AppleProviderSwift) {
2525
self.provider = provider
2626
}
2727
}

FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Services/AuthService.swift

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,12 @@ import FirebaseAuthUIComponents
1717
import FirebaseCore
1818
import SwiftUI
1919

20-
public protocol AuthProviderSwift {
20+
/// Base protocol for all authentication providers
21+
public protocol AuthProviderSwift {}
22+
23+
/// Protocol for providers that can directly create an AuthCredential
24+
/// Used by Google, Apple, Twitter, Facebook, and OAuth providers
25+
public protocol CredentialAuthProviderSwift: AuthProviderSwift {
2126
@MainActor func createAuthCredential() async throws -> AuthCredential
2227
}
2328

@@ -27,12 +32,6 @@ public protocol AuthProviderUI {
2732
var provider: AuthProviderSwift { get }
2833
}
2934

30-
public protocol PhoneAuthProviderSwift: AuthProviderSwift {
31-
@MainActor func verifyPhoneNumber(phoneNumber: String) async throws -> String
32-
@MainActor func createAuthCredential(verificationId: String,
33-
verificationCode: String) async throws -> AuthCredential
34-
}
35-
3635
public enum AuthenticationState {
3736
case unauthenticated
3837
case authenticating
@@ -164,10 +163,6 @@ public final class AuthService {
164163

165164
private var providers: [AuthProviderUI] = []
166165

167-
public var currentPhoneProvider: PhoneAuthProviderSwift? {
168-
providers.compactMap { $0.provider as? PhoneAuthProviderSwift }.first
169-
}
170-
171166
public func registerProvider(providerWithButton: AuthProviderUI) {
172167
providers.append(providerWithButton)
173168
}
@@ -189,7 +184,7 @@ public final class AuthService {
189184
)
190185
}
191186

192-
public func signIn(_ provider: AuthProviderSwift) async throws -> SignInOutcome {
187+
public func signIn(_ provider: CredentialAuthProviderSwift) async throws -> SignInOutcome {
193188
do {
194189
let credential = try await provider.createAuthCredential()
195190
let result = try await signIn(credentials: credential)
@@ -829,8 +824,15 @@ public extension AuthService {
829824
let password = try await passwordPrompt.confirmPassword()
830825
let credential = EmailAuthProvider.credential(withEmail: email, password: password)
831826
_ = try await user.reauthenticate(with: credential)
832-
} else if let matchingProvider = providers.first(where: { $0.id == providerId }) {
833-
let credential = try await matchingProvider.provider.createAuthCredential()
827+
} else if providerId == PhoneAuthProviderID {
828+
// Phone auth requires manual reauthentication via sign out and sign in otherwise it will take
829+
// the user out of the existing flow
830+
throw AuthServiceError.reauthenticationRequired(
831+
"Phone authentication requires you to sign out and sign in again to continue"
832+
)
833+
} else if let matchingProvider = providers.first(where: { $0.id == providerId }),
834+
let credentialProvider = matchingProvider.provider as? CredentialAuthProviderSwift {
835+
let credential = try await credentialProvider.createAuthCredential()
834836
_ = try await user.reauthenticate(with: credential)
835837
} else {
836838
throw AuthServiceError.providerNotFound("No provider found for \(providerId)")

FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/EnterPhoneNumberView.swift

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,8 @@ struct EnterPhoneNumberView: View {
4848
Button(action: {
4949
Task {
5050
do {
51-
guard let provider = authService.currentPhoneProvider else {
52-
fatalError("No phone provider found")
53-
}
5451
let fullPhoneNumber = selectedCountry.dialCode + phoneNumber
55-
let id = try await provider.verifyPhoneNumber(phoneNumber: fullPhoneNumber)
52+
let id = try await authService.verifyPhoneNumber(phoneNumber: fullPhoneNumber)
5653
authService.navigator.push(.enterVerificationCode(
5754
verificationID: id,
5855
fullPhoneNumber: fullPhoneNumber

FirebaseSwiftUI/FirebaseAuthSwiftUI/Sources/Views/EnterVerificationCodeView.swift

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,10 @@ struct EnterVerificationCodeView: View {
5252
Button(action: {
5353
Task {
5454
do {
55-
guard let provider = authService.currentPhoneProvider else {
56-
fatalError("No phone provider found")
57-
}
58-
let credential = try await provider.createAuthCredential(
59-
verificationId: verificationID,
55+
try await authService.signInWithPhoneNumber(
56+
verificationID: verificationID,
6057
verificationCode: verificationCode
6158
)
62-
63-
_ = try await authService.signIn(credentials: credential)
6459
authService.navigator.clear()
6560
} catch {}
6661
}

FirebaseSwiftUI/FirebaseFacebookSwiftUI/Sources/Services/FacebookProviderAuthUI.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import FirebaseAuth
1919
import FirebaseAuthSwiftUI
2020
import SwiftUI
2121

22-
public class FacebookProviderSwift: AuthProviderSwift {
22+
public class FacebookProviderSwift: CredentialAuthProviderSwift {
2323
let scopes: [String]
2424
let providerId = "facebook.com"
2525
private let loginManager = LoginManager()
@@ -119,14 +119,15 @@ public class FacebookProviderSwift: AuthProviderSwift {
119119
}
120120

121121
public class FacebookProviderAuthUI: AuthProviderUI {
122-
public var provider: AuthProviderSwift
122+
private let typedProvider: FacebookProviderSwift
123+
public var provider: AuthProviderSwift { typedProvider }
123124
public let id: String = "facebook.com"
124125

125-
public init(provider: AuthProviderSwift) {
126-
self.provider = provider
126+
public init(provider: FacebookProviderSwift) {
127+
typedProvider = provider
127128
}
128129

129130
@MainActor public func authButton() -> AnyView {
130-
AnyView(SignInWithFacebookButton(facebookProvider: provider as! FacebookProviderSwift))
131+
AnyView(SignInWithFacebookButton(facebookProvider: typedProvider))
131132
}
132133
}

FirebaseSwiftUI/FirebaseGoogleSwiftUI/Sources/Services/GoogleProviderAuthUI.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import GoogleSignIn
1919
import GoogleSignInSwift
2020
import SwiftUI
2121

22-
public class GoogleProviderSwift: AuthProviderSwift {
22+
public class GoogleProviderSwift: CredentialAuthProviderSwift {
2323
let scopes: [String]
2424
let clientID: String
2525
let providerId = "google.com"
@@ -71,14 +71,15 @@ public class GoogleProviderSwift: AuthProviderSwift {
7171
}
7272

7373
public class GoogleProviderAuthUI: AuthProviderUI {
74-
public var provider: AuthProviderSwift
74+
private let typedProvider: GoogleProviderSwift
75+
public var provider: AuthProviderSwift { typedProvider }
7576
public let id: String = "google.com"
7677

77-
public init(provider: AuthProviderSwift) {
78-
self.provider = provider
78+
public init(provider: GoogleProviderSwift) {
79+
typedProvider = provider
7980
}
8081

8182
@MainActor public func authButton() -> AnyView {
82-
AnyView(SignInWithGoogleButton(googleProvider: provider))
83+
AnyView(SignInWithGoogleButton(googleProvider: typedProvider))
8384
}
8485
}

FirebaseSwiftUI/FirebaseGoogleSwiftUI/Sources/Views/SignInWithGoogleButton.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ import SwiftUI
2626
@MainActor
2727
public struct SignInWithGoogleButton {
2828
@Environment(AuthService.self) private var authService
29-
let googleProvider: AuthProviderSwift
29+
let googleProvider: GoogleProviderSwift
3030

31-
public init(googleProvider: AuthProviderSwift) {
31+
public init(googleProvider: GoogleProviderSwift) {
3232
self.googleProvider = googleProvider
3333
}
3434
}

FirebaseSwiftUI/FirebaseOAuthSwiftUI/Sources/Services/OAuthProviderSwift.swift

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import FirebaseCore
1818
import SwiftUI
1919

2020
/// Configuration for a generic OAuth provider
21-
public class OAuthProviderSwift: AuthProviderSwift {
21+
public class OAuthProviderSwift: CredentialAuthProviderSwift {
2222
public let providerId: String
2323
public let scopes: [String]
2424
public let customParameters: [String: String]
@@ -116,20 +116,18 @@ public class OAuthProviderSwift: AuthProviderSwift {
116116
}
117117

118118
public class OAuthProviderAuthUI: AuthProviderUI {
119-
public var provider: AuthProviderSwift
119+
private let typedProvider: OAuthProviderSwift
120+
public var provider: AuthProviderSwift { typedProvider }
120121

121-
public init(provider: AuthProviderSwift) {
122-
self.provider = provider
122+
public init(provider: OAuthProviderSwift) {
123+
typedProvider = provider
123124
}
124125

125126
public var id: String {
126-
guard let oauthProvider = provider as? OAuthProviderSwift else {
127-
return "oauth.unknown"
128-
}
129-
return oauthProvider.providerId
127+
return typedProvider.providerId
130128
}
131129

132130
@MainActor public func authButton() -> AnyView {
133-
AnyView(GenericOAuthButton(provider: provider))
131+
AnyView(GenericOAuthButton(provider: typedProvider))
134132
}
135133
}

FirebaseSwiftUI/FirebaseOAuthSwiftUI/Sources/Views/GenericOAuthButton.swift

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,35 +20,28 @@ import SwiftUI
2020
@MainActor
2121
public struct GenericOAuthButton {
2222
@Environment(AuthService.self) private var authService
23-
let provider: AuthProviderSwift
24-
public init(provider: AuthProviderSwift) {
23+
let provider: OAuthProviderSwift
24+
public init(provider: OAuthProviderSwift) {
2525
self.provider = provider
2626
}
2727
}
2828

2929
extension GenericOAuthButton: View {
3030
public var body: some View {
31-
guard let oauthProvider = provider as? OAuthProviderSwift else {
32-
return AnyView(
33-
Text(authService.string.invalidOAuthProviderError)
34-
.foregroundColor(.red)
35-
)
36-
}
37-
3831
// Create custom style from provider configuration
3932
var resolvedStyle: ProviderStyle {
4033
ProviderStyle(
41-
icon: oauthProvider.buttonIcon,
42-
backgroundColor: oauthProvider.buttonBackgroundColor,
43-
contentColor: oauthProvider.buttonForegroundColor
34+
icon: provider.buttonIcon,
35+
backgroundColor: provider.buttonBackgroundColor,
36+
contentColor: provider.buttonForegroundColor
4437
)
4538
}
4639

4740
return AnyView(
4841
AuthProviderButton(
49-
label: oauthProvider.displayName,
42+
label: provider.displayName,
5043
style: resolvedStyle,
51-
accessibilityId: "sign-in-with-\(oauthProvider.providerId)-button"
44+
accessibilityId: "sign-in-with-\(provider.providerId)-button"
5245
) {
5346
Task {
5447
try? await authService.signIn(provider)

0 commit comments

Comments
 (0)