We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Webauthn allows me to register my phone as security key but not login with it
<!--
    NOTE: This issue should be for problems with PyPI itself, including:
    * pypi.org
    * test.pypi.org
    * files.pythonhosted.org

    This issue should NOT be for a project installed from PyPI. If you are
    having an issue with a specific package, you should reach out to the
    maintainers of that project directly instead.

    Furthermore, this issue should NOT be for any non-PyPI properties (like
    python.org, docs.python.org, etc.)

    If your problem is related to search (a new or updated project doesn't
    appear in the PyPI search results), please wait for a couple of hours
    and check again before reporting it. The search index may take some
    time to be updated.
-->

**Describe the bug**
Webauthn allows me to register my phone as security key but not login with it

**Expected behavior**
After closing the native is security key prompt, A chrome prompt like this should pop up and allows me to select my phone to use as a security key
![ss](https://user-images.githubusercontent.com/62752664/220800866-232ebbed-8b27-4805-a4d9-210b3349b3c6.png)


**To Reproduce**
Add a android phone as a security key by visiting your profile and clicking add security key and follow the expected behavior
Then logout and try to login with the same expected behaviour

**My Platform**
Windows 10 and chrome version Version 110.0.5481.177 (Official Build) (64-bit)

**Additional context**
None


--- 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 json
15 
16 import webauthn as pywebauthn
17 
18 from webauthn.helpers import base64url_to_bytes, generate_challenge
19 from webauthn.helpers.exceptions import (
20     InvalidAuthenticationResponse,
21     InvalidRegistrationResponse,
22 )
23 from webauthn.helpers.options_to_json import options_to_json
24 from webauthn.helpers.structs import (
25     AttestationConveyancePreference,
26     AuthenticationCredential,
27     AuthenticatorSelectionCriteria,
28     AuthenticatorTransport,
29     PublicKeyCredentialDescriptor,
30     RegistrationCredential,
31     UserVerificationRequirement,
32 )
33 
34 
35 class AuthenticationRejectedError(Exception):
36     pass
37 
38 
39 class RegistrationRejectedError(Exception):
40     pass
41 
42 
43 def _get_webauthn_user_public_key_credential_descriptors(user, *, rp_id):
44     """
45     Returns a webauthn.WebAuthnUser instance corresponding
46     to the given user model, with properties suitable for
47     usage within the webauthn API.
48     """
49     return [
50         PublicKeyCredentialDescriptor(
51             id=base64url_to_bytes(credential.credential_id),
52             transports=[
53                 AuthenticatorTransport.USB,
54                 AuthenticatorTransport.NFC,
55                 AuthenticatorTransport.BLE,
56                 AuthenticatorTransport.INTERNAL,
57             ],
58         )
59         for credential in user.webauthn
60     ]
61 
62 
63 def _get_webauthn_user_public_keys(user, *, rp_id):
64     return [
65         (
66             base64url_to_bytes(credential.public_key),
67             credential.sign_count,
68         )
69         for credential in user.webauthn
70     ]
71 
72 
73 def _webauthn_b64encode(source):
74     return base64.urlsafe_b64encode(source).rstrip(b"=")
75 
76 
77 def generate_webauthn_challenge():
78     """
79     Returns a random challenge suitable for use within
80     Webauthn's credential and configuration option objects.
81 
82     See: https://w3c.github.io/webauthn/#cryptographic-challenges
83     """
84     return generate_challenge()
85 
86 
87 def get_credential_options(user, *, challenge, rp_name, rp_id):
88     """
89     Returns a dictionary of options for credential creation
90     on the client side.
91     """
92     _authenticator_selection = AuthenticatorSelectionCriteria()
93     _authenticator_selection.user_verification = UserVerificationRequirement.DISCOURAGED
94     options = pywebauthn.generate_registration_options(
95         rp_id=rp_id,
96         rp_name=rp_name,
97         user_id=str(user.id),
98         user_name=user.username,
99         user_display_name=user.name or user.username,
100         challenge=challenge,
101         attestation=AttestationConveyancePreference.NONE,
102         authenticator_selection=_authenticator_selection,
103     )
104     return json.loads(options_to_json(options))
105 
106 
107 def get_assertion_options(user, *, challenge, rp_id):
108     """
109     Returns a dictionary of options for assertion retrieval
110     on the client side.
111     """
112     options = pywebauthn.generate_authentication_options(
113         rp_id=rp_id,
114         challenge=challenge,
115         allow_credentials=_get_webauthn_user_public_key_credential_descriptors(
116             user, rp_id=rp_id
117         ),
118         user_verification=UserVerificationRequirement.DISCOURAGED,
119     )
120     return json.loads(options_to_json(options))
121 
122 
123 def verify_registration_response(response, challenge, *, rp_id, origin):
124     """
125     Validates the challenge and attestation information
126     sent from the client during device registration.
127 
128     Returns a WebAuthnCredential on success.
129     Raises RegistrationRejectedError on failire.
130     """
131     # NOTE: We re-encode the challenge below, because our
132     # response's clientData.challenge is encoded twice:
133     # first for the entire clientData payload, and then again
134     # for the individual challenge.
135     encoded_challenge = _webauthn_b64encode(challenge)
136     try:
137         _credential = RegistrationCredential.parse_raw(response)
138         return pywebauthn.verify_registration_response(
139             credential=_credential,
140             expected_challenge=encoded_challenge,
141             expected_rp_id=rp_id,
142             expected_origin=origin,
143             require_user_verification=False,
144         )
145     except InvalidRegistrationResponse as e:
146         raise RegistrationRejectedError(str(e))
147 
148 
149 def verify_assertion_response(assertion, *, challenge, user, origin, rp_id):
150     """
151     Validates the challenge and assertion information
152     sent from the client during authentication.
153 
154     Returns an updated signage count on success.
155     Raises AuthenticationRejectedError on failure.
156     """
157     # NOTE: We re-encode the challenge below, because our
158     # response's clientData.challenge is encoded twice:
159     # first for the entire clientData payload, and then again
160     # for the individual challenge.
161     encoded_challenge = _webauthn_b64encode(challenge)
162     webauthn_user_public_keys = _get_webauthn_user_public_keys(user, rp_id=rp_id)
163 
164     for public_key, current_sign_count in webauthn_user_public_keys:
165         try:
166             _credential = AuthenticationCredential.parse_raw(assertion)
167             return pywebauthn.verify_authentication_response(
168                 credential=_credential,
169                 expected_challenge=encoded_challenge,
170                 expected_rp_id=rp_id,
171                 expected_origin=origin,
172                 credential_public_key=public_key,
173                 credential_current_sign_count=current_sign_count,
174                 require_user_verification=False,
175             )
176         except InvalidAuthenticationResponse:
177             pass
178 
179     # If we exit the loop, then we've failed to verify the assertion against
180     # any of the user's WebAuthn credentials. Fail.
181     raise AuthenticationRejectedError("Invalid WebAuthn credential")
182
```
--- 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
@@ -25,7 +25,6 @@
     AttestationConveyancePreference,
     AuthenticationCredential,
     AuthenticatorSelectionCriteria,
-    AuthenticatorTransport,
     PublicKeyCredentialDescriptor,
     RegistrationCredential,
     UserVerificationRequirement,
@@ -47,15 +46,7 @@
     usage within the webauthn API.
     """
     return [
-        PublicKeyCredentialDescriptor(
-            id=base64url_to_bytes(credential.credential_id),
-            transports=[
-                AuthenticatorTransport.USB,
-                AuthenticatorTransport.NFC,
-                AuthenticatorTransport.BLE,
-                AuthenticatorTransport.INTERNAL,
-            ],
-        )
+        PublicKeyCredentialDescriptor(id=base64url_to_bytes(credential.credential_id))
         for credential in user.webauthn
     ]

{"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@@ -25,7 +25,6 @@\n     AttestationConveyancePreference,\n     AuthenticationCredential,\n     AuthenticatorSelectionCriteria,\n-    AuthenticatorTransport,\n     PublicKeyCredentialDescriptor,\n     RegistrationCredential,\n     UserVerificationRequirement,\n@@ -47,15 +46,7 @@\n     usage within the webauthn API.\n     \"\"\"\n     return [\n-        PublicKeyCredentialDescriptor(\n-            id=base64url_to_bytes(credential.credential_id),\n-            transports=[\n-                AuthenticatorTransport.USB,\n-                AuthenticatorTransport.NFC,\n-                AuthenticatorTransport.BLE,\n-                AuthenticatorTransport.INTERNAL,\n-            ],\n-        )\n+        PublicKeyCredentialDescriptor(id=base64url_to_bytes(credential.credential_id))\n         for credential in user.webauthn\n     ]\n", "issue": "Webauthn allows me to register my phone as security key but not login with it\n<!--\r\n    NOTE: This issue should be for problems with PyPI itself, including:\r\n    * pypi.org\r\n    * test.pypi.org\r\n    * files.pythonhosted.org\r\n\r\n    This issue should NOT be for a project installed from PyPI. If you are\r\n    having an issue with a specific package, you should reach out to the\r\n    maintainers of that project directly instead.\r\n\r\n    Furthermore, this issue should NOT be for any non-PyPI properties (like\r\n    python.org, docs.python.org, etc.)\r\n\r\n    If your problem is related to search (a new or updated project doesn't\r\n    appear in the PyPI search results), please wait for a couple of hours\r\n    and check again before reporting it. The search index may take some\r\n    time to be updated.\r\n-->\r\n\r\n**Describe the bug**\r\nWebauthn allows me to register my phone as security key but not login with it\r\n\r\n**Expected behavior**\r\nAfter closing the native is security key prompt, A chrome prompt like this should pop up and allows me to select my phone to use as a security key\r\n![ss](https://user-images.githubusercontent.com/62752664/220800866-232ebbed-8b27-4805-a4d9-210b3349b3c6.png)\r\n\r\n\r\n**To Reproduce**\r\nAdd a android phone as a security key by visiting your profile and clicking add security key and follow the expected behavior\r\nThen logout and try to login with the same expected behaviour\r\n\r\n**My Platform**\r\nWindows 10 and chrome version Version 110.0.5481.177 (Official Build) (64-bit)\r\n\r\n**Additional context**\r\nNone\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 json\n\nimport webauthn as pywebauthn\n\nfrom webauthn.helpers import base64url_to_bytes, generate_challenge\nfrom webauthn.helpers.exceptions import (\n    InvalidAuthenticationResponse,\n    InvalidRegistrationResponse,\n)\nfrom webauthn.helpers.options_to_json import options_to_json\nfrom webauthn.helpers.structs import (\n    AttestationConveyancePreference,\n    AuthenticationCredential,\n    AuthenticatorSelectionCriteria,\n    AuthenticatorTransport,\n    PublicKeyCredentialDescriptor,\n    RegistrationCredential,\n    UserVerificationRequirement,\n)\n\n\nclass AuthenticationRejectedError(Exception):\n    pass\n\n\nclass RegistrationRejectedError(Exception):\n    pass\n\n\ndef _get_webauthn_user_public_key_credential_descriptors(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        PublicKeyCredentialDescriptor(\n            id=base64url_to_bytes(credential.credential_id),\n            transports=[\n                AuthenticatorTransport.USB,\n                AuthenticatorTransport.NFC,\n                AuthenticatorTransport.BLE,\n                AuthenticatorTransport.INTERNAL,\n            ],\n        )\n        for credential in user.webauthn\n    ]\n\n\ndef _get_webauthn_user_public_keys(user, *, rp_id):\n    return [\n        (\n            base64url_to_bytes(credential.public_key),\n            credential.sign_count,\n        )\n        for credential in user.webauthn\n    ]\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    return generate_challenge()\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    _authenticator_selection = AuthenticatorSelectionCriteria()\n    _authenticator_selection.user_verification = UserVerificationRequirement.DISCOURAGED\n    options = pywebauthn.generate_registration_options(\n        rp_id=rp_id,\n        rp_name=rp_name,\n        user_id=str(user.id),\n        user_name=user.username,\n        user_display_name=user.name or user.username,\n        challenge=challenge,\n        attestation=AttestationConveyancePreference.NONE,\n        authenticator_selection=_authenticator_selection,\n    )\n    return json.loads(options_to_json(options))\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.generate_authentication_options(\n        rp_id=rp_id,\n        challenge=challenge,\n        allow_credentials=_get_webauthn_user_public_key_credential_descriptors(\n            user, rp_id=rp_id\n        ),\n        user_verification=UserVerificationRequirement.DISCOURAGED,\n    )\n    return json.loads(options_to_json(options))\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 RegistrationRejectedError 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)\n    try:\n        _credential = RegistrationCredential.parse_raw(response)\n        return pywebauthn.verify_registration_response(\n            credential=_credential,\n            expected_challenge=encoded_challenge,\n            expected_rp_id=rp_id,\n            expected_origin=origin,\n            require_user_verification=False,\n        )\n    except InvalidRegistrationResponse as e:\n        raise RegistrationRejectedError(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 AuthenticationRejectedError on failure.\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)\n    webauthn_user_public_keys = _get_webauthn_user_public_keys(user, rp_id=rp_id)\n\n    for public_key, current_sign_count in webauthn_user_public_keys:\n        try:\n            _credential = AuthenticationCredential.parse_raw(assertion)\n            return pywebauthn.verify_authentication_response(\n                credential=_credential,\n                expected_challenge=encoded_challenge,\n                expected_rp_id=rp_id,\n                expected_origin=origin,\n                credential_public_key=public_key,\n                credential_current_sign_count=current_sign_count,\n                require_user_verification=False,\n            )\n        except InvalidAuthenticationResponse:\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 AuthenticationRejectedError(\"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 json\n\nimport webauthn as pywebauthn\n\nfrom webauthn.helpers import base64url_to_bytes, generate_challenge\nfrom webauthn.helpers.exceptions import (\n    InvalidAuthenticationResponse,\n    InvalidRegistrationResponse,\n)\nfrom webauthn.helpers.options_to_json import options_to_json\nfrom webauthn.helpers.structs import (\n    AttestationConveyancePreference,\n    AuthenticationCredential,\n    AuthenticatorSelectionCriteria,\n    PublicKeyCredentialDescriptor,\n    RegistrationCredential,\n    UserVerificationRequirement,\n)\n\n\nclass AuthenticationRejectedError(Exception):\n    pass\n\n\nclass RegistrationRejectedError(Exception):\n    pass\n\n\ndef _get_webauthn_user_public_key_credential_descriptors(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        PublicKeyCredentialDescriptor(id=base64url_to_bytes(credential.credential_id))\n        for credential in user.webauthn\n    ]\n\n\ndef _get_webauthn_user_public_keys(user, *, rp_id):\n    return [\n        (\n            base64url_to_bytes(credential.public_key),\n            credential.sign_count,\n        )\n        for credential in user.webauthn\n    ]\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    return generate_challenge()\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    _authenticator_selection = AuthenticatorSelectionCriteria()\n    _authenticator_selection.user_verification = UserVerificationRequirement.DISCOURAGED\n    options = pywebauthn.generate_registration_options(\n        rp_id=rp_id,\n        rp_name=rp_name,\n        user_id=str(user.id),\n        user_name=user.username,\n        user_display_name=user.name or user.username,\n        challenge=challenge,\n        attestation=AttestationConveyancePreference.NONE,\n        authenticator_selection=_authenticator_selection,\n    )\n    return json.loads(options_to_json(options))\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.generate_authentication_options(\n        rp_id=rp_id,\n        challenge=challenge,\n        allow_credentials=_get_webauthn_user_public_key_credential_descriptors(\n            user, rp_id=rp_id\n        ),\n        user_verification=UserVerificationRequirement.DISCOURAGED,\n    )\n    return json.loads(options_to_json(options))\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 RegistrationRejectedError 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)\n    try:\n        _credential = RegistrationCredential.parse_raw(response)\n        return pywebauthn.verify_registration_response(\n            credential=_credential,\n            expected_challenge=encoded_challenge,\n            expected_rp_id=rp_id,\n            expected_origin=origin,\n            require_user_verification=False,\n        )\n    except InvalidRegistrationResponse as e:\n        raise RegistrationRejectedError(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 AuthenticationRejectedError on failure.\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)\n    webauthn_user_public_keys = _get_webauthn_user_public_keys(user, rp_id=rp_id)\n\n    for public_key, current_sign_count in webauthn_user_public_keys:\n        try:\n            _credential = AuthenticationCredential.parse_raw(assertion)\n            return pywebauthn.verify_authentication_response(\n                credential=_credential,\n                expected_challenge=encoded_challenge,\n                expected_rp_id=rp_id,\n                expected_origin=origin,\n                credential_public_key=public_key,\n                credential_current_sign_count=current_sign_count,\n                require_user_verification=False,\n            )\n        except InvalidAuthenticationResponse:\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 AuthenticationRejectedError(\"Invalid WebAuthn credential\")\n", "path": "warehouse/utils/webauthn.py"}]}