Skip to content

Commit 486a0a0

Browse files
authored
[Auth] Fix delete action in sample app (#13554)
1 parent 76fcc90 commit 486a0a0

File tree

4 files changed

+56
-58
lines changed

4 files changed

+56
-58
lines changed

FirebaseAuth/Sources/Swift/User/User.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ extension User: NSSecureCoding {}
404404
}
405405

406406
/// Renews the user's authentication tokens by validating a fresh set of credentials supplied
407-
/// by the user and returns additional identity provider data.
407+
/// by the user and returns additional identity provider data.
408408
///
409409
/// If the user associated with the supplied credential is different from the current user,
410410
/// or if the validation of the supplied credentials fails; an error is returned and the current

FirebaseAuth/Tests/SampleSwift/AuthenticationExample/Models/AuthMenu.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ class AuthMenuData: DataSourceProvidable {
353353
customAuthDomainSection, appSection, oobSection, multifactorSection]
354354

355355
static var authLinkSections: [Section] {
356-
let allItems = AuthMenuData.sections.flatMap { $0.items }
356+
let allItems = [providerSection, emailPasswordSection, otherSection].flatMap { $0.items }
357357
let header = "Manage linking between providers"
358358
let footer =
359359
"Select an unchecked row to link the currently signed in user to that auth provider. To unlink the user from a linked provider, select its corresponding row marked with a checkmark."

FirebaseAuth/Tests/SampleSwift/AuthenticationExample/ViewControllers/AccountLinkingViewController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,7 @@ extension AccountLinkingViewController: ASAuthorizationControllerDelegate,
508508
return
509509
}
510510

511-
let credential = OAuthProvider.credential(withProviderID: "apple.com",
511+
let credential = OAuthProvider.credential(providerID: .apple,
512512
idToken: idTokenString,
513513
rawNonce: nonce)
514514
// Once we have created the above `credential`, we can link accounts to it.

FirebaseAuth/Tests/SampleSwift/AuthenticationExample/ViewControllers/UserViewController.swift

Lines changed: 53 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -226,31 +226,46 @@ class UserViewController: UIViewController, DataSourceProviderDelegate {
226226

227227
// MARK: - Sign in with Apple Token Revocation Flow
228228

229-
// For Sign in with Apple
230-
private var currentNonce: String?
229+
/// Used for Sign in with Apple token revocation flow.
230+
private var continuation: CheckedContinuation<ASAuthorizationAppleIDCredential, Error>?
231231

232-
// [START token_revocation_deleteuser]
233232
private func deleteCurrentUser() {
234-
do {
235-
let nonce = try CryptoUtils.randomNonceString()
236-
currentNonce = nonce
237-
let appleIDProvider = ASAuthorizationAppleIDProvider()
238-
let request = appleIDProvider.createRequest()
239-
request.requestedScopes = [.fullName, .email]
240-
request.nonce = CryptoUtils.sha256(nonce)
241-
242-
let authorizationController = ASAuthorizationController(authorizationRequests: [request])
243-
authorizationController.delegate = self
244-
authorizationController.presentationContextProvider = self
245-
authorizationController.performRequests()
246-
} catch {
247-
// In the unlikely case that nonce generation fails, show error view.
248-
displayError(error)
233+
Task {
234+
guard let user else { return }
235+
do {
236+
let needsTokenRevocation = user.providerData
237+
.contains { $0.providerID == AuthProviderID.apple.rawValue }
238+
if needsTokenRevocation {
239+
let appleIDCredential = try await signInWithApple()
240+
241+
guard let appleIDToken = appleIDCredential.identityToken else {
242+
print("Unable to fetch identify token.")
243+
return
244+
}
245+
guard let idTokenString = String(data: appleIDToken, encoding: .utf8) else {
246+
print("Unable to serialise token string from data: \(appleIDToken.debugDescription)")
247+
return
248+
}
249+
250+
let nonce = try CryptoUtils.randomNonceString()
251+
let credential = OAuthProvider.credential(providerID: .apple,
252+
idToken: idTokenString,
253+
rawNonce: nonce)
254+
255+
try await user.reauthenticate(with: credential)
256+
if
257+
let authorizationCode = appleIDCredential.authorizationCode,
258+
let authCodeString = String(data: authorizationCode, encoding: .utf8) {
259+
try await Auth.auth().revokeToken(withAuthorizationCode: authCodeString)
260+
}
261+
}
262+
try await user.delete()
263+
} catch {
264+
displayError(error)
265+
}
249266
}
250267
}
251268

252-
// [END token_revocation_deleteuser]
253-
254269
// MARK: - Private Helpers
255270

256271
private func getVerificationCode() async throws -> String {
@@ -343,48 +358,31 @@ extension UserViewController: ASAuthorizationControllerDelegate,
343358
ASAuthorizationControllerPresentationContextProviding {
344359
// MARK: ASAuthorizationControllerDelegate
345360

346-
// [START token_revocation]
347-
func authorizationController(controller: ASAuthorizationController,
348-
didCompleteWithAuthorization authorization: ASAuthorization) {
349-
guard let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential
350-
else {
351-
print("Unable to retrieve AppleIDCredential")
352-
return
353-
}
354-
355-
guard let _ = currentNonce else {
356-
fatalError("Invalid state: A login callback was received, but no login request was sent.")
357-
}
358-
359-
guard let appleAuthCode = appleIDCredential.authorizationCode else {
360-
print("Unable to fetch authorization code")
361-
return
362-
}
361+
func signInWithApple() async throws -> ASAuthorizationAppleIDCredential {
362+
return try await withCheckedThrowingContinuation { continuation in
363+
self.continuation = continuation
364+
let appleIDProvider = ASAuthorizationAppleIDProvider()
365+
let request = appleIDProvider.createRequest()
366+
request.requestedScopes = [.fullName, .email]
363367

364-
guard let authCodeString = String(data: appleAuthCode, encoding: .utf8) else {
365-
print("Unable to serialize auth code string from data: \(appleAuthCode.debugDescription)")
366-
return
368+
let authorizationController = ASAuthorizationController(authorizationRequests: [request])
369+
authorizationController.delegate = self
370+
authorizationController.performRequests()
367371
}
372+
}
368373

369-
Task {
370-
do {
371-
try await AppManager.shared.auth().revokeToken(withAuthorizationCode: authCodeString)
372-
try await user?.delete()
373-
self.updateUI()
374-
} catch {
375-
self.displayError(error)
376-
}
374+
func authorizationController(controller: ASAuthorizationController,
375+
didCompleteWithAuthorization authorization: ASAuthorization) {
376+
if case let appleIDCredential as ASAuthorizationAppleIDCredential = authorization.credential {
377+
continuation?.resume(returning: appleIDCredential)
378+
} else {
379+
fatalError("Unexpected authorization credential type.")
377380
}
378381
}
379382

380-
// [END token_revocation]
381-
382383
func authorizationController(controller: ASAuthorizationController,
383-
didCompleteWithError error: any Error) {
384-
// Ensure that you have:
385-
// - enabled `Sign in with Apple` on the Firebase console
386-
// - added the `Sign in with Apple` capability for this project
387-
print("Sign in with Apple failed: \(error)")
384+
didCompleteWithError error: Error) {
385+
continuation?.resume(throwing: error)
388386
}
389387

390388
// MARK: ASAuthorizationControllerPresentationContextProviding

0 commit comments

Comments
 (0)