Skip to content

Commit c497d1a

Browse files
committed
Rebase and through getIDToken...
1 parent e2620f4 commit c497d1a

File tree

3 files changed

+193
-102
lines changed

3 files changed

+193
-102
lines changed

FirebaseAuth/Sources/Swift/Auth/AuthWorker.swift

+75-3
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,8 @@ actor AuthWorker {
317317
#endif
318318
}
319319

320+
// MARK: User.swift implementations
321+
320322
func updateEmail(user: User,
321323
email: String?,
322324
password: String?) async throws {
@@ -373,6 +375,59 @@ actor AuthWorker {
373375
}
374376
}
375377

378+
#if os(iOS)
379+
/// Updates the phone number for the user. On success, the cached user profile data is updated.
380+
///
381+
/// Invoked asynchronously on the global work queue in the future.
382+
/// - Parameter credential: The new phone number credential corresponding to the phone
383+
/// number to be added to the Firebase account. If a phone number is already linked to the
384+
/// account, this new phone number will replace it.
385+
/// - Parameter isLinkOperation: Boolean value indicating whether or not this is a link
386+
/// operation.
387+
/// - Parameter completion: Optionally; the block invoked when the user profile change has
388+
/// finished.
389+
func updateOrLinkPhoneNumber(user: User, credential: PhoneAuthCredential,
390+
isLinkOperation: Bool) async throws {
391+
let accessToken = try await user.internalGetTokenAsync()
392+
393+
guard let configuration = user.auth?.requestConfiguration else {
394+
fatalError("Auth Internal Error: nil value for VerifyPhoneNumberRequest initializer")
395+
}
396+
switch credential.credentialKind {
397+
case .phoneNumber: fatalError("Internal Error: Missing verificationCode")
398+
case let .verification(verificationID, code):
399+
let operation = isLinkOperation ? AuthOperationType.link : AuthOperationType.update
400+
let request = VerifyPhoneNumberRequest(verificationID: verificationID,
401+
verificationCode: code,
402+
operation: operation,
403+
requestConfiguration: configuration)
404+
request.accessToken = accessToken
405+
do {
406+
let verifyResponse = try await AuthBackend.call(with: request)
407+
guard let idToken = verifyResponse.idToken,
408+
let refreshToken = verifyResponse.refreshToken else {
409+
fatalError("Internal Auth Error: missing token in internalUpdateOrLinkPhoneNumber")
410+
}
411+
user.tokenService = SecureTokenService(
412+
withRequestConfiguration: configuration,
413+
accessToken: idToken,
414+
accessTokenExpirationDate: verifyResponse.approximateExpirationDate,
415+
refreshToken: refreshToken
416+
)
417+
// Get account info to update cached user info.
418+
let userAccount = try await getAccountInfoRefreshingCache(user)
419+
user.isAnonymous = false
420+
if let error = user.updateKeychain() {
421+
throw error
422+
}
423+
} catch {
424+
user.signOutIfTokenIsInvalid(withError: error)
425+
throw error
426+
}
427+
}
428+
}
429+
#endif
430+
376431
/// Performs a setAccountInfo request by mutating the results of a getAccountInfo response,
377432
/// atomically in regards to other calls to this method.
378433
/// - Parameter changeBlock: A block responsible for mutating a template `SetAccountInfoRequest`
@@ -410,7 +465,7 @@ actor AuthWorker {
410465
/// Gets the users' account data from the server, updating our local values.
411466
/// - Parameter callback: Invoked when the request to getAccountInfo has completed, or when an
412467
/// error has been detected. Invoked asynchronously on the auth global work queue in the future.
413-
private func getAccountInfoRefreshingCache(_ user: User) async throws
468+
func getAccountInfoRefreshingCache(_ user: User) async throws
414469
-> GetAccountInfoResponseUser {
415470
let token = try await user.internalGetTokenAsync()
416471
let request = GetAccountInfoRequest(accessToken: token,
@@ -438,8 +493,7 @@ actor AuthWorker {
438493
guard user.uid == requestConfiguration.auth?.getUserID() else {
439494
throw AuthErrorUtils.userMismatchError()
440495
}
441-
// TODO: set tokenService migration
442-
496+
try await user.setTokenService(tokenService: user.tokenService)
443497
return authResult
444498
} catch {
445499
if (error as NSError).code == AuthErrorCode.userNotFound.rawValue {
@@ -449,6 +503,24 @@ actor AuthWorker {
449503
}
450504
}
451505

506+
#if os(iOS)
507+
func reauthenticate(with provider: FederatedAuthProvider,
508+
uiDelegate: AuthUIDelegate?) async throws -> AuthDataResult {
509+
let credential = try await provider.credential(with: uiDelegate)
510+
return try await reauthenticate(with: credential)
511+
}
512+
#endif
513+
514+
func getIDTokenResult(user: User,
515+
forcingRefresh forceRefresh: Bool) async throws -> AuthTokenResult {
516+
let token = try await user.internalGetTokenAsync(forceRefresh: forceRefresh)
517+
let tokenResult = try AuthTokenResult.tokenResult(token: token)
518+
AuthLog.logDebug(code: "I-AUT000017", message: "Actual token expiration date: " +
519+
"\(String(describing: tokenResult.expirationDate))," +
520+
"current date: \(Date())")
521+
return tokenResult
522+
}
523+
452524
/// Update the current user; initializing the user's internal properties correctly, and
453525
/// optionally saving the user to disk.
454526
///

FirebaseAuth/Sources/Swift/User/User.swift

+54-99
Original file line numberDiff line numberDiff line change
@@ -227,10 +227,16 @@ extension User: NSSecureCoding {}
227227
@objc(updatePhoneNumberCredential:completion:)
228228
open func updatePhoneNumber(_ credential: PhoneAuthCredential,
229229
completion: ((Error?) -> Void)? = nil) {
230-
kAuthGlobalWorkQueue.async {
231-
self.internalUpdateOrLinkPhoneNumber(credential: credential,
232-
isLinkOperation: false) { error in
233-
User.callInMainThreadWithError(callback: completion, error: error)
230+
Task {
231+
do {
232+
try await self.updatePhoneNumber(credential)
233+
await MainActor.run {
234+
completion?(nil)
235+
}
236+
} catch {
237+
await MainActor.run {
238+
completion?(error)
239+
}
234240
}
235241
}
236242
}
@@ -251,15 +257,9 @@ extension User: NSSecureCoding {}
251257
/// account this new phone number will replace it.
252258
@available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *)
253259
open func updatePhoneNumber(_ credential: PhoneAuthCredential) async throws {
254-
return try await withCheckedThrowingContinuation { continuation in
255-
self.updatePhoneNumber(credential) { error in
256-
if let error {
257-
continuation.resume(throwing: error)
258-
} else {
259-
continuation.resume()
260-
}
261-
}
262-
}
260+
try await auth.authWorker.updateOrLinkPhoneNumber(user: self,
261+
credential: credential,
262+
isLinkOperation: false)
263263
}
264264
#endif
265265

@@ -296,9 +296,16 @@ extension User: NSSecureCoding {}
296296
/// - Parameter completion: Optionally; the block invoked when the reload has finished. Invoked
297297
/// asynchronously on the main thread in the future.
298298
@objc open func reload(completion: ((Error?) -> Void)? = nil) {
299-
kAuthGlobalWorkQueue.async {
300-
self.getAccountInfoRefreshingCache { user, error in
301-
User.callInMainThreadWithError(callback: completion, error: error)
299+
Task {
300+
do {
301+
try await self.reload()
302+
await MainActor.run {
303+
completion?(nil)
304+
}
305+
} catch {
306+
await MainActor.run {
307+
completion?(error)
308+
}
302309
}
303310
}
304311
}
@@ -310,15 +317,7 @@ extension User: NSSecureCoding {}
310317
/// `updateEmail(to:)`.
311318
@available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *)
312319
open func reload() async throws {
313-
return try await withCheckedThrowingContinuation { continuation in
314-
self.reload { error in
315-
if let error {
316-
continuation.resume(throwing: error)
317-
} else {
318-
continuation.resume()
319-
}
320-
}
321-
}
320+
let _ = try await auth.authWorker.getAccountInfoRefreshingCache(self)
322321
}
323322

324323
/// Renews the user's authentication tokens by validating a fresh set of credentials supplied
@@ -418,15 +417,15 @@ extension User: NSSecureCoding {}
418417
open func reauthenticate(with provider: FederatedAuthProvider,
419418
uiDelegate: AuthUIDelegate?,
420419
completion: ((AuthDataResult?, Error?) -> Void)? = nil) {
421-
kAuthGlobalWorkQueue.async {
422-
Task {
423-
do {
424-
let credential = try await provider.credential(with: uiDelegate)
425-
self.reauthenticate(with: credential, completion: completion)
426-
} catch {
427-
if let completion {
428-
completion(nil, error)
429-
}
420+
Task {
421+
do {
422+
let result = try await reauthenticate(with: provider, uiDelegate: uiDelegate)
423+
await MainActor.run {
424+
completion?(result, nil)
425+
}
426+
} catch {
427+
await MainActor.run {
428+
completion?(nil, error)
430429
}
431430
}
432431
}
@@ -445,15 +444,7 @@ extension User: NSSecureCoding {}
445444
@discardableResult
446445
open func reauthenticate(with provider: FederatedAuthProvider,
447446
uiDelegate: AuthUIDelegate?) async throws -> AuthDataResult {
448-
return try await withCheckedThrowingContinuation { continuation in
449-
self.reauthenticate(with: provider, uiDelegate: uiDelegate) { result, error in
450-
if let result {
451-
continuation.resume(returning: result)
452-
} else if let error {
453-
continuation.resume(throwing: error)
454-
}
455-
}
456-
}
447+
return try await auth.authWorker.reauthenticate(with: provider, uiDelegate: uiDelegate)
457448
}
458449
#endif
459450

@@ -478,10 +469,15 @@ extension User: NSSecureCoding {}
478469
@objc(getIDTokenForcingRefresh:completion:)
479470
open func getIDTokenForcingRefresh(_ forceRefresh: Bool,
480471
completion: ((String?, Error?) -> Void)?) {
481-
getIDTokenResult(forcingRefresh: forceRefresh) { tokenResult, error in
482-
if let completion {
483-
DispatchQueue.main.async {
484-
completion(tokenResult?.token, error)
472+
Task {
473+
do {
474+
let tokenResult = try await getIDTokenResult(forcingRefresh: forceRefresh)
475+
await MainActor.run {
476+
completion?(tokenResult.token, nil)
477+
}
478+
} catch {
479+
await MainActor.run {
480+
completion?(nil, error)
485481
}
486482
}
487483
}
@@ -496,15 +492,7 @@ extension User: NSSecureCoding {}
496492
/// - Returns: The Firebase authentication token.
497493
@available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *)
498494
open func getIDToken(forcingRefresh forceRefresh: Bool = false) async throws -> String {
499-
return try await withCheckedThrowingContinuation { continuation in
500-
self.getIDTokenForcingRefresh(forceRefresh) { tokenResult, error in
501-
if let tokenResult {
502-
continuation.resume(returning: tokenResult)
503-
} else if let error {
504-
continuation.resume(throwing: error)
505-
}
506-
}
507-
}
495+
return try await getIDTokenResult(forcingRefresh: forceRefresh).token
508496
}
509497

510498
/// API included for compatibility with a mis-named Firebase 10 API.
@@ -518,13 +506,7 @@ extension User: NSSecureCoding {}
518506
/// asynchronously on the main thread in the future.
519507
@objc(getIDTokenResultWithCompletion:)
520508
open func getIDTokenResult(completion: ((AuthTokenResult?, Error?) -> Void)?) {
521-
getIDTokenResult(forcingRefresh: false) { tokenResult, error in
522-
if let completion {
523-
DispatchQueue.main.async {
524-
completion(tokenResult, error)
525-
}
526-
}
527-
}
509+
getIDTokenResult(forcingRefresh: false, completion: completion)
528510
}
529511

530512
/// Retrieves the Firebase authentication token, possibly refreshing it if it has expired.
@@ -539,34 +521,15 @@ extension User: NSSecureCoding {}
539521
@objc(getIDTokenResultForcingRefresh:completion:)
540522
open func getIDTokenResult(forcingRefresh: Bool,
541523
completion: ((AuthTokenResult?, Error?) -> Void)?) {
542-
kAuthGlobalWorkQueue.async {
543-
self.internalGetToken(forceRefresh: forcingRefresh) { token, error in
544-
var tokenResult: AuthTokenResult?
545-
if let token {
546-
do {
547-
tokenResult = try AuthTokenResult.tokenResult(token: token)
548-
AuthLog.logDebug(code: "I-AUT000017", message: "Actual token expiration date: " +
549-
"\(String(describing: tokenResult?.expirationDate))," +
550-
"current date: \(Date())")
551-
if let completion {
552-
DispatchQueue.main.async {
553-
completion(tokenResult, error)
554-
}
555-
}
556-
return
557-
} catch {
558-
if let completion {
559-
DispatchQueue.main.async {
560-
completion(tokenResult, error)
561-
}
562-
}
563-
return
564-
}
524+
Task {
525+
do {
526+
let tokenResult = try await getIDTokenResult(forcingRefresh: forcingRefresh)
527+
await MainActor.run {
528+
completion?(tokenResult, nil)
565529
}
566-
if let completion {
567-
DispatchQueue.main.async {
568-
completion(nil, error)
569-
}
530+
} catch {
531+
await MainActor.run {
532+
completion?(nil, error)
570533
}
571534
}
572535
}
@@ -582,15 +545,7 @@ extension User: NSSecureCoding {}
582545
@available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *)
583546
open func getIDTokenResult(forcingRefresh forceRefresh: Bool = false) async throws
584547
-> AuthTokenResult {
585-
return try await withCheckedThrowingContinuation { continuation in
586-
self.getIDTokenResult(forcingRefresh: forceRefresh) { tokenResult, error in
587-
if let tokenResult {
588-
continuation.resume(returning: tokenResult)
589-
} else if let error {
590-
continuation.resume(throwing: error)
591-
}
592-
}
593-
}
548+
try await auth.authWorker.getIDTokenResult(user: self, forcingRefresh: forceRefresh)
594549
}
595550

596551
/// Associates a user account from a third-party identity provider with this user and

0 commit comments

Comments
 (0)