Repository: firebase/firebase-ios-sdk (language: cpp)

Issue:
Crash when setting Auth settings
<!-- DO NOT DELETE
validate_template=true
template_path=.github/ISSUE_TEMPLATE/bug_report.md
-->
### Step 0: Are you in the right place?

  * For issues or feature requests related to __the code in this repository__
    file a Github issue.
    * If this is a __feature request__ please use the Feature Request template.
  * For general technical questions, post a question on [StackOverflow](http://stackoverflow.com/)
    with the `firebase` tag.
  * For general (non-iOS) Firebase discussion, use the [firebase-talk](https://groups.google.com/forum/#!forum/firebase-talk)
    google group.
  * For backend issues, console issues, and other non-SDK help that does not fall under one
    of the above categories, reach out to
    [Firebase Support](https://firebase.google.com/support/).
  * Once you've read this section and determined that your issue is appropriate for
    this repository, please delete this section.

### [REQUIRED] Step 1: Describe your environment

  * Xcode version: 12.4
  * Firebase SDK version: 7.7.0
  * Installation method: `Swift Package Manager`
  * Firebase Component: Auth

### [REQUIRED] Step 2: Describe the problem

```
2021-03-06 09:48:22.576728+0100 Echo Beta[9268:1286077] -[FIRAuthSettings copyWithZone:]: unrecognized selector sent to instance 0x283aa7570
2021-03-06 09:48:22.586123+0100 Echo Beta[9268:1286077] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[FIRAuthSettings copyWithZone:]: unrecognized selector sent to instance 0x283aa7570'
*** First throw call stack:
(0x1929999d8 0x1a6d1fb54 0x1928a9bbc 0x19299c01c 0x19299df8c 0x1a6d37180 0x103b6ca00 0x102b168b0 0x102a564b0 0x198f172c4 0x198f87228 0x198f87244 0x198f05694 0x198f056b8 0x19520af38 0x1947f6218 0x1947cf4b8 0x1947cf36c 0x19520af38 0x194ba0184 0x194ba04c8 0x194b9ee00 0x195245bc0 0x1952474e8 0x195222b0c 0x1952a5078 0x1952a9818 0x1952a0afc 0x192919bf0 0x192919af0 0x192918e38 0x1929133e0 0x192912ba0 0x1a967b598 0x1952042f4 0x195209874 0x102af3e98 0x1925f1568)
libc++abi.dylib: terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[FIRAuthSettings copyWithZone:]: unrecognized selector sent to instance 0x283aa7570'
terminating with uncaught exception of type NSException
```

#### Steps to reproduce:

This may be wrong, but the crash should not happen anyways when I for phone auth, I set isAppVerificationDisabledFor Testing

#### Relevant Code:

```
    #if BETA
    let settings = AuthSettings()
    settings.isAppVerificationDisabledForTesting = true
    Auth.auth().settings = settings
    #endif
```

Crash when setting Auth settings
<!-- DO NOT DELETE
validate_template=true
template_path=.github/ISSUE_TEMPLATE/bug_report.md
-->
### Step 0: Are you in the right place?

  * For issues or feature requests related to __the code in this repository__
    file a Github issue.
    * If this is a __feature request__ please use the Feature Request template.
  * For general technical questions, post a question on [StackOverflow](http://stackoverflow.com/)
    with the `firebase` tag.
  * For general (non-iOS) Firebase discussion, use the [firebase-talk](https://groups.google.com/forum/#!forum/firebase-talk)
    google group.
  * For backend issues, console issues, and other non-SDK help that does not fall under one
    of the above categories, reach out to
    [Firebase Support](https://firebase.google.com/support/).
  * Once you've read this section and determined that your issue is appropriate for
    this repository, please delete this section.

### [REQUIRED] Step 1: Describe your environment

  * Xcode version: 12.4
  * Firebase SDK version: 7.7.0
  * Installation method: `Swift Package Manager`
  * Firebase Component: Auth

### [REQUIRED] Step 2: Describe the problem

```
2021-03-06 09:48:22.576728+0100 Echo Beta[9268:1286077] -[FIRAuthSettings copyWithZone:]: unrecognized selector sent to instance 0x283aa7570
2021-03-06 09:48:22.586123+0100 Echo Beta[9268:1286077] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[FIRAuthSettings copyWithZone:]: unrecognized selector sent to instance 0x283aa7570'
*** First throw call stack:
(0x1929999d8 0x1a6d1fb54 0x1928a9bbc 0x19299c01c 0x19299df8c 0x1a6d37180 0x103b6ca00 0x102b168b0 0x102a564b0 0x198f172c4 0x198f87228 0x198f87244 0x198f05694 0x198f056b8 0x19520af38 0x1947f6218 0x1947cf4b8 0x1947cf36c 0x19520af38 0x194ba0184 0x194ba04c8 0x194b9ee00 0x195245bc0 0x1952474e8 0x195222b0c 0x1952a5078 0x1952a9818 0x1952a0afc 0x192919bf0 0x192919af0 0x192918e38 0x1929133e0 0x192912ba0 0x1a967b598 0x1952042f4 0x195209874 0x102af3e98 0x1925f1568)
libc++abi.dylib: terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[FIRAuthSettings copyWithZone:]: unrecognized selector sent to instance 0x283aa7570'
terminating with uncaught exception of type NSException
```

#### Steps to reproduce:

This may be wrong, but the crash should not happen anyways when I for phone auth, I set isAppVerificationDisabledFor Testing

#### Relevant Code:

```
    #if BETA
    let settings = AuthSettings()
    settings.isAppVerificationDisabledForTesting = true
    Auth.auth().settings = settings
    #endif
```



Discussion / hints:
I guess the correct way is 
```
Auth.auth().settings.isAppVerificationDisabledForTesting = true
```
Should I make the `settings` setter private in a PR?
Thanks @nidegen for the report and sorry for the crash! 

It looks like the `AuthSettings()` initializer was unintentionally surfaced in Swift despite being unavailable in Objective-C (we've seen this in other places as well, not explicitly marking it with `NS_UNAVAILABLE`). The code you've provided seems reasonable to me though from a usage standpoint, and removing the initializer is breaking change so it seems like we should fix the crash for now by properly implementing `copyWithZone:` and re-evaluate removing the initializer at a breaking change (if the Auth team prefers to hide it). 
I guess the correct way is 
```
Auth.auth().settings.isAppVerificationDisabledForTesting = true
```
Should I make the `settings` setter private in a PR?
Thanks @nidegen for the report and sorry for the crash! 

It looks like the `AuthSettings()` initializer was unintentionally surfaced in Swift despite being unavailable in Objective-C (we've seen this in other places as well, not explicitly marking it with `NS_UNAVAILABLE`). The code you've provided seems reasonable to me though from a usage standpoint, and removing the initializer is breaking change so it seems like we should fix the crash for now by properly implementing `copyWithZone:` and re-evaluate removing the initializer at a breaking change (if the Auth team prefers to hide it). 

Fix patch:
diff --git a/FirebaseAuth/CHANGELOG.md b/FirebaseAuth/CHANGELOG.md
index a310454a104..d540f6691ad 100644
--- a/FirebaseAuth/CHANGELOG.md
+++ b/FirebaseAuth/CHANGELOG.md
@@ -1,3 +1,6 @@
+# Unreleased
+- [fixed] Fixed a crash that occurred when assigning auth settings (#7670).
+
 # 7.8.0
 - [fixed] Fixed auth state sharing during first app launch. (#7472)
 
diff --git a/FirebaseAuth/Sources/Auth/FIRAuthSettings.m b/FirebaseAuth/Sources/Auth/FIRAuthSettings.m
index fd9c6cecee2..8715897c9be 100644
--- a/FirebaseAuth/Sources/Auth/FIRAuthSettings.m
+++ b/FirebaseAuth/Sources/Auth/FIRAuthSettings.m
@@ -28,6 +28,13 @@ - (instancetype)init {
   return self;
 }
 
+- (instancetype)copyWithZone:(NSZone *__unused _Nullable)zone {
+  // Auth settings are mutable, so always return a copy.
+  FIRAuthSettings *newSettings = [[FIRAuthSettings alloc] init];
+  newSettings.appVerificationDisabledForTesting = self.isAppVerificationDisabledForTesting;
+  return newSettings;
+}
+
 @end
 
 NS_ASSUME_NONNULL_END
diff --git a/FirebaseAuth/Sources/Public/FirebaseAuth/FIRAuthSettings.h b/FirebaseAuth/Sources/Public/FirebaseAuth/FIRAuthSettings.h
index 60ba71094b7..1746627bb21 100644
--- a/FirebaseAuth/Sources/Public/FirebaseAuth/FIRAuthSettings.h
+++ b/FirebaseAuth/Sources/Public/FirebaseAuth/FIRAuthSettings.h
@@ -22,7 +22,7 @@ NS_ASSUME_NONNULL_BEGIN
     @brief Determines settings related to an auth object.
  */
 NS_SWIFT_NAME(AuthSettings)
-@interface FIRAuthSettings : NSObject
+@interface FIRAuthSettings : NSObject <NSCopying>
 
 /** @property appVerificationDisabledForTesting
     @brief Flag to determine whether app verification should be disabled for testing or not.


Test patch: