We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
TFA with Fido2 privacy intrution by requiring attestation
**Describe the bug**
Can't register TFA with a FIDO key without device attestation, making this feature unusable for privacy conscious developers.

**Expected behavior**
Respect users privacy, when registering FIDO keys by not requiring attestation. Most sites work without attestation pip should work without as well.

**To Reproduce**
- With any Yubikey supporting Fido2
- With Firefox (92.0 (64-Bit)) go to https://pypi.org/manage/account/webauthn-provision
- Try registering a Fido2 device
- Wait for Firefox to bring up its privacy warning
- Select "anonymize anyway" and continue
- Pip says "Registration rejected. Error: Authenticator attestation is required.."

![Firefox fido2 pip](https://user-images.githubusercontent.com/82288872/134816676-9feb37a0-0519-46a8-a1d9-3acb068ca760.png)

**My Platform**
macOS 11.6
Firefox 92.0 (64-Bit)
Yubikey blue USB-A with NFC


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `warehouse/utils/webauthn.py`
Content:
```
1 # Licensed under the Apache License, Version 2.0 (the "License");
2 # you may not use this file except in compliance with the License.
3 # You may obtain a copy of the License at
4 #
5 # http://www.apache.org/licenses/LICENSE-2.0
6 #
7 # Unless required by applicable law or agreed to in writing, software
8 # distributed under the License is distributed on an "AS IS" BASIS,
9 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 # See the License for the specific language governing permissions and
11 # limitations under the License.
12 
13 import base64
14 import os
15 
16 import webauthn as pywebauthn
17 
18 from webauthn.webauthn import (
19     AuthenticationRejectedException as _AuthenticationRejectedException,
20     RegistrationRejectedException as _RegistrationRejectedException,
21 )
22 
23 
24 class AuthenticationRejectedException(Exception):
25     pass
26 
27 
28 class RegistrationRejectedException(Exception):
29     pass
30 
31 
32 WebAuthnCredential = pywebauthn.WebAuthnCredential
33 
34 
35 def _get_webauthn_users(user, *, rp_id):
36     """
37     Returns a webauthn.WebAuthnUser instance corresponding
38     to the given user model, with properties suitable for
39     usage within the webauthn API.
40     """
41     return [
42         pywebauthn.WebAuthnUser(
43             str(user.id),
44             user.username,
45             user.name or user.username,
46             None,
47             credential.credential_id,
48             credential.public_key,
49             credential.sign_count,
50             rp_id,
51         )
52         for credential in user.webauthn
53     ]
54 
55 
56 def _webauthn_b64decode(encoded):
57     padding = "=" * (len(encoded) % 4)
58     return base64.urlsafe_b64decode(encoded + padding)
59 
60 
61 def _webauthn_b64encode(source):
62     return base64.urlsafe_b64encode(source).rstrip(b"=")
63 
64 
65 def generate_webauthn_challenge():
66     """
67     Returns a random challenge suitable for use within
68     Webauthn's credential and configuration option objects.
69 
70     See: https://w3c.github.io/webauthn/#cryptographic-challenges
71     """
72     # NOTE: Webauthn recommends at least 16 bytes of entropy,
73     # we go with 32 because it doesn't cost us anything.
74     return _webauthn_b64encode(os.urandom(32)).decode()
75 
76 
77 def get_credential_options(user, *, challenge, rp_name, rp_id):
78     """
79     Returns a dictionary of options for credential creation
80     on the client side.
81     """
82     options = pywebauthn.WebAuthnMakeCredentialOptions(
83         challenge,
84         rp_name,
85         rp_id,
86         str(user.id),
87         user.username,
88         user.name or user.username,
89         None,
90         user_verification="discouraged",
91     )
92 
93     return options.registration_dict
94 
95 
96 def get_assertion_options(user, *, challenge, rp_id):
97     """
98     Returns a dictionary of options for assertion retrieval
99     on the client side.
100     """
101     options = pywebauthn.WebAuthnAssertionOptions(
102         _get_webauthn_users(user, rp_id=rp_id), challenge
103     )
104 
105     return options.assertion_dict
106 
107 
108 def verify_registration_response(response, challenge, *, rp_id, origin):
109     """
110     Validates the challenge and attestation information
111     sent from the client during device registration.
112 
113     Returns a WebAuthnCredential on success.
114     Raises RegistrationRejectedException on failire.
115     """
116     # NOTE: We re-encode the challenge below, because our
117     # response's clientData.challenge is encoded twice:
118     # first for the entire clientData payload, and then again
119     # for the individual challenge.
120     encoded_challenge = _webauthn_b64encode(challenge.encode()).decode()
121     response = pywebauthn.WebAuthnRegistrationResponse(
122         rp_id, origin, response, encoded_challenge, self_attestation_permitted=True
123     )
124     try:
125         return response.verify()
126     except _RegistrationRejectedException as e:
127         raise RegistrationRejectedException(str(e))
128 
129 
130 def verify_assertion_response(assertion, *, challenge, user, origin, rp_id):
131     """
132     Validates the challenge and assertion information
133     sent from the client during authentication.
134 
135     Returns an updated signage count on success.
136     Raises AuthenticationRejectedException on failure.
137     """
138     webauthn_users = _get_webauthn_users(user, rp_id=rp_id)
139     cred_ids = [cred.credential_id for cred in webauthn_users]
140     encoded_challenge = _webauthn_b64encode(challenge.encode()).decode()
141 
142     for webauthn_user in webauthn_users:
143         response = pywebauthn.WebAuthnAssertionResponse(
144             webauthn_user,
145             assertion,
146             encoded_challenge,
147             origin,
148             allow_credentials=cred_ids,
149         )
150         try:
151             return (webauthn_user.credential_id, response.verify())
152         except _AuthenticationRejectedException:
153             pass
154 
155     # If we exit the loop, then we've failed to verify the assertion against
156     # any of the user's WebAuthn credentials. Fail.
157     raise AuthenticationRejectedException("Invalid WebAuthn credential")
158
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/warehouse/utils/webauthn.py b/warehouse/utils/webauthn.py
--- a/warehouse/utils/webauthn.py
+++ b/warehouse/utils/webauthn.py
@@ -87,6 +87,7 @@
         user.username,
         user.name or user.username,
         None,
+        attestation=None,
         user_verification="discouraged",
     )
 
@@ -119,7 +120,12 @@
     # for the individual challenge.
     encoded_challenge = _webauthn_b64encode(challenge.encode()).decode()
     response = pywebauthn.WebAuthnRegistrationResponse(
-        rp_id, origin, response, encoded_challenge, self_attestation_permitted=True
+        rp_id,
+        origin,
+        response,
+        encoded_challenge,
+        self_attestation_permitted=True,
+        none_attestation_permitted=True,
     )
     try:
         return response.verify()

{"golden_diff": "diff --git a/warehouse/utils/webauthn.py b/warehouse/utils/webauthn.py\n--- a/warehouse/utils/webauthn.py\n+++ b/warehouse/utils/webauthn.py\n@@ -87,6 +87,7 @@\n         user.username,\n         user.name or user.username,\n         None,\n+        attestation=None,\n         user_verification=\"discouraged\",\n     )\n \n@@ -119,7 +120,12 @@\n     # for the individual challenge.\n     encoded_challenge = _webauthn_b64encode(challenge.encode()).decode()\n     response = pywebauthn.WebAuthnRegistrationResponse(\n-        rp_id, origin, response, encoded_challenge, self_attestation_permitted=True\n+        rp_id,\n+        origin,\n+        response,\n+        encoded_challenge,\n+        self_attestation_permitted=True,\n+        none_attestation_permitted=True,\n     )\n     try:\n         return response.verify()\n", "issue": "TFA with Fido2 privacy intrution by requiring attestation\n**Describe the bug**\r\nCan't register TFA with a FIDO key without device attestation, making this feature unusable for privacy conscious developers.\r\n\r\n**Expected behavior**\r\nRespect users privacy, when registering FIDO keys by not requiring attestation. Most sites work without attestation pip should work without as well.\r\n\r\n**To Reproduce**\r\n- With any Yubikey supporting Fido2\r\n- With Firefox (92.0 (64-Bit)) go to https://pypi.org/manage/account/webauthn-provision\r\n- Try registering a Fido2 device\r\n- Wait for Firefox to bring up its privacy warning\r\n- Select \"anonymize anyway\" and continue\r\n- Pip says \"Registration rejected. Error: Authenticator attestation is required..\"\r\n\r\n![Firefox fido2 pip](https://user-images.githubusercontent.com/82288872/134816676-9feb37a0-0519-46a8-a1d9-3acb068ca760.png)\r\n\r\n**My Platform**\r\nmacOS 11.6\r\nFirefox 92.0 (64-Bit)\r\nYubikey blue USB-A with NFC\r\n\n", "before_files": [{"content": "# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport base64\nimport os\n\nimport webauthn as pywebauthn\n\nfrom webauthn.webauthn import (\n    AuthenticationRejectedException as _AuthenticationRejectedException,\n    RegistrationRejectedException as _RegistrationRejectedException,\n)\n\n\nclass AuthenticationRejectedException(Exception):\n    pass\n\n\nclass RegistrationRejectedException(Exception):\n    pass\n\n\nWebAuthnCredential = pywebauthn.WebAuthnCredential\n\n\ndef _get_webauthn_users(user, *, rp_id):\n    \"\"\"\n    Returns a webauthn.WebAuthnUser instance corresponding\n    to the given user model, with properties suitable for\n    usage within the webauthn API.\n    \"\"\"\n    return [\n        pywebauthn.WebAuthnUser(\n            str(user.id),\n            user.username,\n            user.name or user.username,\n            None,\n            credential.credential_id,\n            credential.public_key,\n            credential.sign_count,\n            rp_id,\n        )\n        for credential in user.webauthn\n    ]\n\n\ndef _webauthn_b64decode(encoded):\n    padding = \"=\" * (len(encoded) % 4)\n    return base64.urlsafe_b64decode(encoded + padding)\n\n\ndef _webauthn_b64encode(source):\n    return base64.urlsafe_b64encode(source).rstrip(b\"=\")\n\n\ndef generate_webauthn_challenge():\n    \"\"\"\n    Returns a random challenge suitable for use within\n    Webauthn's credential and configuration option objects.\n\n    See: https://w3c.github.io/webauthn/#cryptographic-challenges\n    \"\"\"\n    # NOTE: Webauthn recommends at least 16 bytes of entropy,\n    # we go with 32 because it doesn't cost us anything.\n    return _webauthn_b64encode(os.urandom(32)).decode()\n\n\ndef get_credential_options(user, *, challenge, rp_name, rp_id):\n    \"\"\"\n    Returns a dictionary of options for credential creation\n    on the client side.\n    \"\"\"\n    options = pywebauthn.WebAuthnMakeCredentialOptions(\n        challenge,\n        rp_name,\n        rp_id,\n        str(user.id),\n        user.username,\n        user.name or user.username,\n        None,\n        user_verification=\"discouraged\",\n    )\n\n    return options.registration_dict\n\n\ndef get_assertion_options(user, *, challenge, rp_id):\n    \"\"\"\n    Returns a dictionary of options for assertion retrieval\n    on the client side.\n    \"\"\"\n    options = pywebauthn.WebAuthnAssertionOptions(\n        _get_webauthn_users(user, rp_id=rp_id), challenge\n    )\n\n    return options.assertion_dict\n\n\ndef verify_registration_response(response, challenge, *, rp_id, origin):\n    \"\"\"\n    Validates the challenge and attestation information\n    sent from the client during device registration.\n\n    Returns a WebAuthnCredential on success.\n    Raises RegistrationRejectedException on failire.\n    \"\"\"\n    # NOTE: We re-encode the challenge below, because our\n    # response's clientData.challenge is encoded twice:\n    # first for the entire clientData payload, and then again\n    # for the individual challenge.\n    encoded_challenge = _webauthn_b64encode(challenge.encode()).decode()\n    response = pywebauthn.WebAuthnRegistrationResponse(\n        rp_id, origin, response, encoded_challenge, self_attestation_permitted=True\n    )\n    try:\n        return response.verify()\n    except _RegistrationRejectedException as e:\n        raise RegistrationRejectedException(str(e))\n\n\ndef verify_assertion_response(assertion, *, challenge, user, origin, rp_id):\n    \"\"\"\n    Validates the challenge and assertion information\n    sent from the client during authentication.\n\n    Returns an updated signage count on success.\n    Raises AuthenticationRejectedException on failure.\n    \"\"\"\n    webauthn_users = _get_webauthn_users(user, rp_id=rp_id)\n    cred_ids = [cred.credential_id for cred in webauthn_users]\n    encoded_challenge = _webauthn_b64encode(challenge.encode()).decode()\n\n    for webauthn_user in webauthn_users:\n        response = pywebauthn.WebAuthnAssertionResponse(\n            webauthn_user,\n            assertion,\n            encoded_challenge,\n            origin,\n            allow_credentials=cred_ids,\n        )\n        try:\n            return (webauthn_user.credential_id, response.verify())\n        except _AuthenticationRejectedException:\n            pass\n\n    # If we exit the loop, then we've failed to verify the assertion against\n    # any of the user's WebAuthn credentials. Fail.\n    raise AuthenticationRejectedException(\"Invalid WebAuthn credential\")\n", "path": "warehouse/utils/webauthn.py"}], "after_files": [{"content": "# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport base64\nimport os\n\nimport webauthn as pywebauthn\n\nfrom webauthn.webauthn import (\n    AuthenticationRejectedException as _AuthenticationRejectedException,\n    RegistrationRejectedException as _RegistrationRejectedException,\n)\n\n\nclass AuthenticationRejectedException(Exception):\n    pass\n\n\nclass RegistrationRejectedException(Exception):\n    pass\n\n\nWebAuthnCredential = pywebauthn.WebAuthnCredential\n\n\ndef _get_webauthn_users(user, *, rp_id):\n    \"\"\"\n    Returns a webauthn.WebAuthnUser instance corresponding\n    to the given user model, with properties suitable for\n    usage within the webauthn API.\n    \"\"\"\n    return [\n        pywebauthn.WebAuthnUser(\n            str(user.id),\n            user.username,\n            user.name or user.username,\n            None,\n            credential.credential_id,\n            credential.public_key,\n            credential.sign_count,\n            rp_id,\n        )\n        for credential in user.webauthn\n    ]\n\n\ndef _webauthn_b64decode(encoded):\n    padding = \"=\" * (len(encoded) % 4)\n    return base64.urlsafe_b64decode(encoded + padding)\n\n\ndef _webauthn_b64encode(source):\n    return base64.urlsafe_b64encode(source).rstrip(b\"=\")\n\n\ndef generate_webauthn_challenge():\n    \"\"\"\n    Returns a random challenge suitable for use within\n    Webauthn's credential and configuration option objects.\n\n    See: https://w3c.github.io/webauthn/#cryptographic-challenges\n    \"\"\"\n    # NOTE: Webauthn recommends at least 16 bytes of entropy,\n    # we go with 32 because it doesn't cost us anything.\n    return _webauthn_b64encode(os.urandom(32)).decode()\n\n\ndef get_credential_options(user, *, challenge, rp_name, rp_id):\n    \"\"\"\n    Returns a dictionary of options for credential creation\n    on the client side.\n    \"\"\"\n    options = pywebauthn.WebAuthnMakeCredentialOptions(\n        challenge,\n        rp_name,\n        rp_id,\n        str(user.id),\n        user.username,\n        user.name or user.username,\n        None,\n        attestation=None,\n        user_verification=\"discouraged\",\n    )\n\n    return options.registration_dict\n\n\ndef get_assertion_options(user, *, challenge, rp_id):\n    \"\"\"\n    Returns a dictionary of options for assertion retrieval\n    on the client side.\n    \"\"\"\n    options = pywebauthn.WebAuthnAssertionOptions(\n        _get_webauthn_users(user, rp_id=rp_id), challenge\n    )\n\n    return options.assertion_dict\n\n\ndef verify_registration_response(response, challenge, *, rp_id, origin):\n    \"\"\"\n    Validates the challenge and attestation information\n    sent from the client during device registration.\n\n    Returns a WebAuthnCredential on success.\n    Raises RegistrationRejectedException on failire.\n    \"\"\"\n    # NOTE: We re-encode the challenge below, because our\n    # response's clientData.challenge is encoded twice:\n    # first for the entire clientData payload, and then again\n    # for the individual challenge.\n    encoded_challenge = _webauthn_b64encode(challenge.encode()).decode()\n    response = pywebauthn.WebAuthnRegistrationResponse(\n        rp_id,\n        origin,\n        response,\n        encoded_challenge,\n        self_attestation_permitted=True,\n        none_attestation_permitted=True,\n    )\n    try:\n        return response.verify()\n    except _RegistrationRejectedException as e:\n        raise RegistrationRejectedException(str(e))\n\n\ndef verify_assertion_response(assertion, *, challenge, user, origin, rp_id):\n    \"\"\"\n    Validates the challenge and assertion information\n    sent from the client during authentication.\n\n    Returns an updated signage count on success.\n    Raises AuthenticationRejectedException on failure.\n    \"\"\"\n    webauthn_users = _get_webauthn_users(user, rp_id=rp_id)\n    cred_ids = [cred.credential_id for cred in webauthn_users]\n    encoded_challenge = _webauthn_b64encode(challenge.encode()).decode()\n\n    for webauthn_user in webauthn_users:\n        response = pywebauthn.WebAuthnAssertionResponse(\n            webauthn_user,\n            assertion,\n            encoded_challenge,\n            origin,\n            allow_credentials=cred_ids,\n        )\n        try:\n            return (webauthn_user.credential_id, response.verify())\n        except _AuthenticationRejectedException:\n            pass\n\n    # If we exit the loop, then we've failed to verify the assertion against\n    # any of the user's WebAuthn credentials. Fail.\n    raise AuthenticationRejectedException(\"Invalid WebAuthn credential\")\n", "path": "warehouse/utils/webauthn.py"}]}