Skip to content

Commit 7725367

Browse files
docs: update documentation
1 parent 6e0e490 commit 7725367

File tree

1 file changed

+138
-24
lines changed

1 file changed

+138
-24
lines changed

FirebaseSwiftUI/README.md

Lines changed: 138 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,22 @@ The default views support:
266266
- **Sign in with Twitter**
267267
- **Generic OAuth Providers** (GitHub, Microsoft, Yahoo, or custom OIDC)
268268

269+
### Reauthentication in Default Views
270+
271+
Sensitive operations like deleting accounts, updating passwords, or unenrolling MFA factors require recent authentication. When using default views, reauthentication is handled automatically based on the user's sign-in provider.
272+
273+
#### Automatic Reauthentication Behavior
274+
275+
When a sensitive operation requires reauthentication, the default views automatically:
276+
277+
- **OAuth Providers (Google, Apple, Facebook, Twitter, etc.)**: Display an alert asking the user to confirm, then automatically obtain fresh credentials and complete the operation.
278+
279+
- **Email/Password**: Present a sheet prompting the user to enter their password before continuing.
280+
281+
- **Phone**: Show an alert explaining verification is needed, then present a sheet for SMS code verification.
282+
283+
The operation automatically retries after successful reauthentication. No additional code is required when using `AuthPickerView` or the built-in account management views (`UpdatePasswordView`, `SignedInView`, etc.).
284+
269285
---
270286

271287
## Usage with Custom Views
@@ -635,6 +651,76 @@ When building custom views, you need to handle several things yourself that `Aut
635651
3. **Anonymous User Upgrades**: Handle the linking of anonymous accounts if `shouldAutoUpgradeAnonymousUsers` is enabled
636652
4. **Navigation State**: Manage navigation between different auth screens (phone verification, password recovery, etc.)
637653
5. **Loading States**: Show loading indicators during async authentication operations by observing `authService.authenticationState`
654+
6. **Reauthentication**: Handle reauthentication errors for sensitive operations (see [Reauthentication in Custom Views](#reauthentication-in-custom-views) below)
655+
656+
### Reauthentication in Custom Views
657+
658+
When building custom views, handle reauthentication by catching specific errors and implementing your own flow. Sensitive operations throw three types of reauthentication errors, each containing context information.
659+
660+
#### Implementation Patterns
661+
662+
**OAuth Providers (Google, Apple, Facebook, Twitter, etc.):**
663+
664+
Catch the error and call `reauthenticate(context:)` which automatically handles the OAuth flow:
665+
666+
```swift
667+
do {
668+
try await authService.deleteUser()
669+
} catch let error as AuthServiceError {
670+
if case .oauthReauthenticationRequired(let context) = error {
671+
try await authService.reauthenticate(context: context)
672+
try await authService.deleteUser() // Retry operation
673+
}
674+
}
675+
```
676+
677+
**Email/Password:**
678+
679+
Catch the error, prompt for password, create credential, and call `reauthenticate(with:)`:
680+
681+
```swift
682+
do {
683+
try await authService.updatePassword(to: newPassword)
684+
} catch let error as AuthServiceError {
685+
if case .emailReauthenticationRequired(let context) = error {
686+
// Show your password prompt UI
687+
let password = await promptUserForPassword()
688+
let credential = EmailAuthProvider.credential(
689+
withEmail: context.email,
690+
password: password
691+
)
692+
try await authService.reauthenticate(with: credential)
693+
try await authService.updatePassword(to: newPassword) // Retry
694+
}
695+
}
696+
```
697+
698+
**Phone:**
699+
700+
Catch the error, verify phone, create credential, and call `reauthenticate(with:)`:
701+
702+
```swift
703+
do {
704+
try await authService.deleteUser()
705+
} catch let error as AuthServiceError {
706+
if case .phoneReauthenticationRequired(let context) = error {
707+
// Send verification code
708+
let verificationId = try await authService.verifyPhoneNumber(
709+
phoneNumber: context.phoneNumber
710+
)
711+
// Show your SMS code input UI
712+
let code = await promptUserForSMSCode()
713+
let credential = PhoneAuthProvider.provider().credential(
714+
withVerificationID: verificationId,
715+
verificationCode: code
716+
)
717+
try await authService.reauthenticate(with: credential)
718+
try await authService.deleteUser() // Retry
719+
}
720+
}
721+
```
722+
723+
All reauthentication context objects include a `.displayMessage` property for user-facing text.
638724

639725
### Custom OAuth Providers
640726

@@ -767,13 +853,12 @@ Creates a new `AuthService` instance.
767853
##### Email Authentication
768854

769855
```swift
770-
public func withEmailSignIn(_ provider: EmailProviderSwift? = nil, onTap: @escaping () -> Void = {}) -> AuthService
856+
public func withEmailSignIn(onTap: @escaping () -> Void = {}) -> AuthService
771857
```
772858

773859
Enables email authentication and will render email sign-in directly within the AuthPickerView (default Views), email link sign-in is rendered as a button. When calling `AuthService.renderButtons()`, email link sign-in button is rendered. `onTap` custom callback (i.e where to navigate when tapped) allows user to control what happens when tapped. Default behavior in AuthPickerView is to push the user to email link sign-in default View.
774860

775861
**Parameters:**
776-
- `provider`: An optional instance of `EmailProviderSwift`. If not provided, a default instance will be created.
777862
- `onTap`: A callback that will be executed when the email button is tapped.
778863

779864
**Example:**
@@ -1213,12 +1298,15 @@ Updates the current user's photo URL.
12131298
public func updatePassword(to password: String) async throws
12141299
```
12151300

1216-
Updates the current user's password. May require recent authentication.
1301+
Updates the current user's password. This is a sensitive operation that may require recent authentication.
12171302

