Skip to content

Commit

Permalink
Merge pull request #195 from duo-labs/feat/remove-pydantic-dependency
Browse files Browse the repository at this point in the history
feat/remove-pydantic-dependency
  • Loading branch information
MasterKale authored Jan 11, 2024
2 parents eb3b6a3 + 939c486 commit a3fb0a5
Show file tree
Hide file tree
Showing 53 changed files with 1,332 additions and 607 deletions.
4 changes: 4 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# "Run Black over everything"
b134c58a394353e02c4f40808bf104f51578e7df
# "Run Black on setup.py"
64a0579be773f2ac783f8b50f1046fccc09389a8
2 changes: 0 additions & 2 deletions .github/workflows/build_and_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ jobs:
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11']
pydantic-version: ['>=1.0,<2.0', '>=2.0,<3.0']

steps:
- uses: actions/checkout@v3
Expand All @@ -28,7 +27,6 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install 'pydantic${{ matrix.pydantic-version }}'
- name: Test with unittest
run: |
python -m unittest
Expand Down
16 changes: 14 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
{
"black-formatter.args": [
"--line-length", "99"
],
"mypy-type-checker.path": ["venv/bin/mypy"],
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter"
}
"editor.defaultFormatter": "ms-python.black-formatter",
"editor.formatOnPaste": false,
"editor.formatOnSaveMode": "file",
"editor.formatOnSave": true,
},
"python.analysis.typeCheckingMode": "basic",
"gitlens.advanced.blame.customArguments": [
"--ignore-revs-file",
".git-blame-ignore-revs"
]
}
6 changes: 1 addition & 5 deletions examples/authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
base64url_to_bytes,
)
from webauthn.helpers.structs import (
PYDANTIC_V2,
PublicKeyCredentialDescriptor,
UserVerificationRequirement,
)
Expand Down Expand Up @@ -66,8 +65,5 @@
require_user_verification=True,
)
print("\n[Authentication Verification]")
if PYDANTIC_V2:
print(authentication_verification.model_dump_json(indent=2))
else:
print(authentication_verification.json(indent=2))
print(authentication_verification)
assert authentication_verification.new_sign_count == 1
10 changes: 3 additions & 7 deletions examples/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
)
from webauthn.helpers.cose import COSEAlgorithmIdentifier
from webauthn.helpers.structs import (
PYDANTIC_V2,
AttestationConveyancePreference,
AuthenticatorAttachment,
AuthenticatorSelectionCriteria,
Expand Down Expand Up @@ -63,11 +62,11 @@
"response": {
"attestationObject": "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVkBZ0mWDeWIDoxodDQXD2R2YFuP5K65ooYyx5lc87qDHZdjRQAAAAAAAAAAAAAAAAAAAAAAAAAAACBmggo_UlC8p2tiPVtNQ8nZ5NSxst4WS_5fnElA2viTq6QBAwM5AQAgWQEA31dtHqc70D_h7XHQ6V_nBs3Tscu91kBL7FOw56_VFiaKYRH6Z4KLr4J0S12hFJ_3fBxpKfxyMfK66ZMeAVbOl_wemY4S5Xs4yHSWy21Xm_dgWhLJjZ9R1tjfV49kDPHB_ssdvP7wo3_NmoUPYMgK-edgZ_ehttp_I6hUUCnVaTvn_m76b2j9yEPReSwl-wlGsabYG6INUhTuhSOqG-UpVVQdNJVV7GmIPHCA2cQpJBDZBohT4MBGme_feUgm4sgqVCWzKk6CzIKIz5AIVnspLbu05SulAVnSTB3NxTwCLNJR_9v9oSkvphiNbmQBVQH1tV_psyi9HM1Jtj9VJVKMeyFDAQAB",
"clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIiwiY2hhbGxlbmdlIjoiQ2VUV29nbWcwY2NodWlZdUZydjhEWFhkTVpTSVFSVlpKT2dhX3hheVZWRWNCajBDdzN5NzN5aEQ0RmtHU2UtUnJQNmhQSkpBSW0zTFZpZW40aFhFTGciLCJvcmlnaW4iOiJodHRwOi8vbG9jYWxob3N0OjUwMDAiLCJjcm9zc09yaWdpbiI6ZmFsc2V9",
"transports": ["internal"]
"transports": ["internal"],
},
"type": "public-key",
"clientExtensionResults": {},
"authenticatorAttachment": "platform"
"authenticatorAttachment": "platform",
},
expected_challenge=base64url_to_bytes(
"CeTWogmg0cchuiYuFrv8DXXdMZSIQRVZJOga_xayVVEcBj0Cw3y73yhD4FkGSe-RrP6hPJJAIm3LVien4hXELg"
Expand All @@ -78,10 +77,7 @@
)

