Skip to content

Commit

Permalink
Add tests to ensure no opts parser mutability
Browse files Browse the repository at this point in the history
  • Loading branch information
MasterKale committed Mar 28, 2024
1 parent 434c6bc commit 15f2fbb
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 2 deletions.
32 changes: 31 additions & 1 deletion tests/test_parse_authentication_options.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
from email.mime import base
from unittest import TestCase

from webauthn.helpers import base64url_to_bytes
from webauthn.helpers import base64url_to_bytes, options_to_json
from webauthn.helpers.exceptions import InvalidJSONStructure
from webauthn.helpers.structs import (
AuthenticatorTransport,
PublicKeyCredentialDescriptor,
UserVerificationRequirement,
)
from webauthn.helpers.parse_authentication_options_json import parse_authentication_options_json
from webauthn.authentication.generate_authentication_options import generate_authentication_options


class TestParseAuthenticationOptionsJSON(TestCase):
Expand Down Expand Up @@ -83,6 +84,35 @@ def test_supports_json_string(self) -> None:
self.assertEqual(opts.allow_credentials, [])
self.assertEqual(opts.user_verification, UserVerificationRequirement.PREFERRED)

def test_supports_options_to_json_output(self) -> None:
"""
Test that output from `generate_authentication_options()` that's fed directly into
`options_to_json()` gets parsed back into the original options without any changes along
the way.
"""
opts = generate_authentication_options(
rp_id="example.com",
challenge=b"1234567890",
timeout=12000,
allow_credentials=[
PublicKeyCredentialDescriptor(
id=b"1234567890",
transports=[AuthenticatorTransport.INTERNAL, AuthenticatorTransport.HYBRID],
)
],
user_verification=UserVerificationRequirement.REQUIRED,
)

opts_json = options_to_json(opts)

parsed_opts_json = parse_authentication_options_json(opts_json)

self.assertEqual(parsed_opts_json.rp_id, opts.rp_id)
self.assertEqual(parsed_opts_json.challenge, opts.challenge)
self.assertEqual(parsed_opts_json.allow_credentials, opts.allow_credentials)
self.assertEqual(parsed_opts_json.timeout, opts.timeout)
self.assertEqual(parsed_opts_json.user_verification, opts.user_verification)

def test_raises_on_non_dict_json(self) -> None:
with self.assertRaisesRegex(InvalidJSONStructure, "not a JSON object"):
parse_authentication_options_json("[0]")
Expand Down
46 changes: 45 additions & 1 deletion tests/test_parse_registration_options_json.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from unittest import TestCase

from webauthn.helpers import base64url_to_bytes
from webauthn.helpers import base64url_to_bytes, options_to_json
from webauthn.helpers.exceptions import InvalidJSONStructure
from webauthn.helpers.structs import (
AuthenticatorTransport,
Expand All @@ -16,6 +16,7 @@
)
from webauthn.helpers.cose import COSEAlgorithmIdentifier
from webauthn.helpers.parse_registration_options_json import parse_registration_options_json
from webauthn.registration.generate_registration_options import generate_registration_options


class TestParseRegistrationOptionsJSON(TestCase):
Expand Down Expand Up @@ -221,6 +222,49 @@ def test_supports_json_string(self) -> None:
)
self.assertEqual(parsed.timeout, 60000)

def test_supports_options_to_json_output(self) -> None:
"""
Test that output from `generate_registration_options()` that's fed directly into
`options_to_json()` gets parsed back into the original options without any changes along
the way.
"""
opts = generate_registration_options(
rp_id="example.com",
rp_name="Example Co",
user_id=bytes([1, 2, 3, 4]),
user_name="lee",
user_display_name="Lee",
attestation=AttestationConveyancePreference.DIRECT,
authenticator_selection=AuthenticatorSelectionCriteria(
authenticator_attachment=AuthenticatorAttachment.PLATFORM,
resident_key=ResidentKeyRequirement.REQUIRED,
require_resident_key=True,
user_verification=UserVerificationRequirement.DISCOURAGED,
),
challenge=bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]),
exclude_credentials=[
PublicKeyCredentialDescriptor(
id=b"1234567890",
transports=[AuthenticatorTransport.INTERNAL, AuthenticatorTransport.HYBRID],
),
],
supported_pub_key_algs=[COSEAlgorithmIdentifier.ECDSA_SHA_512],
timeout=12000,
)

opts_json = options_to_json(opts)

parsed_opts_json = parse_registration_options_json(opts_json)

self.assertEqual(parsed_opts_json.rp, opts.rp)
self.assertEqual(parsed_opts_json.user, opts.user)
self.assertEqual(parsed_opts_json.attestation, opts.attestation)
self.assertEqual(parsed_opts_json.authenticator_selection, opts.authenticator_selection)
self.assertEqual(parsed_opts_json.challenge, opts.challenge)
self.assertEqual(parsed_opts_json.exclude_credentials, opts.exclude_credentials)
self.assertEqual(parsed_opts_json.pub_key_cred_params, opts.pub_key_cred_params)
self.assertEqual(parsed_opts_json.timeout, opts.timeout)

def test_raises_on_non_dict_json(self) -> None:
with self.assertRaisesRegex(InvalidJSONStructure, "not a JSON object"):
parse_registration_options_json("[0]")
Expand Down

0 comments on commit 15f2fbb

Please sign in to comment.