12181303
**Parameters:**
12191304
- `password`: New password
12201305

1221-
**Throws:** `AuthServiceError.noCurrentUser` or Firebase Auth errors
1306+
**Throws:**
1307+
- `AuthServiceError.noCurrentUser` if no user is signed in
1308+
- Reauthentication errors (`emailReauthenticationRequired`, `phoneReauthenticationRequired`, or `oauthReauthenticationRequired`) if recent authentication is required - see [Reauthentication](#reauthentication-in-default-views)
1309+
- Firebase Auth errors
12221310

12231311
---
12241312

@@ -1240,7 +1328,42 @@ Sends a verification email to the current user's email address.
12401328
public func deleteUser() async throws
12411329
```
12421330

1243-
Deletes the current user's account. May require recent authentication.
1331+
Deletes the current user's account. This is a sensitive operation that requires recent authentication.
1332+
1333+
**Throws:**
1334+
- `AuthServiceError.noCurrentUser` if no user is signed in
1335+
- Reauthentication errors (`emailReauthenticationRequired`, `phoneReauthenticationRequired`, or `oauthReauthenticationRequired`) if recent authentication is required - see [Reauthentication](#reauthentication-in-default-views)
1336+
- Firebase Auth errors
1337+
1338+
---
1339+
1340+
##### Reauthenticate with OAuth Provider
1341+
1342+
```swift
1343+
public func reauthenticate(context: OAuthReauthContext) async throws
1344+
```
1345+
1346+
Reauthenticates the current user with an OAuth provider (Google, Apple, Facebook, Twitter, etc.). Automatically locates the registered provider, obtains fresh credentials, and completes reauthentication.
1347+
1348+
**Parameters:**
1349+
- `context`: The reauth context from `oauthReauthenticationRequired` error
1350+
1351+
**Throws:** `AuthServiceError.noCurrentUser` or `AuthServiceError.providerNotFound`
1352+
1353+
**Note:** Only works for OAuth providers. For email/phone, use `reauthenticate(with:)`.
1354+
1355+
---
1356+
1357+
##### Reauthenticate with Credential
1358+
1359+
```swift
1360+
public func reauthenticate(with credential: AuthCredential) async throws
1361+
```
1362+
1363+
Reauthenticates the current user with a pre-obtained authentication credential. Use for email/password or phone authentication.
1364+
1365+
**Parameters:**
1366+
- `credential`: The authentication credential (from `EmailAuthProvider` or `PhoneAuthProvider`)
12441367

12451368
**Throws:** `AuthServiceError.noCurrentUser` or Firebase Auth errors
12461369

@@ -1423,22 +1546,6 @@ Navigator for managing navigation routes in default views.
14231546

14241547
---
14251548

1426-
```swift
1427-
public var passwordPrompt: PasswordPromptCoordinator
1428-
```
1429-
A coordinator that manages password prompt dialogs during reauthentication flows for the email provider.
1430-
1431-
Users can provide a custom `PasswordPromptCoordinator` instance when initializing `EmailProviderSwift` to customize password prompting behavior:
1432-
1433-
```swift
1434-
let customPrompt = PasswordPromptCoordinator()
1435-
authService.withEmailSignIn(EmailProviderSwift(passwordPrompt: customPrompt))
1436-
```
1437-
1438-
**Default Behavior:** If no custom coordinator is provided, a default `PasswordPromptCoordinator()` instance is created automatically. The default coordinator displays a modal sheet that prompts the user to enter their password when reauthentication is required for sensitive operations (e.g., updating email, deleting account).
1439-
1440-
---
1441-
14421549
```swift
14431550
public var authView: AuthView?
14441551
```
@@ -1539,9 +1646,14 @@ public enum AuthServiceError: Error {
15391646
Errors specific to `AuthService` operations.
15401647

15411648
**Reauthentication Errors:**
1542-
- `oauthReauthenticationRequired`: For OAuth providers like Google, Apple, Facebook, Twitter. Pass the context to `authService.reauthenticate(context:)`.
1543-
- `emailReauthenticationRequired`: For email/password authentication. Must handle password prompt externally.
1544-
- `phoneReauthenticationRequired`: For phone authentication. Must handle SMS verification flow externally.
1649+
1650+
Thrown by sensitive operations when Firebase requires recent authentication. Each includes context information:
1651+
1652+
- **`oauthReauthenticationRequired(context: OAuthReauthContext)`**: OAuth providers. Context contains `providerId`, `providerName`, and `displayMessage`. Pass to `reauthenticate(context:)`.
1653+
1654+
- **`emailReauthenticationRequired(context: EmailReauthContext)`**: Email/password provider. Context contains `email` and `displayMessage`. Prompt for password, then call `reauthenticate(with:)`.
1655+
1656+
- **`phoneReauthenticationRequired(context: PhoneReauthContext)`**: Phone provider. Context contains `phoneNumber` and `displayMessage`. Handle SMS verification, then call `reauthenticate(with:)`.
15451657

15461658
---
15471659

@@ -1559,6 +1671,8 @@ Errors specific to `AuthService` operations.
15591671

15601672
6. **Provider-specific setup**: Some providers (Google, Facebook) require additional configuration in AppDelegate or Info.plist. See the [sample app](https://github.com/firebase/FirebaseUI-iOS/tree/main/samples/swiftui) for examples.
15611673

1674+
7. **Handle reauthentication**: Default views handle reauthentication automatically. For custom views, catch and handle reauthentication errors when performing sensitive operations like `deleteUser()`, `updatePassword()`, and `unenrollMFA()`. See [Reauthentication in Custom Views](#reauthentication-in-custom-views).
1675+
15621676
---
15631677

15641678
## Additional Resources

0 commit comments

Comments
 (0)