print("\n[Registration Verification - None]")
if PYDANTIC_V2:
print(registration_verification.model_dump_json(indent=2))
else:
print(registration_verification.json(indent=2))
print(registration_verification)
assert registration_verification.credential_id == base64url_to_bytes(
"ZoIKP1JQvKdrYj1bTUPJ2eTUsbLeFkv-X5xJQNr4k6s"
)
5 changes: 0 additions & 5 deletions mypy.ini
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
[mypy]
plugins = pydantic.mypy

python_version = 3.8

[pydantic-mypy]
init_typed=True

[mypy-asn1crypto.*]
ignore_missing_imports = True

Expand Down
11 changes: 4 additions & 7 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
annotated-types==0.5.0
asn1crypto==1.4.0
black==21.9b0
cbor2==5.4.6
cbor2==5.5.0
cffi==1.15.0
click==8.0.3
cryptography==41.0.4
cryptography==41.0.7
mccabe==0.6.1
mypy==1.4.1
mypy-extensions==1.0.0
pathspec==0.9.0
platformdirs==2.4.0
pycodestyle==2.8.0
pycparser==2.20
pydantic==2.4.2
pydantic_core==2.10.1
pyflakes==2.4.0
pyOpenSSL==23.2.0
pyOpenSSL==23.3.0
regex==2021.10.8
six==1.16.0
toml==0.10.2
tomli==1.2.1
typing_extensions==4.7.1
typing_extensions==4.9.0
48 changes: 23 additions & 25 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,49 +9,47 @@


def read(*parts):
with codecs.open(os.path.join(HERE, *parts), 'r') as fp:
with codecs.open(os.path.join(HERE, *parts), "r") as fp:
return fp.read()


def find_version(*file_paths):
version_file = read(*file_paths)
version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]",
version_file, re.M)
version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", version_file, re.M)
if version_match:
return version_match.group(1)
raise RuntimeError('Unable to find version string.')
raise RuntimeError("Unable to find version string.")


LONG_DESCRIPTION = read('README.md')
VERSION = find_version('webauthn', '__init__.py')
LONG_DESCRIPTION = read("README.md")
VERSION = find_version("webauthn", "__init__.py")


setup(
name='webauthn',
name="webauthn",
packages=find_packages(exclude=["tests"]),
include_package_data=True,
package_data={"webauthn": ["py.typed"]},
version=VERSION,
description='Pythonic WebAuthn',
description="Pythonic WebAuthn",
long_description=LONG_DESCRIPTION,
long_description_content_type='text/markdown',
keywords='webauthn fido2',
author='Duo Labs',
author_email='[email protected]',
url='https://github.com/duo-labs/py_webauthn',
download_url='https://github.com/duo-labs/py_webauthn/archive/{}.tar.gz'.format(VERSION),
license='BSD',
long_description_content_type="text/markdown",
keywords="webauthn fido2",
author="Duo Labs",
author_email="[email protected]",
url="https://github.com/duo-labs/py_webauthn",
download_url="https://github.com/duo-labs/py_webauthn/archive/{}.tar.gz".format(VERSION),
license="BSD",
classifiers=[
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License',
'Programming Language :: Python :: 3'
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: BSD License",
"Programming Language :: Python :: 3",
],
install_requires=[
'asn1crypto>=1.4.0',
'cbor2>=5.4.6',
'cryptography>=41.0.4',
'pydantic>=1.10.11',
'pyOpenSSL>=23.2.0',
]
"asn1crypto>=1.4.0",
"cbor2>=5.4.6",
"cryptography>=41.0.7",
"pyOpenSSL>=23.3.0",
],
)
13 changes: 0 additions & 13 deletions tests/test_bytes_subclass_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,3 @@ def base64url_to_memoryview(data: str) -> memoryview:
)

assert verification.new_sign_count == 7

def test_supports_strings_for_bytes(self) -> None:
"""
Preserve the ability to pass strings for `bytes` fields
"""
response = AuthenticatorAssertionResponse(
authenticator_data=bytes(),
client_data_json=bytes(),
signature=bytes(),
user_handle='some_user_handle_string' # type: ignore
)

