Skip to content

Commit 3e39b02

Browse files
authored
[Auth] Remove AuthBackend singleton (#14006)
1 parent 1c82538 commit 3e39b02

38 files changed

+236
-211
lines changed

FirebaseAuth/Sources/Swift/Auth/Auth.swift

Lines changed: 37 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,12 @@ extension Auth: AuthInterop {
123123
return
124124
}
125125
// Call back with current user token.
126-
currentUser.internalGetToken(forceRefresh: forceRefresh) { token, error in
127-
DispatchQueue.main.async {
128-
callback(token, error)
126+
currentUser
127+
.internalGetToken(forceRefresh: forceRefresh, backend: strongSelf.backend) { token, error in
128+
DispatchQueue.main.async {
129+
callback(token, error)
130+
}
129131
}
130-
}
131132
}
132133
}
133134

@@ -292,7 +293,7 @@ extension Auth: AuthInterop {
292293
requestConfiguration: self.requestConfiguration)
293294
Task {
294295
do {
295-
let response = try await AuthBackend.call(with: request)
296+
let response = try await self.backend.call(with: request)
296297
Auth.wrapMainAsync(callback: completion, withParam: response.signinMethods, error: nil)
297298
} catch {
298299
Auth.wrapMainAsync(callback: completion, withParam: nil, error: error)
@@ -395,7 +396,7 @@ extension Auth: AuthInterop {
395396
let response = try await injectRecaptcha(request: request,
396397
action: AuthRecaptchaAction.signInWithPassword)
397398
#else
398-
let response = try await AuthBackend.call(with: request)
399+
let response = try await backend.call(with: request)
399400
#endif
400401
return try await completeSignIn(
401402
withAccessToken: response.idToken,
@@ -709,7 +710,7 @@ extension Auth: AuthInterop {
709710
let request = SignUpNewUserRequest(requestConfiguration: self.requestConfiguration)
710711
Task {
711712
do {
712-
let response = try await AuthBackend.call(with: request)
713+
let response = try await self.backend.call(with: request)
713714
let user = try await self.completeSignIn(
714715
withAccessToken: response.idToken,
715716
accessTokenExpirationDate: response.approximateExpirationDate,
@@ -771,7 +772,7 @@ extension Auth: AuthInterop {
771772
requestConfiguration: self.requestConfiguration)
772773
Task {
773774
do {
774-
let response = try await AuthBackend.call(with: request)
775+
let response = try await self.backend.call(with: request)
775776
let user = try await self.completeSignIn(
776777
withAccessToken: response.idToken,
777778
accessTokenExpirationDate: response.approximateExpirationDate,
@@ -881,7 +882,7 @@ extension Auth: AuthInterop {
881882
if let inResponse {
882883
response = inResponse
883884
} else {
884-
response = try await AuthBackend.call(with: request)
885+
response = try await self.backend.call(with: request)
885886
}
886887
let user = try await self.completeSignIn(
887888
withAccessToken: response.idToken,
@@ -993,7 +994,7 @@ extension Auth: AuthInterop {
993994
requestConfiguration: self.requestConfiguration)
994995
Task {
995996
do {
996-
let response = try await AuthBackend.call(with: request)
997+
let response = try await self.backend.call(with: request)
997998

998999
let operation = ActionCodeInfo.actionCodeOperation(forRequestType: response.requestType)
9991000
guard let email = response.email else {
@@ -1433,7 +1434,7 @@ extension Auth: AuthInterop {
14331434
/// complete, or fails. Invoked asynchronously on the main thread in the future.
14341435
@objc open func revokeToken(withAuthorizationCode authorizationCode: String,
14351436
completion: ((Error?) -> Void)? = nil) {
1436-
currentUser?.internalGetToken { idToken, error in
1437+
currentUser?.internalGetToken(backend: backend) { idToken, error in
14371438
if let error {
14381439
Auth.wrapMainAsync(completion, error)
14391440
return
@@ -1613,7 +1614,9 @@ extension Auth: AuthInterop {
16131614

16141615
// MARK: Internal methods
16151616

1616-
init(app: FirebaseApp, keychainStorageProvider: AuthKeychainStorage = AuthKeychainStorageReal()) {
1617+
init(app: FirebaseApp,
1618+
keychainStorageProvider: AuthKeychainStorage = AuthKeychainStorageReal(),
1619+
backend: AuthBackend = AuthBackend(rpcIssuer: AuthBackendRPCIssuer())) {
16171620
Auth.setKeychainServiceNameForApp(app)
16181621
self.app = app
16191622
mainBundleUrlTypes = Bundle.main
@@ -1638,6 +1641,7 @@ extension Auth: AuthInterop {
16381641
auth: nil,
16391642
heartbeatLogger: app.heartbeatLogger,
16401643
appCheck: appCheck)
1644+
self.backend = backend
16411645
super.init()
16421646
requestConfiguration.auth = self
16431647

@@ -1911,17 +1915,18 @@ extension Auth: AuthInterop {
19111915
return
19121916
}
19131917
let uid = strongSelf.currentUser?.uid
1914-
strongSelf.currentUser?.internalGetToken(forceRefresh: true) { token, error in
1915-
if strongSelf.currentUser?.uid != uid {
1916-
return
1917-
}
1918-
if error != nil {
1919-
// Kicks off exponential back off logic to retry failed attempt. Starts with one minute
1920-
// delay (60 seconds) if this is the first failed attempt.
1921-
let rescheduleDelay = retry ? min(delay * 2, 16 * 60) : 60
1922-
strongSelf.scheduleAutoTokenRefresh(withDelay: rescheduleDelay, retry: true)
1918+
strongSelf.currentUser?
1919+
.internalGetToken(forceRefresh: true, backend: strongSelf.backend) { token, error in
1920+
if strongSelf.currentUser?.uid != uid {
1921+
return
1922+
}
1923+
if error != nil {
1924+
// Kicks off exponential back off logic to retry failed attempt. Starts with one minute
1925+
// delay (60 seconds) if this is the first failed attempt.
1926+
let rescheduleDelay = retry ? min(delay * 2, 16 * 60) : 60
1927+
strongSelf.scheduleAutoTokenRefresh(withDelay: rescheduleDelay, retry: true)
1928+
}
19231929
}
1924-
}
19251930
}
19261931
}
19271932

@@ -2075,7 +2080,7 @@ extension Auth: AuthInterop {
20752080
requestConfiguration: requestConfiguration)
20762081
request.autoCreate = !isReauthentication
20772082
credential.prepare(request)
2078-
let response = try await AuthBackend.call(with: request)
2083+
let response = try await backend.call(with: request)
20792084
if response.needConfirmation {
20802085
let email = response.email
20812086
let credential = OAuthCredential(withVerifyAssertionResponse: response)
@@ -2114,7 +2119,7 @@ extension Auth: AuthInterop {
21142119
phoneNumber: phoneNumber,
21152120
operation: operation,
21162121
requestConfiguration: requestConfiguration)
2117-
return try await AuthBackend.call(with: request)
2122+
return try await backend.call(with: request)
21182123
case let .verification(verificationID, code):
21192124
guard verificationID.count > 0 else {
21202125
throw AuthErrorUtils.missingVerificationIDError(message: nil)
@@ -2126,7 +2131,7 @@ extension Auth: AuthInterop {
21262131
verificationCode: code,
21272132
operation: operation,
21282133
requestConfiguration: requestConfiguration)
2129-
return try await AuthBackend.call(with: request)
2134+
return try await backend.call(with: request)
21302135
}
21312136
}
21322137
#endif
@@ -2152,7 +2157,7 @@ extension Auth: AuthInterop {
21522157
timestamp: credential.timestamp,
21532158
displayName: credential.displayName,
21542159
requestConfiguration: requestConfiguration)
2155-
let response = try await AuthBackend.call(with: request)
2160+
let response = try await backend.call(with: request)
21562161
let user = try await completeSignIn(withAccessToken: response.idToken,
21572162
accessTokenExpirationDate: response
21582163
.approximateExpirationDate,
@@ -2184,7 +2189,7 @@ extension Auth: AuthInterop {
21842189
let request = EmailLinkSignInRequest(email: email,
21852190
oobCode: actionCode,
21862191
requestConfiguration: requestConfiguration)
2187-
let response = try await AuthBackend.call(with: request)
2192+
let response = try await backend.call(with: request)
21882193
let user = try await completeSignIn(withAccessToken: response.idToken,
21892194
accessTokenExpirationDate: response
21902195
.approximateExpirationDate,
@@ -2242,7 +2247,7 @@ extension Auth: AuthInterop {
22422247
private func wrapAsyncRPCTask(_ request: any AuthRPCRequest, _ callback: ((Error?) -> Void)?) {
22432248
Task {
22442249
do {
2245-
let _ = try await AuthBackend.call(with: request)
2250+
let _ = try await self.backend.call(with: request)
22462251
Auth.wrapMainAsync(callback, nil)
22472252
} catch {
22482253
Auth.wrapMainAsync(callback, error)
@@ -2294,7 +2299,7 @@ extension Auth: AuthInterop {
22942299
action: action)
22952300
} else {
22962301
do {
2297-
return try await AuthBackend.call(with: request)
2302+
return try await backend.call(with: request)
22982303
} catch {
22992304
let nsError = error as NSError
23002305
if let underlyingError = nsError.userInfo[NSUnderlyingErrorKey] as? NSError,
@@ -2313,7 +2318,7 @@ extension Auth: AuthInterop {
23132318
}
23142319
}
23152320
}
2316-
return try await AuthBackend.call(with: request)
2321+
return try await backend.call(with: request)
23172322
}
23182323
#endif
23192324

@@ -2330,6 +2335,8 @@ extension Auth: AuthInterop {
23302335
/// Auth's backend.
23312336
var requestConfiguration: AuthRequestConfiguration
23322337

2338+
let backend: AuthBackend
2339+
23332340
#if os(iOS)
23342341

23352342
/// The manager for APNs tokens used by phone number auth.

FirebaseAuth/Sources/Swift/AuthProvider/OAuthProvider.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ import Foundation
413413
private func getHeadfulLiteUrl(eventID: String,
414414
sessionID: String) async throws -> URL? {
415415
let authDomain = try await AuthWebUtils
416-
.fetchAuthDomain(withRequestConfiguration: auth.requestConfiguration)
416+
.fetchAuthDomain(withRequestConfiguration: auth.requestConfiguration, backend: auth.backend)
417417
let bundleID = Bundle.main.bundleIdentifier
418418
let clientID = auth.app?.options.clientID
419419
let appID = auth.app?.options.googleAppID

FirebaseAuth/Sources/Swift/AuthProvider/PhoneAuthProvider.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ import Foundation
217217
.requestConfiguration)
218218

219219
do {
220-
let response = try await AuthBackend.call(with: request)
220+
let response = try await auth.backend.call(with: request)
221221
return response.verificationID
222222
} catch {
223223
return try await handleVerifyErrorWithRetry(error: error,
@@ -245,7 +245,7 @@ import Foundation
245245
requestConfiguration: auth.requestConfiguration
246246
)
247247

248-
let response = try await AuthBackend.call(with: request)
248+
let response = try await auth.backend.call(with: request)
249249
return response.verificationID
250250
}
251251
guard let session else {
@@ -263,15 +263,15 @@ import Foundation
263263
let request = StartMFAEnrollmentRequest(idToken: idToken,
264264
enrollmentInfo: startMFARequestInfo,
265265
requestConfiguration: auth.requestConfiguration)
266-
let response = try await AuthBackend.call(with: request)
266+
let response = try await auth.backend.call(with: request)
267267
return response.phoneSessionInfo?.sessionInfo
268268
} else {
269269
let request = StartMFASignInRequest(MFAPendingCredential: session.mfaPendingCredential,
270270
MFAEnrollmentID: session.multiFactorInfo?.uid,
271271
signInInfo: startMFARequestInfo,
272272
requestConfiguration: auth.requestConfiguration)
273273

274-
let response = try await AuthBackend.call(with: request)
274+
let response = try await auth.backend.call(with: request)
275275
return response.responseInfo?.sessionInfo
276276
}
277277
} catch {
@@ -328,7 +328,7 @@ import Foundation
328328
isSandbox: token.type == AuthAPNSTokenType.sandbox,
329329
requestConfiguration: auth.requestConfiguration)
330330
do {
331-
let verifyResponse = try await AuthBackend.call(with: request)
331+
let verifyResponse = try await auth.backend.call(with: request)
332332
guard let receipt = verifyResponse.receipt,
333333
let timeout = verifyResponse.suggestedTimeOutDate?.timeIntervalSinceNow else {
334334
fatalError("Internal Auth Error: invalid VerifyClientResponse")
@@ -436,7 +436,7 @@ import Foundation
436436
/// - Parameter eventID: The event ID used for this purpose.
437437
private func reCAPTCHAURL(withEventID eventID: String) async throws -> URL? {
438438
let authDomain = try await AuthWebUtils
439-
.fetchAuthDomain(withRequestConfiguration: auth.requestConfiguration)
439+
.fetchAuthDomain(withRequestConfiguration: auth.requestConfiguration, backend: auth.backend)
440440
let bundleID = Bundle.main.bundleIdentifier
441441
let clientID = auth.app?.options.clientID
442442
let appID = auth.app?.options.googleAppID

FirebaseAuth/Sources/Swift/Backend/AuthBackend.swift

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,21 +32,7 @@ class AuthBackend: AuthBackendProtocol {
3232
return "FirebaseAuth.iOS/\(FirebaseVersion()) \(GTMFetcherStandardUserAgentString(nil))"
3333
}
3434

35-
static func call<T: AuthRPCRequest>(with request: T) async throws -> T.Response {
36-
return try await shared.call(with: request)
37-
}
38-
39-
static func setTestRPCIssuer(issuer: AuthBackendRPCIssuer) {
40-
shared.rpcIssuer = issuer
41-
}
42-
43-
static func resetRPCIssuer() {
44-
shared.rpcIssuer = AuthBackendRPCIssuer()
45-
}
46-
47-
private static let shared: AuthBackend = .init(rpcIssuer: AuthBackendRPCIssuer())
48-
49-
private var rpcIssuer: any AuthBackendRPCIssuerProtocol
35+
private let rpcIssuer: any AuthBackendRPCIssuerProtocol
5036

5137
init(rpcIssuer: any AuthBackendRPCIssuerProtocol) {
5238
self.rpcIssuer = rpcIssuer

FirebaseAuth/Sources/Swift/Backend/RPC/SecureTokenRequest.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ private var gAPIHost = "securetoken.googleapis.com"
5959

6060
/// Represents the parameters for the token endpoint.
6161
@available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *)
62-
struct SecureTokenRequest: AuthRPCRequest {
62+
class SecureTokenRequest: AuthRPCRequest {
6363
typealias Response = SecureTokenResponse
6464

6565
/// The type of grant requested.

FirebaseAuth/Sources/Swift/MultiFactor/MultiFactor.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ import Foundation
8888
.requestConfiguration)
8989
Task {
9090
do {
91-
let response = try await AuthBackend.call(with: request)
91+
let response = try await auth.backend.call(with: request)
9292
do {
9393
let user = try await auth.completeSignIn(withAccessToken: response.idToken,
9494
accessTokenExpirationDate: nil,
@@ -139,7 +139,7 @@ import Foundation
139139

140140
Task {
141141
do {
142-
let response = try await AuthBackend.call(with: request)
142+
let response = try await auth.backend.call(with: request)
143143
do {
144144
let user = try await auth.completeSignIn(withAccessToken: response.idToken,
145145
accessTokenExpirationDate: nil,
@@ -217,7 +217,7 @@ import Foundation
217217
requestConfiguration: user.requestConfiguration)
218218
Task {
219219
do {
220-
let response = try await AuthBackend.call(with: request)
220+
let response = try await auth.backend.call(with: request)
221221
do {
222222
let user = try await auth.completeSignIn(withAccessToken: response.idToken,
223223
accessTokenExpirationDate: nil,

FirebaseAuth/Sources/Swift/MultiFactor/MultiFactorResolver.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ import Foundation
7272
)
7373
Task {
7474
do {
75-
let response = try await AuthBackend.call(with: request)
75+
let response = try await self.auth.backend.call(with: request)
7676
let user = try await self.auth.completeSignIn(withAccessToken: response.idToken,
7777
accessTokenExpirationDate: nil,
7878
refreshToken: response.refreshToken,

FirebaseAuth/Sources/Swift/MultiFactor/TOTP/TOTPMultiFactorGenerator.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ import Foundation
3131
@objc(generateSecretWithMultiFactorSession:completion:)
3232
open class func generateSecret(with session: MultiFactorSession,
3333
completion: @escaping (TOTPSecret?, Error?) -> Void) {
34-
guard let currentUser = session.currentUser,
35-
let requestConfiguration = currentUser.auth?.requestConfiguration else {
34+
guard let currentUser = session.currentUser, let auth = currentUser.auth else {
3635
let error = AuthErrorUtils.error(code: AuthErrorCode.internalError,
3736
userInfo: [NSLocalizedDescriptionKey:
3837
"Invalid ID token."])
@@ -42,10 +41,10 @@ import Foundation
4241
let totpEnrollmentInfo = AuthProtoStartMFATOTPEnrollmentRequestInfo()
4342
let request = StartMFAEnrollmentRequest(idToken: session.idToken,
4443
totpEnrollmentInfo: totpEnrollmentInfo,
45-
requestConfiguration: requestConfiguration)
44+
requestConfiguration: auth.requestConfiguration)
4645
Task {
4746
do {
48-
let response = try await AuthBackend.call(with: request)
47+
let response = try await auth.backend.call(with: request)
4948
if let totpSessionInfo = response.totpSessionInfo {
5049
let secret = TOTPSecret(secretKey: totpSessionInfo.sharedSecretKey,
5150
hashingAlgorithm: totpSessionInfo.hashingAlgorithm,

0 commit comments

Comments
 (0)