self.assertEqual(response.user_handle, b'some_user_handle_string')
12 changes: 4 additions & 8 deletions tests/test_decode_credential_public_key.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,11 @@ def test_decodes_ec2_public_key(self) -> None:
assert decoded.crv == 1
assert (
decoded.x
and bytes_to_base64url(decoded.x)
== "MMcEPFOpY_jJlmcBrnbgvq4-7CGKt5TBEPmxdjpTaDE"
and bytes_to_base64url(decoded.x) == "MMcEPFOpY_jJlmcBrnbgvq4-7CGKt5TBEPmxdjpTaDE"
)
assert (
decoded.y
and bytes_to_base64url(decoded.y)
== "xuwbECbDdNfTTegnc174oYdusZiMmJgct0yI_ulrJGI"
and bytes_to_base64url(decoded.y) == "xuwbECbDdNfTTegnc174oYdusZiMmJgct0yI_ulrJGI"
)

def test_decode_rsa_public_key(self) -> None:
Expand Down Expand Up @@ -62,11 +60,9 @@ def test_decode_uncompressed_ec2_public_key(self) -> None:
assert decoded.crv == 1
assert (
decoded.x
and bytes_to_base64url(decoded.x)
== "FrEpm55XKvkgIN-izKDHBF-VJ09Rw2F5mFOFcJ5MVM0"
and bytes_to_base64url(decoded.x) == "FrEpm55XKvkgIN-izKDHBF-VJ09Rw2F5mFOFcJ5MVM0"
)
assert (
decoded.y
and bytes_to_base64url(decoded.y)
== "o0EM9dj0V-xJ1JwpE2XZ_8NRIt5KVvr71Zl0rB8BWOs"
and bytes_to_base64url(decoded.y) == "o0EM9dj0V-xJ1JwpE2XZ_8NRIt5KVvr71Zl0rB8BWOs"
)
6 changes: 6 additions & 0 deletions tests/test_generate_authentication_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,9 @@ def test_generates_options_with_custom_values(self) -> None:
PublicKeyCredentialDescriptor(id=b"12345"),
]
assert options.user_verification == UserVerificationRequirement.REQUIRED

def test_raises_on_empty_rp_id(self) -> None:
with self.assertRaisesRegex(ValueError, "rp_id"):
generate_authentication_options(
rp_id="",
)
44 changes: 38 additions & 6 deletions tests/test_generate_registration_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,7 @@ def test_generates_options_with_custom_values(self) -> None:
timeout=120000,
)

assert options.rp == PublicKeyCredentialRpEntity(
id="example.com", name="Example Co"
)
assert options.rp == PublicKeyCredentialRpEntity(id="example.com", name="Example Co")
assert options.challenge == b"1234567890"
assert options.user == PublicKeyCredentialUserEntity(
id=b"ABAV6QWPBEY9WOTOA1A4",
Expand All @@ -80,12 +78,46 @@ def test_generates_options_with_custom_values(self) -> None:
alg=COSEAlgorithmIdentifier.ECDSA_SHA_512,
)
assert options.timeout == 120000
assert options.exclude_credentials == [
PublicKeyCredentialDescriptor(id=b"1234567890")
]
assert options.exclude_credentials == [PublicKeyCredentialDescriptor(id=b"1234567890")]
assert options.authenticator_selection == AuthenticatorSelectionCriteria(
authenticator_attachment=AuthenticatorAttachment.PLATFORM,
resident_key=ResidentKeyRequirement.REQUIRED,
require_resident_key=True,
)
assert options.attestation == AttestationConveyancePreference.DIRECT

def test_raises_on_empty_rp_id(self) -> None:
with self.assertRaisesRegex(ValueError, "rp_id"):
generate_registration_options(
rp_id="",
rp_name="Example Co",
user_id="blah",
user_name="blah",
)

def test_raises_on_empty_rp_name(self) -> None:
with self.assertRaisesRegex(ValueError, "rp_name"):
generate_registration_options(
rp_id="example.com",
rp_name="",
user_id="blah",
user_name="blah",
)

def test_raises_on_empty_user_id(self) -> None:
with self.assertRaisesRegex(ValueError, "user_id"):
generate_registration_options(
rp_id="example.com",
rp_name="Example Co",
user_id="",
user_name="blah",
)

def test_raises_on_empty_user_name(self) -> None:
with self.assertRaisesRegex(ValueError, "user_name"):
generate_registration_options(
rp_id="example.com",
rp_name="Example Co",
user_id="blah",
user_name="",
)
Loading

0 comments on commit a3fb0a5

Please sign in to comment.